xref: /original-bsd/lib/libc/net/ns_addr.c (revision 2301fdfb)
1 /*
2  * Copyright (c) 1986 Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that the above copyright notice and this paragraph are
7  * duplicated in all such forms and that any documentation,
8  * advertising materials, and other materials related to such
9  * distribution and use acknowledge that the software was developed
10  * by the University of California, Berkeley.  The name of the
11  * University may not be used to endorse or promote products derived
12  * from this software without specific prior written permission.
13  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  *
17  * This code is derived from software contributed to Berkeley by
18  * J.Q. Johnson at Cornell University.
19  */
20 
21 #if defined(LIBC_SCCS) && !defined(lint)
22 static char sccsid[] = "@(#)ns_addr.c	6.4 (Berkeley) 08/12/88";
23 #endif /* LIBC_SCCS and not lint */
24 
25 #include <sys/types.h>
26 #include <netns/ns.h>
27 
28 static struct ns_addr addr, zero_addr;
29 
30 struct ns_addr
31 ns_addr(name)
32 	char *name;
33 {
34 	char separator = '.';
35 	char *hostname, *socketname, *cp;
36 	char buf[50];
37 	extern char *index();
38 
39 	addr = zero_addr;
40 	(void)strncpy(buf, name, 49);
41 
42 	/*
43 	 * First, figure out what he intends as a field separtor.
44 	 * Despite the way this routine is written, the prefered
45 	 * form  2-272.AA001234H.01777, i.e. XDE standard.
46 	 * Great efforts are made to insure backward compatability.
47 	 */
48 	if (hostname = index(buf, '#'))
49 		separator = '#';
50 	else {
51 		hostname = index(buf, '.');
52 		if ((cp = index(buf, ':')) &&
53 		    ( (hostname && cp < hostname) || (hostname == 0))) {
54 			hostname = cp;
55 			separator = ':';
56 		}
57 	}
58 	if (hostname)
59 		*hostname++ = 0;
60 	Field(buf, addr.x_net.c_net, 4);
61 	if (hostname == 0)
62 		return (addr);  /* No separator means net only */
63 
64 	socketname = index(hostname, separator);
65 	if (socketname) {
66 		*socketname++ = 0;
67 		Field(socketname, (u_char *)&addr.x_port, 2);
68 	}
69 
70 	Field(hostname, addr.x_host.c_host, 6);
71 
72 	return (addr);
73 }
74 
75 static
76 Field(buf, out, len)
77 char *buf;
78 u_char *out;
79 int len;
80 {
81 	register char *bp = buf;
82 	int i, ibase, base16 = 0, base10 = 0, clen = 0;
83 	int hb[6], *hp;
84 	char *fmt;
85 
86 	/*
87 	 * first try 2-273#2-852-151-014#socket
88 	 */
89 	if ((*buf != '-') &&
90 	    (1 < (i = sscanf(buf, "%d-%d-%d-%d-%d",
91 			&hb[0], &hb[1], &hb[2], &hb[3], &hb[4])))) {
92 		cvtbase(1000L, 256, hb, i, out, len);
93 		return;
94 	}
95 	/*
96 	 * try form 8E1#0.0.AA.0.5E.E6#socket
97 	 */
98 	if (1 < (i = sscanf(buf,"%x.%x.%x.%x.%x.%x",
99 			&hb[0], &hb[1], &hb[2], &hb[3], &hb[4], &hb[5]))) {
100 		cvtbase(256L, 256, hb, i, out, len);
101 		return;
102 	}
103 	/*
104 	 * try form 8E1#0:0:AA:0:5E:E6#socket
105 	 */
106 	if (1 < (i = sscanf(buf,"%x:%x:%x:%x:%x:%x",
107 			&hb[0], &hb[1], &hb[2], &hb[3], &hb[4], &hb[5]))) {
108 		cvtbase(256L, 256, hb, i, out, len);
109 		return;
110 	}
111 	/*
112 	 * This is REALLY stretching it but there was a
113 	 * comma notation separting shorts -- definitely non standard
114 	 */
115 	if (1 < (i = sscanf(buf,"%x,%x,%x",
116 			&hb[0], &hb[1], &hb[2]))) {
117 		hb[0] = htons(hb[0]); hb[1] = htons(hb[1]);
118 		hb[2] = htons(hb[2]);
119 		cvtbase(65536L, 256, hb, i, out, len);
120 		return;
121 	}
122 
123 	/* Need to decide if base 10, 16 or 8 */
124 	while (*bp) switch (*bp++) {
125 
126 	case '0': case '1': case '2': case '3': case '4': case '5':
127 	case '6': case '7': case '-':
128 		break;
129 
130 	case '8': case '9':
131 		base10 = 1;
132 		break;
133 
134 	case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
135 	case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
136 		base16 = 1;
137 		break;
138 
139 	case 'x': case 'X':
140 		*--bp = '0';
141 		base16 = 1;
142 		break;
143 
144 	case 'h': case 'H':
145 		base16 = 1;
146 		/* fall into */
147 
148 	default:
149 		*--bp = 0; /* Ends Loop */
150 	}
151 	if (base16) {
152 		fmt = "%3x";
153 		ibase = 4096;
154 	} else if (base10 == 0 && *buf == '0') {
155 		fmt = "%3o";
156 		ibase = 512;
157 	} else {
158 		fmt = "%3d";
159 		ibase = 1000;
160 	}
161 
162 	for (bp = buf; *bp++; ) clen++;
163 	if (clen == 0) clen++;
164 	if (clen > 18) clen = 18;
165 	i = ((clen - 1) / 3) + 1;
166 	bp = clen + buf - 3;
167 	hp = hb + i - 1;
168 
169 	while (hp > hb) {
170 		(void)sscanf(bp, fmt, hp);
171 		bp[0] = 0;
172 		hp--;
173 		bp -= 3;
174 	}
175 	(void)sscanf(buf, fmt, hp);
176 	cvtbase((long)ibase, 256, hb, i, out, len);
177 }
178 
179 static
180 cvtbase(oldbase,newbase,input,inlen,result,reslen)
181 	long oldbase;
182 	int newbase;
183 	int input[];
184 	int inlen;
185 	unsigned char result[];
186 	int reslen;
187 {
188 	int d, e;
189 	long sum;
190 
191 	e = 1;
192 	while (e > 0 && reslen > 0) {
193 		d = 0; e = 0; sum = 0;
194 		/* long division: input=input/newbase */
195 		while (d < inlen) {
196 			sum = sum*oldbase + (long) input[d];
197 			e += (sum > 0);
198 			input[d++] = sum / newbase;
199 			sum %= newbase;
200 		}
201 		result[--reslen] = sum;	/* accumulate remainder */
202 	}
203 	for (d=0; d < reslen; d++)
204 		result[d] = 0;
205 }
206