compat_ns_addr.c revision 1.3 1 1.3 msaitoh /* $NetBSD: compat_ns_addr.c,v 1.3 2012/10/15 22:22:01 msaitoh Exp $ */
2 1.1 matt
3 1.1 matt /*
4 1.1 matt * Copyright (c) 1986, 1993
5 1.1 matt * The Regents of the University of California. All rights reserved.
6 1.1 matt *
7 1.1 matt * This code is derived from software contributed to Berkeley by
8 1.1 matt * J.Q. Johnson.
9 1.1 matt *
10 1.1 matt * Redistribution and use in source and binary forms, with or without
11 1.1 matt * modification, are permitted provided that the following conditions
12 1.1 matt * are met:
13 1.1 matt * 1. Redistributions of source code must retain the above copyright
14 1.1 matt * notice, this list of conditions and the following disclaimer.
15 1.1 matt * 2. Redistributions in binary form must reproduce the above copyright
16 1.1 matt * notice, this list of conditions and the following disclaimer in the
17 1.1 matt * documentation and/or other materials provided with the distribution.
18 1.1 matt * 3. Neither the name of the University nor the names of its contributors
19 1.1 matt * may be used to endorse or promote products derived from this software
20 1.1 matt * without specific prior written permission.
21 1.1 matt *
22 1.1 matt * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 1.1 matt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 1.1 matt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 1.1 matt * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 1.1 matt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 1.1 matt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 1.1 matt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 1.1 matt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 1.1 matt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 1.1 matt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 1.1 matt * SUCH DAMAGE.
33 1.1 matt */
34 1.1 matt
35 1.1 matt #include <sys/cdefs.h>
36 1.1 matt #if defined(LIBC_SCCS) && !defined(lint)
37 1.1 matt #if 0
38 1.1 matt static char sccsid[] = "@(#)ns_addr.c 8.1 (Berkeley) 6/7/93";
39 1.1 matt #else
40 1.3 msaitoh __RCSID("$NetBSD: compat_ns_addr.c,v 1.3 2012/10/15 22:22:01 msaitoh Exp $");
41 1.1 matt #endif
42 1.1 matt #endif /* LIBC_SCCS and not lint */
43 1.1 matt
44 1.1 matt #include "namespace.h"
45 1.1 matt #include <sys/param.h>
46 1.1 matt #include <compat/include/ns.h>
47 1.1 matt
48 1.1 matt #include <assert.h>
49 1.1 matt #include <stdio.h>
50 1.1 matt #include <string.h>
51 1.1 matt
52 1.2 matt static void Field(char *, uint8_t *, int);
53 1.2 matt static void cvtbase(long, int, int[], int, uint8_t [], int);
54 1.1 matt
55 1.1 matt struct ns_addr
56 1.2 matt ns_addr(const char *name)
57 1.1 matt {
58 1.1 matt char separator;
59 1.1 matt char *hostname, *socketname, *cp;
60 1.1 matt char buf[50];
61 1.1 matt static struct ns_addr addr;
62 1.1 matt
63 1.1 matt _DIAGASSERT(name != NULL);
64 1.1 matt
65 1.1 matt (void)strlcpy(buf, name, sizeof(buf));
66 1.1 matt
67 1.1 matt /*
68 1.1 matt * First, figure out what he intends as a field separtor.
69 1.1 matt * Despite the way this routine is written, the prefered
70 1.1 matt * form 2-272.AA001234H.01777, i.e. XDE standard.
71 1.1 matt * Great efforts are made to insure backward compatibility.
72 1.1 matt */
73 1.1 matt if ((hostname = strchr(buf, '#')) != NULL)
74 1.1 matt separator = '#';
75 1.1 matt else {
76 1.1 matt hostname = strchr(buf, '.');
77 1.1 matt if ((cp = strchr(buf, ':')) &&
78 1.1 matt ((hostname && cp < hostname) || (hostname == 0))) {
79 1.1 matt hostname = cp;
80 1.1 matt separator = ':';
81 1.1 matt } else
82 1.1 matt separator = '.';
83 1.1 matt }
84 1.1 matt if (hostname)
85 1.1 matt *hostname++ = 0;
86 1.1 matt
87 1.1 matt memset(&addr, '\0', sizeof(addr));
88 1.1 matt Field(buf, addr.x_net.c_net, 4);
89 1.1 matt if (hostname == 0)
90 1.1 matt return (addr); /* No separator means net only */
91 1.1 matt
92 1.1 matt socketname = strchr(hostname, separator);
93 1.1 matt if (socketname) {
94 1.1 matt *socketname++ = 0;
95 1.2 matt Field(socketname, (uint8_t *)(void *)&addr.x_port, 2);
96 1.1 matt }
97 1.1 matt
98 1.1 matt Field(hostname, addr.x_host.c_host, 6);
99 1.1 matt
100 1.1 matt return (addr);
101 1.1 matt }
102 1.1 matt
103 1.1 matt static void
104 1.2 matt Field(char *buf, uint8_t *out, int len)
105 1.1 matt {
106 1.1 matt register char *bp = buf;
107 1.3 msaitoh int i, ibase, base16 = 0, base10 = 0;
108 1.3 msaitoh unsigned int clen = 0;
109 1.1 matt int hb[6], *hp;
110 1.1 matt
111 1.1 matt _DIAGASSERT(buf != NULL);
112 1.1 matt _DIAGASSERT(out != NULL);
113 1.1 matt
114 1.1 matt /*
115 1.1 matt * first try 2-273#2-852-151-014#socket
116 1.1 matt */
117 1.1 matt if ((*buf != '-') &&
118 1.1 matt (1 < (i = sscanf(buf, "%d-%d-%d-%d-%d",
119 1.1 matt &hb[0], &hb[1], &hb[2], &hb[3], &hb[4])))) {
120 1.1 matt cvtbase(1000L, 256, hb, i, out, len);
121 1.1 matt return;
122 1.1 matt }
123 1.1 matt /*
124 1.1 matt * try form 8E1#0.0.AA.0.5E.E6#socket
125 1.1 matt */
126 1.1 matt if (1 < (i = sscanf(buf,"%x.%x.%x.%x.%x.%x",
127 1.1 matt &hb[0], &hb[1], &hb[2], &hb[3], &hb[4], &hb[5]))) {
128 1.1 matt cvtbase(256L, 256, hb, i, out, len);
129 1.1 matt return;
130 1.1 matt }
131 1.1 matt /*
132 1.1 matt * try form 8E1#0:0:AA:0:5E:E6#socket
133 1.1 matt */
134 1.1 matt if (1 < (i = sscanf(buf,"%x:%x:%x:%x:%x:%x",
135 1.1 matt &hb[0], &hb[1], &hb[2], &hb[3], &hb[4], &hb[5]))) {
136 1.1 matt cvtbase(256L, 256, hb, i, out, len);
137 1.1 matt return;
138 1.1 matt }
139 1.1 matt /*
140 1.1 matt * This is REALLY stretching it but there was a
141 1.1 matt * comma notation separting shorts -- definitely non standard
142 1.1 matt */
143 1.1 matt if (1 < (i = sscanf(buf,"%x,%x,%x",
144 1.1 matt &hb[0], &hb[1], &hb[2]))) {
145 1.1 matt hb[0] = htons(hb[0]); hb[1] = htons(hb[1]);
146 1.1 matt hb[2] = htons(hb[2]);
147 1.1 matt cvtbase(65536L, 256, hb, i, out, len);
148 1.1 matt return;
149 1.1 matt }
150 1.1 matt
151 1.1 matt /* Need to decide if base 10, 16 or 8 */
152 1.1 matt while (*bp) switch (*bp++) {
153 1.1 matt
154 1.1 matt case '0': case '1': case '2': case '3': case '4': case '5':
155 1.1 matt case '6': case '7': case '-':
156 1.1 matt break;
157 1.1 matt
158 1.1 matt case '8': case '9':
159 1.1 matt base10 = 1;
160 1.1 matt break;
161 1.1 matt
162 1.1 matt case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
163 1.1 matt case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
164 1.1 matt base16 = 1;
165 1.1 matt break;
166 1.1 matt
167 1.1 matt case 'x': case 'X':
168 1.1 matt *--bp = '0';
169 1.1 matt base16 = 1;
170 1.1 matt break;
171 1.1 matt
172 1.1 matt case 'h': case 'H':
173 1.1 matt base16 = 1;
174 1.1 matt /* FALLTHROUGH */
175 1.1 matt
176 1.1 matt default:
177 1.1 matt *--bp = 0; /* Ends Loop */
178 1.1 matt }
179 1.1 matt if (base16) {
180 1.1 matt ibase = 4096;
181 1.1 matt } else if (base10 == 0 && *buf == '0') {
182 1.1 matt ibase = 512;
183 1.1 matt } else {
184 1.1 matt base10 = 1;
185 1.1 matt ibase = 1000;
186 1.1 matt }
187 1.1 matt
188 1.1 matt for (bp = buf; *bp++; ) clen++;
189 1.1 matt if (clen == 0) clen++;
190 1.1 matt if (clen > 18) clen = 18;
191 1.1 matt i = ((clen - 1) / 3) + 1;
192 1.1 matt bp = clen + buf - 3;
193 1.1 matt hp = hb + i - 1;
194 1.1 matt
195 1.1 matt while (hp > hb) {
196 1.1 matt if (base16)
197 1.1 matt (void)sscanf(bp, "%3x", hp);
198 1.1 matt else if (base10)
199 1.1 matt (void)sscanf(bp, "%3d", hp);
200 1.1 matt else
201 1.1 matt (void)sscanf(bp, "%3o", hp);
202 1.1 matt
203 1.1 matt bp[0] = 0;
204 1.1 matt hp--;
205 1.1 matt bp -= 3;
206 1.1 matt }
207 1.1 matt if (base16)
208 1.1 matt (void)sscanf(buf, "%3x", hp);
209 1.1 matt else if (base10)
210 1.1 matt (void)sscanf(buf, "%3d", hp);
211 1.1 matt else
212 1.1 matt (void)sscanf(buf, "%3o", hp);
213 1.1 matt
214 1.1 matt cvtbase((long)ibase, 256, hb, i, out, len);
215 1.1 matt }
216 1.1 matt
217 1.1 matt static void
218 1.2 matt cvtbase(long oldbase, int newbase, int input[], int inlen,
219 1.2 matt uint8_t result[], int reslen)
220 1.1 matt {
221 1.1 matt int d, e;
222 1.1 matt long sum;
223 1.1 matt
224 1.1 matt _DIAGASSERT(input != NULL);
225 1.1 matt _DIAGASSERT(result != NULL);
226 1.2 matt _DIAGASSERT(inlen > 0);
227 1.1 matt
228 1.1 matt e = 1;
229 1.1 matt while (e > 0 && reslen > 0) {
230 1.1 matt d = 0; e = 0; sum = 0;
231 1.1 matt /* long division: input=input/newbase */
232 1.1 matt while (d < inlen) {
233 1.1 matt sum = sum*oldbase + (long) input[d];
234 1.1 matt e += (sum > 0);
235 1.1 matt input[d++] = (int) (sum / newbase);
236 1.1 matt sum %= newbase;
237 1.1 matt }
238 1.1 matt /* accumulate remainder */
239 1.1 matt result[--reslen] = (unsigned char)sum;
240 1.1 matt }
241 1.1 matt for (d=0; d < reslen; d++)
242 1.1 matt result[d] = 0;
243 1.1 matt }
244