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