Commit | Line | Data |
---|---|---|
e48725fe KB |
1 | /*- |
2 | * Copyright (c) 1990 The Regents of the University of California. | |
3 | * All rights reserved. | |
4 | * | |
5 | * %sccs.include.redist.c% | |
6 | */ | |
7 | ||
8 | #if defined(LIBC_SCCS) && !defined(lint) | |
24fac7d8 | 9 | static char sccsid[] = "@(#)linkaddr.c 5.2 (Berkeley) %G%"; |
e48725fe KB |
10 | #endif /* LIBC_SCCS and not lint */ |
11 | ||
12 | #include <sys/types.h> | |
13 | #include <sys/socket.h> | |
14 | #include <net/if_dl.h> | |
24fac7d8 | 15 | #include <string.h> |
e48725fe KB |
16 | |
17 | /* States*/ | |
18 | #define NAMING 0 | |
19 | #define GOTONE 1 | |
20 | #define GOTTWO 2 | |
21 | #define RESET 3 | |
22 | /* Inputs */ | |
23 | #define DIGIT (4*0) | |
24 | #define END (4*1) | |
25 | #define DELIM (4*2) | |
26 | #define LETTER (4*3) | |
27 | ||
24fac7d8 | 28 | void |
e48725fe | 29 | link_addr(addr, sdl) |
24fac7d8 KB |
30 | register const char *addr; |
31 | register struct sockaddr_dl *sdl; | |
e48725fe KB |
32 | { |
33 | register char *cp = sdl->sdl_data; | |
34 | char *cplim = sdl->sdl_len + (char *)sdl; | |
35 | register int byte = 0, state = NAMING, new; | |
36 | ||
37 | bzero((char *)&sdl->sdl_family, sdl->sdl_len - 1); | |
38 | sdl->sdl_family = AF_LINK; | |
39 | do { | |
40 | state &= ~LETTER; | |
41 | if ((*addr >= '0') && (*addr <= '9')) { | |
42 | new = *addr - '0'; | |
43 | } else if ((*addr >= 'a') && (*addr <= 'f')) { | |
44 | new = *addr - 'a' + 10; | |
45 | } else if ((*addr >= 'A') && (*addr <= 'F')) { | |
46 | new = *addr - 'A' + 10; | |
47 | } else if (*addr == 0) { | |
48 | state |= END; | |
49 | } else if (state == NAMING && | |
50 | (((*addr >= 'A') && (*addr <= 'Z')) || | |
51 | ((*addr >= 'a') && (*addr <= 'z')))) | |
52 | state |= LETTER; | |
53 | else | |
54 | state |= DELIM; | |
55 | addr++; | |
56 | switch (state /* | INPUT */) { | |
57 | case NAMING | DIGIT: | |
58 | case NAMING | LETTER: | |
59 | *cp++ = addr[-1]; continue; | |
60 | case NAMING | DELIM: | |
61 | state = RESET; sdl->sdl_nlen = cp - sdl->sdl_data; continue; | |
62 | case GOTTWO | DIGIT: | |
63 | *cp++ = byte; /*FALLTHROUGH*/ | |
64 | case RESET | DIGIT: | |
65 | state = GOTONE; byte = new; continue; | |
66 | case GOTONE | DIGIT: | |
67 | state = GOTTWO; byte = new + (byte << 4); continue; | |
68 | default: /* | DELIM */ | |
69 | state = RESET; *cp++ = byte; byte = 0; continue; | |
70 | case GOTONE | END: | |
71 | case GOTTWO | END: | |
72 | *cp++ = byte; /* FALLTHROUGH */ | |
73 | case RESET | END: | |
74 | break; | |
75 | } | |
76 | break; | |
77 | } while (cp < cplim); | |
78 | sdl->sdl_alen = cp - LLADDR(sdl); | |
79 | new = cp - (char *)sdl; | |
80 | if (new > sizeof(*sdl)) | |
81 | sdl->sdl_len = new; | |
82 | return; | |
83 | } | |
84 | ||
85 | static char hexlist[] = "0123456789abcdef"; | |
86 | ||
87 | char * | |
88 | link_ntoa(sdl) | |
24fac7d8 | 89 | register const struct sockaddr_dl *sdl; |
e48725fe KB |
90 | { |
91 | static char obuf[64]; | |
92 | register char *out = obuf; | |
93 | register int i; | |
94 | register u_char *in = (u_char *)LLADDR(sdl); | |
95 | u_char *inlim = in + sdl->sdl_nlen; | |
96 | int firsttime = 1; | |
97 | ||
98 | if (sdl->sdl_nlen) { | |
99 | bcopy(sdl->sdl_data, obuf, sdl->sdl_nlen); | |
100 | out += sdl->sdl_nlen; | |
101 | *out++ = ':'; | |
102 | } | |
103 | while (in < inlim) { | |
104 | if (firsttime) firsttime = 0; else *out++ = '.'; | |
105 | i = *in++; | |
106 | if (i > 0xf) { | |
107 | out[1] = hexlist[i & 0xf]; | |
108 | i >>= 4; | |
109 | out[0] = hexlist[i]; | |
110 | out += 2; | |
111 | } else | |
112 | *out++ = hexlist[i]; | |
113 | } | |
114 | *out = 0; | |
115 | return(obuf); | |
116 | } |