From: Philippe Guibert Date: Wed, 1 Feb 2017 17:26:34 +0000 (+0100) Subject: lib: add string to macaddress and reverse function X-Git-Tag: frr-3.0-branchpoint~29^2~21 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=c215ecaf837f770f401b949a021c9e0f09421a37;p=matthieu%2Ffrr.git lib: add string to macaddress and reverse function 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 --- diff --git a/lib/prefix.c b/lib/prefix.c index 1b168abedc..75879b5c51 100644 --- a/lib/prefix.c +++ b/lib/prefix.c @@ -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; +} diff --git a/lib/prefix.h b/lib/prefix.h index 472dc1a01a..53cf9208e5 100644 --- a/lib/prefix.h +++ b/lib/prefix.h @@ -35,9 +35,14 @@ #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;