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