diff options
Diffstat (limited to 'libbb/in_ether.c')
-rw-r--r-- | libbb/in_ether.c | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/libbb/in_ether.c b/libbb/in_ether.c new file mode 100644 index 0000000..dadadba --- /dev/null +++ b/libbb/in_ether.c @@ -0,0 +1,58 @@ +/* vi: set sw=4 ts=4: */ +/* + * Utility routines. + */ + +//kbuild:lib-$(CONFIG_IFCONFIG) += in_ether.o +//kbuild:lib-$(CONFIG_IFENSLAVE) += in_ether.o + +#include "libbb.h" +#include <net/if_arp.h> +#include <net/ethernet.h> + +/* Convert Ethernet address from "XX[:]XX[:]XX[:]XX[:]XX[:]XX" to sockaddr. + * Return nonzero on error. + */ +int FAST_FUNC in_ether(const char *bufp, struct sockaddr *sap) +{ + char *ptr; + int i, j; + unsigned char val; + unsigned char c; + + sap->sa_family = ARPHRD_ETHER; + ptr = (char *) sap->sa_data; + + i = ETH_ALEN; + goto first; + do { + /* We might get a semicolon here */ + if (*bufp == ':') + bufp++; + first: + j = val = 0; + do { + c = *bufp; + if (((unsigned char)(c - '0')) <= 9) { + c -= '0'; + } else if ((unsigned char)((c|0x20) - 'a') <= 5) { + c = (unsigned char)((c|0x20) - 'a') + 10; + } else { + if (j && (c == ':' || c == '\0')) + /* One-digit byte: __:X:__ */ + break; + return -1; + } + ++bufp; + val <<= 4; + val += c; + j ^= 1; + } while (j); + + *ptr++ = val; + + } while (--i); + + /* Error if we aren't at end of string */ + return *bufp; +} |