Annotation of src/lib/libc/net/linkaddr.c, Revision 1.16
1.16 ! matt 1: /* $NetBSD: linkaddr.c,v 1.15 2012/03/13 21:13:41 christos Exp $ */
1.5 cgd 2:
1.1 cgd 3: /*-
1.5 cgd 4: * Copyright (c) 1990, 1993
5: * The Regents of the University of California. All rights reserved.
1.1 cgd 6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
1.13 agc 15: * 3. Neither the name of the University nor the names of its contributors
1.1 cgd 16: * may be used to endorse or promote products derived from this software
17: * without specific prior written permission.
18: *
19: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29: * SUCH DAMAGE.
30: */
31:
1.6 christos 32: #include <sys/cdefs.h>
1.1 cgd 33: #if defined(LIBC_SCCS) && !defined(lint)
1.5 cgd 34: #if 0
35: static char sccsid[] = "@(#)linkaddr.c 8.1 (Berkeley) 6/4/93";
36: #else
1.16 ! matt 37: __RCSID("$NetBSD: linkaddr.c,v 1.15 2012/03/13 21:13:41 christos Exp $");
1.5 cgd 38: #endif
1.1 cgd 39: #endif /* LIBC_SCCS and not lint */
40:
41: #include <sys/types.h>
42: #include <sys/socket.h>
43: #include <net/if_dl.h>
1.10 lukem 44:
45: #include <assert.h>
1.1 cgd 46: #include <string.h>
47:
48: /* States*/
49: #define NAMING 0
50: #define GOTONE 1
51: #define GOTTWO 2
52: #define RESET 3
53: /* Inputs */
54: #define DIGIT (4*0)
55: #define END (4*1)
56: #define DELIM (4*2)
57: #define LETTER (4*3)
58:
59: void
1.15 christos 60: link_addr(const char *addr, struct sockaddr_dl *sdl)
1.1 cgd 61: {
62: register char *cp = sdl->sdl_data;
1.9 christos 63: char *cplim = sdl->sdl_len + (char *)(void *)sdl;
1.15 christos 64: int byte = 0, state = NAMING;
65: size_t newaddr = 0; /* pacify gcc */
1.1 cgd 66:
1.10 lukem 67: _DIAGASSERT(addr != NULL);
68: _DIAGASSERT(sdl != NULL);
69:
1.8 kleink 70: (void)memset(&sdl->sdl_family, 0, (size_t)sdl->sdl_len - 1);
1.1 cgd 71: sdl->sdl_family = AF_LINK;
72: do {
73: state &= ~LETTER;
74: if ((*addr >= '0') && (*addr <= '9')) {
1.6 christos 75: newaddr = *addr - '0';
1.1 cgd 76: } else if ((*addr >= 'a') && (*addr <= 'f')) {
1.6 christos 77: newaddr = *addr - 'a' + 10;
1.1 cgd 78: } else if ((*addr >= 'A') && (*addr <= 'F')) {
1.6 christos 79: newaddr = *addr - 'A' + 10;
1.1 cgd 80: } else if (*addr == 0) {
81: state |= END;
82: } else if (state == NAMING &&
83: (((*addr >= 'A') && (*addr <= 'Z')) ||
84: ((*addr >= 'a') && (*addr <= 'z'))))
85: state |= LETTER;
86: else
87: state |= DELIM;
88: addr++;
89: switch (state /* | INPUT */) {
90: case NAMING | DIGIT:
91: case NAMING | LETTER:
1.5 cgd 92: *cp++ = addr[-1];
93: continue;
1.1 cgd 94: case NAMING | DELIM:
1.5 cgd 95: state = RESET;
1.15 christos 96: _DIAGASSERT(__type_fit(uint8_t, cp - sdl->sdl_data));
97: sdl->sdl_nlen = (uint8_t)(cp - sdl->sdl_data);
1.5 cgd 98: continue;
1.1 cgd 99: case GOTTWO | DIGIT:
1.5 cgd 100: *cp++ = byte;
101: /* FALLTHROUGH */
1.1 cgd 102: case RESET | DIGIT:
1.5 cgd 103: state = GOTONE;
1.15 christos 104: byte = (int)newaddr;
1.5 cgd 105: continue;
1.1 cgd 106: case GOTONE | DIGIT:
1.5 cgd 107: state = GOTTWO;
1.15 christos 108: byte = (int)newaddr + (byte << 4);
1.5 cgd 109: continue;
1.1 cgd 110: default: /* | DELIM */
1.5 cgd 111: state = RESET;
112: *cp++ = byte;
113: byte = 0;
114: continue;
1.1 cgd 115: case GOTONE | END:
116: case GOTTWO | END:
1.5 cgd 117: *cp++ = byte;
118: /* FALLTHROUGH */
1.1 cgd 119: case RESET | END:
120: break;
121: }
122: break;
123: } while (cp < cplim);
1.15 christos 124:
125: _DIAGASSERT(__type_fit(uint8_t, cp - LLADDR(sdl)));
126: sdl->sdl_alen = (uint8_t)(cp - LLADDR(sdl));
1.9 christos 127: newaddr = cp - (char *)(void *)sdl;
1.15 christos 128: if (newaddr > sizeof(*sdl)) {
129: _DIAGASSERT(__type_fit(uint8_t, newaddr));
130: sdl->sdl_len = (uint8_t)newaddr;
131: }
1.1 cgd 132: return;
133: }
134:
1.7 mycroft 135: static const char hexlist[16] = "0123456789abcdef";
1.1 cgd 136:
137: char *
1.16 ! matt 138: link_ntoa(const struct sockaddr_dl *sdl)
1.1 cgd 139: {
140: static char obuf[64];
141: register char *out = obuf;
1.9 christos 142: register size_t i;
1.14 christos 143: const u_char *in = (const u_char *)CLLADDR(sdl);
144: const u_char *inlim = in + sdl->sdl_alen;
1.1 cgd 145: int firsttime = 1;
1.10 lukem 146:
147: _DIAGASSERT(sdl != NULL);
1.1 cgd 148:
149: if (sdl->sdl_nlen) {
1.8 kleink 150: (void)memcpy(obuf, sdl->sdl_data, (size_t)sdl->sdl_nlen);
1.1 cgd 151: out += sdl->sdl_nlen;
1.5 cgd 152: if (sdl->sdl_alen)
153: *out++ = ':';
1.1 cgd 154: }
155: while (in < inlim) {
1.5 cgd 156: if (firsttime)
157: firsttime = 0;
158: else
159: *out++ = '.';
1.1 cgd 160: i = *in++;
161: if (i > 0xf) {
162: out[1] = hexlist[i & 0xf];
163: i >>= 4;
164: out[0] = hexlist[i];
165: out += 2;
166: } else
167: *out++ = hexlist[i];
168: }
169: *out = 0;
1.5 cgd 170: return (obuf);
1.1 cgd 171: }
CVSweb <webmaster@jp.NetBSD.org>