diff options
Diffstat (limited to 'libbb')
-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 000000000..dadadbafe --- /dev/null +++ b/libbb/in_ether.c | |||
@@ -0,0 +1,58 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | ||
2 | /* | ||
3 | * Utility routines. | ||
4 | */ | ||
5 | |||
6 | //kbuild:lib-$(CONFIG_IFCONFIG) += in_ether.o | ||
7 | //kbuild:lib-$(CONFIG_IFENSLAVE) += in_ether.o | ||
8 | |||
9 | #include "libbb.h" | ||
10 | #include <net/if_arp.h> | ||
11 | #include <net/ethernet.h> | ||
12 | |||
13 | /* Convert Ethernet address from "XX[:]XX[:]XX[:]XX[:]XX[:]XX" to sockaddr. | ||
14 | * Return nonzero on error. | ||
15 | */ | ||
16 | int FAST_FUNC in_ether(const char *bufp, struct sockaddr *sap) | ||
17 | { | ||
18 | char *ptr; | ||
19 | int i, j; | ||
20 | unsigned char val; | ||
21 | unsigned char c; | ||
22 | |||
23 | sap->sa_family = ARPHRD_ETHER; | ||
24 | ptr = (char *) sap->sa_data; | ||
25 | |||
26 | i = ETH_ALEN; | ||
27 | goto first; | ||
28 | do { | ||
29 | /* We might get a semicolon here */ | ||
30 | if (*bufp == ':') | ||
31 | bufp++; | ||
32 | first: | ||
33 | j = val = 0; | ||
34 | do { | ||
35 | c = *bufp; | ||
36 | if (((unsigned char)(c - '0')) <= 9) { | ||
37 | c -= '0'; | ||
38 | } else if ((unsigned char)((c|0x20) - 'a') <= 5) { | ||
39 | c = (unsigned char)((c|0x20) - 'a') + 10; | ||
40 | } else { | ||
41 | if (j && (c == ':' || c == '\0')) | ||
42 | /* One-digit byte: __:X:__ */ | ||
43 | break; | ||
44 | return -1; | ||
45 | } | ||
46 | ++bufp; | ||
47 | val <<= 4; | ||
48 | val += c; | ||
49 | j ^= 1; | ||
50 | } while (j); | ||
51 | |||
52 | *ptr++ = val; | ||
53 | |||
54 | } while (--i); | ||
55 | |||
56 | /* Error if we aren't at end of string */ | ||
57 | return *bufp; | ||
58 | } | ||