xref: /openbsd-src/sys/lib/libsa/net.c (revision 9ffa8117f28ad1e2b8a77350d9c73ec963f951e7)
1 /*	$OpenBSD: net.c,v 1.20 2015/10/26 14:48:54 mmcc Exp $	*/
2 /*	$NetBSD: net.c,v 1.14 1996/10/13 02:29:02 christos Exp $	*/
3 
4 /*
5  * Copyright (c) 1992 Regents of the University of California.
6  * All rights reserved.
7  *
8  * This software was developed by the Computer Systems Engineering group
9  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
10  * contributed to Berkeley.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  * 3. All advertising materials mentioning features or use of this software
21  *    must display the following acknowledgement:
22  *	This product includes software developed by the University of
23  *	California, Lawrence Berkeley Laboratory and its contributors.
24  * 4. Neither the name of the University nor the names of its contributors
25  *    may be used to endorse or promote products derived from this software
26  *    without specific prior written permission.
27  *
28  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38  * SUCH DAMAGE.
39  *
40  * @(#) Header: net.c,v 1.9 93/08/06 19:32:15 leres Exp  (LBL)
41  */
42 
43 #include <sys/param.h>
44 #include <sys/socket.h>
45 
46 #include <net/if.h>
47 #include <netinet/in.h>
48 
49 #include <netinet/if_ether.h>
50 #include <netinet/ip.h>
51 #include <netinet/ip_var.h>
52 
53 #include "stand.h"
54 #include "net.h"
55 
56 /*
57  * Send a packet and wait for a reply, with exponential backoff.
58  *
59  * The send routine must return the actual number of bytes written.
60  *
61  * The receive routine can indicate success by returning the number of
62  * bytes read; it can return 0 to indicate EOF; it can return -1 with a
63  * non-zero errno to indicate failure; finally, it can return -1 with a
64  * zero errno to indicate it isn't done yet.
65  */
66 ssize_t
sendrecv(struct iodesc * d,ssize_t (* sproc)(struct iodesc *,void *,size_t),void * sbuf,size_t ssize,ssize_t (* rproc)(struct iodesc *,void *,size_t,time_t),void * rbuf,size_t rsize)67 sendrecv(struct iodesc *d, ssize_t (*sproc)(struct iodesc *, void *, size_t),
68     void *sbuf, size_t ssize,
69     ssize_t (*rproc)(struct iodesc *, void *, size_t, time_t),
70     void *rbuf, size_t rsize)
71 {
72 	ssize_t cc;
73 	time_t t, tmo, tlast;
74 	long tleft;
75 
76 #ifdef NET_DEBUG
77 	if (debug)
78 		printf("sendrecv: called\n");
79 #endif
80 
81 	tmo = MINTMO;
82 	tlast = tleft = 0;
83 	t = getsecs();
84 	for (;;) {
85 		if (tleft <= 0) {
86 			if (tmo >= MAXTMO) {
87 				errno = ETIMEDOUT;
88 				return -1;
89 			}
90 			cc = (*sproc)(d, sbuf, ssize);
91 			if (cc < 0 || (size_t)cc < ssize)
92 				panic("sendrecv: short write! (%d < %d)",
93 				    cc, ssize);
94 
95 			tleft = tmo;
96 			tmo <<= 1;
97 			if (tmo > MAXTMO)
98 				tmo = MAXTMO;
99 			tlast = t;
100 		}
101 
102 		/* Try to get a packet and process it. */
103 		cc = (*rproc)(d, rbuf, rsize, tleft);
104 		/* Return on data, EOF or real error. */
105 		if (cc != -1 || errno != 0)
106 			return (cc);
107 
108 		/* Timed out or didn't get the packet we're waiting for */
109 		t = getsecs();
110 		tleft -= t - tlast;
111 		tlast = t;
112 	}
113 }
114 
115 /*
116  * Like inet_addr() in the C library, but we only accept base-10.
117  * Return values are in network order.
118  */
119 u_int32_t
inet_addr(const char * cp)120 inet_addr(const char *cp)
121 {
122 	u_long val;
123 	int n;
124 	char c;
125 	u_int parts[4];
126 	u_int *pp = parts;
127 
128 	for (;;) {
129 		/*
130 		 * Collect number up to ``.''.
131 		 * Values are specified as for C:
132 		 * 0x=hex, 0=octal, other=decimal.
133 		 */
134 		val = 0;
135 		while ((c = *cp) != '\0') {
136 			if (c >= '0' && c <= '9') {
137 				val = (val * 10) + (c - '0');
138 				cp++;
139 				continue;
140 			}
141 			break;
142 		}
143 		if (*cp == '.') {
144 			/*
145 			 * Internet format:
146 			 *	a.b.c.d
147 			 *	a.b.c	(with c treated as 16-bits)
148 			 *	a.b	(with b treated as 24 bits)
149 			 */
150 			if (pp >= parts + 3 || val > 0xff)
151 				goto bad;
152 			*pp++ = val, cp++;
153 		} else
154 			break;
155 	}
156 	/*
157 	 * Check for trailing characters.
158 	 */
159 	if (*cp != '\0')
160 		goto bad;
161 
162 	/*
163 	 * Concoct the address according to
164 	 * the number of parts specified.
165 	 */
166 	n = pp - parts + 1;
167 	switch (n) {
168 
169 	case 1:				/* a -- 32 bits */
170 		break;
171 
172 	case 2:				/* a.b -- 8.24 bits */
173 		if (val > 0xffffff)
174 			goto bad;
175 		val |= parts[0] << 24;
176 		break;
177 
178 	case 3:				/* a.b.c -- 8.8.16 bits */
179 		if (val > 0xffff)
180 			goto bad;
181 		val |= (parts[0] << 24) | (parts[1] << 16);
182 		break;
183 
184 	case 4:				/* a.b.c.d -- 8.8.8.8 bits */
185 		if (val > 0xff)
186 			goto bad;
187 		val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
188 		break;
189 	}
190 
191 	return (htonl(val));
192  bad:
193 	return (htonl(INADDR_NONE));
194 }
195 
196 const char *
inet_ntoa(struct in_addr ia)197 inet_ntoa(struct in_addr ia)
198 {
199 	return (intoa(ia.s_addr));
200 }
201 
202 /* Similar to inet_ntoa() */
203 const char *
intoa(u_int32_t addr)204 intoa(u_int32_t addr)
205 {
206 	char *cp;
207 	u_int byte;
208 	int n;
209 	static char buf[sizeof(".255.255.255.255")];
210 
211 	addr = ntohl(addr);
212 	cp = &buf[sizeof buf];
213 	*--cp = '\0';
214 
215 	n = 4;
216 	do {
217 		byte = addr & 0xff;
218 		*--cp = byte % 10 + '0';
219 		byte /= 10;
220 		if (byte > 0) {
221 			*--cp = byte % 10 + '0';
222 			byte /= 10;
223 			if (byte > 0)
224 				*--cp = byte + '0';
225 		}
226 		*--cp = '.';
227 		addr >>= 8;
228 	} while (--n > 0);
229 
230 	return (cp+1);
231 }
232 
233 static const char *
number(const char * s,int * n)234 number(const char *s, int *n)
235 {
236 	for (*n = 0; isdigit((unsigned char)*s); s++)
237 		*n = (*n * 10) + *s - '0';
238 	return s;
239 }
240 
241 u_int32_t
ip_convertaddr(const char * p)242 ip_convertaddr(const char *p)
243 {
244 #define IP_ANYADDR	0
245 	u_int32_t addr = 0, n;
246 
247 	if (p == NULL || *p == '\0')
248 		return IP_ANYADDR;
249 	p = number(p, &n);
250 	addr |= (n << 24) & 0xff000000;
251 	if (*p == '\0' || *p++ != '.')
252 		return IP_ANYADDR;
253 	p = number(p, &n);
254 	addr |= (n << 16) & 0xff0000;
255 	if (*p == '\0' || *p++ != '.')
256 		return IP_ANYADDR;
257 	p = number(p, &n);
258 	addr |= (n << 8) & 0xff00;
259 	if (*p == '\0' || *p++ != '.')
260 		return IP_ANYADDR;
261 	p = number(p, &n);
262 	addr |= n & 0xff;
263 	if (*p != '\0')
264 		return IP_ANYADDR;
265 
266 	return htonl(addr);
267 }
268