]> git.puffer.fish Git - matthieu/frr.git/commitdiff
lib: add string to macaddress and reverse function
authorPhilippe Guibert <philippe.guibert@6wind.com>
Wed, 1 Feb 2017 17:26:34 +0000 (18:26 +0100)
committerPhilippe Guibert <philippe.guibert@6wind.com>
Tue, 14 Feb 2017 12:58:59 +0000 (13:58 +0100)
As mac-address structure is to be used as a prefix field, two new
functions permit handling mac address in order to convert it. either
from string to internal value, or the reverse operation.
Internal representation of a mac address is a 6 byte char value standing
for the 6 byte value the mac address has.

Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
lib/prefix.c
lib/prefix.h

index 1b168abedcb4b7805a3c9f906671dc2dec1135b1..75879b5c51e747c9e959403ac3d80aaa3894be3f 100644 (file)
@@ -1023,3 +1023,118 @@ inet6_ntoa (struct in6_addr addr)
   inet_ntop (AF_INET6, &addr, buf, INET6_ADDRSTRLEN);
   return buf;
 }
+
+
+static uint8_t convertchartohexa(uint8_t * hexa, int *error)
+{
+  if ((*hexa == '0') || (*hexa == '1') || (*hexa == '2') ||
+      (*hexa == '3') || (*hexa == '4') || (*hexa == '5') ||
+      (*hexa == '6') || (*hexa == '7') || (*hexa == '8')
+      || (*hexa == '9'))
+    return (uint8_t) (*hexa) - '0';
+  if ((*hexa == 'a') || (*hexa == 'A'))
+    return 0xa;
+  if ((*hexa == 'b') || (*hexa == 'B'))
+    return 0xb;
+  if ((*hexa == 'c') || (*hexa == 'C'))
+    return 0xc;
+  if ((*hexa == 'd') || (*hexa == 'D'))
+    return 0xd;
+  if ((*hexa == 'e') || (*hexa == 'E'))
+    return 0xe;
+  if ((*hexa == 'f') || (*hexa == 'F'))
+    return 0xf;
+  *error = -1;
+  return 0;
+}
+
+/* converts to internal representation of mac address
+ * returns 1 on success, 0 otherwise 
+ * format accepted: AA:BB:CC:DD:EE:FF
+ * if mac parameter is null, then check only
+ */
+int str2mac(const char *str, char *mac)
+{
+  unsigned int k = 0, i, j;
+  uint8_t *ptr, *ptr2;
+  size_t len;
+  uint8_t car;
+  
+  if (!str)
+    return 0;
+  
+  if (str[0] == ':' && str[1] == '\0')
+    return 1;
+  
+  i = 0;
+  ptr = (uint8_t *) str;
+  while (i < 6) {
+    uint8_t temp[5];
+    int error = 0;
+    ptr2 = (uint8_t *) strchr((const char *)ptr, ':');
+    if (ptr2 == NULL) {
+      /* if last occurence return ok */
+      if (i != 5) {
+        zlog_err("[%s]: format non recognized", mac);
+        return 0;
+      }
+      len = strlen((char *)ptr);
+    } else {
+      len = ptr2 - ptr;
+    }
+    if (len > 5) {
+      zlog_err("[%s]: format non recognized", mac);
+      return 0;
+    }
+    memcpy(temp, ptr, len);
+    for (j = 0; j < len; j++) {
+      if (k >= ETHER_ADDR_LEN)
+        return 0;
+      if (mac)
+        mac[k] = 0;
+      car = convertchartohexa(&temp[j], &error);
+      if (error)
+        return 0;
+      if (mac)
+        mac[k] = car << 4;
+      j++;
+      if (j == len)
+        return 0;
+      car = convertchartohexa(&temp[j], &error) & 0xf;
+      if (error)
+        return 0;
+      if (mac)
+        mac[k] |= car & 0xf;
+      k++;
+      i++;
+    }
+    ptr = ptr2;
+    if (ptr == NULL)
+      break;
+    ptr++;
+  }
+  if (mac && 0) {
+    zlog_err("leave correct : %02x:%02x:%02x:%02x:%02x:%02x",
+             mac[0] & 0xff, mac[1] & 0xff, mac[2] & 0xff,
+             mac[3] & 0xff, mac[4] & 0xff, mac[5] & 0xff);
+  }
+  return 1;
+}
+
+char *mac2str(char *mac, char *buf, int size)
+{
+  char *ptr;
+  
+  assert (size > ETHER_ADDR_STRLEN);
+  if (!mac)
+    return NULL;
+  if (!buf)
+    ptr = (char *)XMALLOC(MTYPE_TMP, ETHER_ADDR_STRLEN* sizeof(char));
+  else
+    ptr = buf;
+  snprintf(ptr, (ETHER_ADDR_STRLEN),
+           "%02x:%02x:%02x:%02x:%02x:%02x", (uint8_t) mac[0],
+           (uint8_t) mac[1], (uint8_t) mac[2], (uint8_t) mac[3],
+           (uint8_t) mac[4], (uint8_t) mac[5]);
+  return ptr;
+}
index 472dc1a01ac189069466e9df427f10370ce6b4b3..53cf9208e5d26da9e5a1f5db182605a07828218b 100644 (file)
 #include "sockunion.h"
 
 #ifndef ETHER_ADDR_LEN
+#ifdef ETHERADDRL
 #define ETHER_ADDR_LEN  ETHERADDRL
+#else
+#define ETHER_ADDR_LEN 6
+#endif
 #endif
 
+#define ETHER_ADDR_STRLEN (3*ETHER_ADDR_LEN)
 /*
  * there isn't a portable ethernet address type. We define our
  * own to simplify internal handling
@@ -322,6 +327,9 @@ extern void masklen2ip6 (const int, struct in6_addr *);
 
 extern const char *inet6_ntoa (struct in6_addr);
 
+extern int str2mac(const char *str, char *mac);
+extern char *mac2str(char *mac, char *buf, int size);
+
 static inline int ipv6_martian (struct in6_addr *addr)
 {
   struct in6_addr localhost_addr;