| /* vi: set sw=4 ts=4: */ |
| /* |
| * Utility routines. |
| */ |
| //kbuild:lib-$(CONFIG_ARP) += in_ether.o |
| //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; |
| } |