net.c revision 221364
11590Srgrimes/*	$NetBSD: net.c,v 1.20 1997/12/26 22:41:30 scottr Exp $	*/
21590Srgrimes
31590Srgrimes/*
41590Srgrimes * Copyright (c) 1992 Regents of the University of California.
51590Srgrimes * All rights reserved.
61590Srgrimes *
71590Srgrimes * This software was developed by the Computer Systems Engineering group
81590Srgrimes * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
91590Srgrimes * contributed to Berkeley.
101590Srgrimes *
111590Srgrimes * Redistribution and use in source and binary forms, with or without
121590Srgrimes * modification, are permitted provided that the following conditions
131590Srgrimes * are met:
141590Srgrimes * 1. Redistributions of source code must retain the above copyright
151590Srgrimes *    notice, this list of conditions and the following disclaimer.
161590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
171590Srgrimes *    notice, this list of conditions and the following disclaimer in the
181590Srgrimes *    documentation and/or other materials provided with the distribution.
191590Srgrimes * 4. Neither the name of the University nor the names of its contributors
201590Srgrimes *    may be used to endorse or promote products derived from this software
211590Srgrimes *    without specific prior written permission.
221590Srgrimes *
231590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
241590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
251590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
261590Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
271590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
281590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
291590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
301590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
311590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
321590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
331590Srgrimes * SUCH DAMAGE.
3487710Smarkm *
3587710Smarkm * @(#) Header: net.c,v 1.9 93/08/06 19:32:15 leres Exp  (LBL)
3687710Smarkm */
3787710Smarkm
381590Srgrimes#include <sys/cdefs.h>
3987710Smarkm__FBSDID("$FreeBSD: head/lib/libstand/net.c 221364 2011-05-03 07:39:54Z rodrigc $");
4032503Scharnier
411590Srgrimes#include <sys/param.h>
421590Srgrimes#include <sys/socket.h>
431590Srgrimes
441590Srgrimes#include <string.h>
451590Srgrimes
461590Srgrimes#include <net/if.h>
4787710Smarkm#include <netinet/in.h>
4887710Smarkm#include <netinet/if_ether.h>
4932503Scharnier#include <netinet/in_systm.h>
5032503Scharnier
5178733Sdd#include <netinet/in_pcb.h>
525297Sache#include <netinet/ip.h>
5350636Speter#include <netinet/ip_var.h>
5487710Smarkm#include <netinet/udp.h>
551590Srgrimes#include <netinet/udp_var.h>
561590Srgrimes
578874Srgrimes#include "stand.h"
585297Sache#include "net.h"
595297Sache
6014443Sjoerg/*
6114443Sjoerg * Send a packet and wait for a reply, with exponential backoff.
625297Sache *
635297Sache * The send routine must return the actual number of bytes written,
645297Sache * or -1 on error.
655297Sache *
665297Sache * The receive routine can indicate success by returning the number of
675297Sache * bytes read; it can return 0 to indicate EOF; it can return -1 with a
685297Sache * non-zero errno to indicate failure; finally, it can return -1 with a
695297Sache * zero errno to indicate it isn't done yet.
705297Sache */
715297Sachessize_t
725297Sachesendrecv(struct iodesc *d,
735297Sache	ssize_t (*sproc)(struct iodesc *, void *, size_t),
748874Srgrimes	void *sbuf, size_t ssize,
751590Srgrimes	ssize_t (*rproc)(struct iodesc *, void *, size_t, time_t),
761590Srgrimes	void *rbuf, size_t rsize)
771590Srgrimes{
7814443Sjoerg	ssize_t cc;
791590Srgrimes	time_t t, tmo, tlast;
801590Srgrimes	long tleft;
8117676Speter
821590Srgrimes#ifdef NET_DEBUG
831590Srgrimes	if (debug)
841590Srgrimes		printf("sendrecv: called\n");
8517676Speter#endif
8617676Speter
8717676Speter	tmo = MINTMO;
881590Srgrimes	tlast = 0;
891590Srgrimes	tleft = 0;
901590Srgrimes	t = getsecs();
911590Srgrimes	for (;;) {
921590Srgrimes		if (tleft <= 0) {
931590Srgrimes			if (tmo >= MAXTMO) {
941590Srgrimes				errno = ETIMEDOUT;
951590Srgrimes				return -1;
961590Srgrimes			}
971590Srgrimes			cc = (*sproc)(d, sbuf, ssize);
981590Srgrimes			if (cc != -1 && cc < ssize)
9920988Speter				panic("sendrecv: short write! (%zd < %zd)",
1002929Sache				    cc, ssize);
1011590Srgrimes
1021590Srgrimes			tleft = tmo;
1031590Srgrimes			tmo <<= 1;
1041590Srgrimes			if (tmo > MAXTMO)
1051590Srgrimes				tmo = MAXTMO;
1061590Srgrimes
10720988Speter			if (cc == -1) {
1082929Sache				/* Error on transmit; wait before retrying */
1091590Srgrimes				while ((getsecs() - t) < tmo)
1101590Srgrimes					;
1111590Srgrimes				tleft = 0;
11217698Speter				continue;
11317698Speter			}
11417698Speter
11517698Speter			tlast = t;
11617698Speter		}
1171590Srgrimes
1181590Srgrimes		/* Try to get a packet and process it. */
1191590Srgrimes		cc = (*rproc)(d, rbuf, rsize, tleft);
1201590Srgrimes		/* Return on data, EOF or real error. */
1211590Srgrimes		if (cc != -1 || errno != 0)
1221590Srgrimes			return (cc);
1231590Srgrimes
1241590Srgrimes		/* Timed out or didn't get the packet we're waiting for */
1251590Srgrimes		t = getsecs();
1261590Srgrimes		tleft -= t - tlast;
12714443Sjoerg		tlast = t;
1281590Srgrimes	}
1291590Srgrimes}
1301590Srgrimes
1311590Srgrimes/*
13217676Speter * Like inet_addr() in the C library, but we only accept base-10.
1338874Srgrimes * Return values are in network order.
13417676Speter */
13517676Spetern_long
13617676Speterinet_addr(char *cp)
13717676Speter{
13817676Speter	u_long val;
13917676Speter	int n;
14017676Speter	char c;
14117676Speter	u_int parts[4];
14217676Speter	u_int *pp = parts;
14317676Speter
1441590Srgrimes	for (;;) {
1451590Srgrimes		/*
1461590Srgrimes		 * Collect number up to ``.''.
1471590Srgrimes		 * Values are specified as for C:
1481590Srgrimes		 * 0x=hex, 0=octal, other=decimal.
1491590Srgrimes		 */
1501590Srgrimes		val = 0;
1511590Srgrimes		while ((c = *cp) != '\0') {
1521590Srgrimes			if (c >= '0' && c <= '9') {
1531590Srgrimes				val = (val * 10) + (c - '0');
1541590Srgrimes				cp++;
1551590Srgrimes				continue;
1561590Srgrimes			}
1571590Srgrimes			break;
15814443Sjoerg		}
1591590Srgrimes		if (*cp == '.') {
16014443Sjoerg			/*
16187710Smarkm			 * Internet format:
1621590Srgrimes			 *	a.b.c.d
1631590Srgrimes			 *	a.b.c	(with c treated as 16-bits)
1641590Srgrimes			 *	a.b	(with b treated as 24 bits)
1651590Srgrimes			 */
1661590Srgrimes			if (pp >= parts + 3 || val > 0xff)
1671590Srgrimes				goto bad;
1681590Srgrimes			*pp++ = val, cp++;
1691590Srgrimes		} else
1701590Srgrimes			break;
17114443Sjoerg	}
1721590Srgrimes	/*
1731590Srgrimes	 * Check for trailing characters.
1741590Srgrimes	 */
1751590Srgrimes	if (*cp != '\0')
1761590Srgrimes		goto bad;
1771590Srgrimes
1781590Srgrimes	/*
1791590Srgrimes	 * Concoct the address according to
1801590Srgrimes	 * the number of parts specified.
1811590Srgrimes	 */
1821590Srgrimes	n = pp - parts + 1;
1831590Srgrimes	switch (n) {
1841590Srgrimes
185	case 1:				/* a -- 32 bits */
186		break;
187
188	case 2:				/* a.b -- 8.24 bits */
189		if (val > 0xffffff)
190			goto bad;
191		val |= parts[0] << 24;
192		break;
193
194	case 3:				/* a.b.c -- 8.8.16 bits */
195		if (val > 0xffff)
196			goto bad;
197		val |= (parts[0] << 24) | (parts[1] << 16);
198		break;
199
200	case 4:				/* a.b.c.d -- 8.8.8.8 bits */
201		if (val > 0xff)
202			goto bad;
203		val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
204		break;
205	}
206
207	return (htonl(val));
208 bad:
209	return (htonl(INADDR_NONE));
210}
211
212char *
213inet_ntoa(struct in_addr ia)
214{
215	return (intoa(ia.s_addr));
216}
217
218/* Similar to inet_ntoa() */
219char *
220intoa(n_long addr)
221{
222	char *cp;
223	u_int byte;
224	int n;
225	static char buf[17];	/* strlen(".255.255.255.255") + 1 */
226
227	addr = ntohl(addr);
228	cp = &buf[sizeof buf];
229	*--cp = '\0';
230
231	n = 4;
232	do {
233		byte = addr & 0xff;
234		*--cp = byte % 10 + '0';
235		byte /= 10;
236		if (byte > 0) {
237			*--cp = byte % 10 + '0';
238			byte /= 10;
239			if (byte > 0)
240				*--cp = byte + '0';
241		}
242		*--cp = '.';
243		addr >>= 8;
244	} while (--n > 0);
245
246	return (cp+1);
247}
248
249static char *
250number(char *s, int *n)
251{
252	for (*n = 0; isdigit(*s); s++)
253		*n = (*n * 10) + *s - '0';
254	return s;
255}
256
257n_long
258ip_convertaddr(char *p)
259{
260#define IP_ANYADDR	0
261	n_long addr = 0, n;
262
263	if (p == (char *)0 || *p == '\0')
264		return IP_ANYADDR;
265	p = number(p, &n);
266	addr |= (n << 24) & 0xff000000;
267	if (*p == '\0' || *p++ != '.')
268		return IP_ANYADDR;
269	p = number(p, &n);
270	addr |= (n << 16) & 0xff0000;
271	if (*p == '\0' || *p++ != '.')
272		return IP_ANYADDR;
273	p = number(p, &n);
274	addr |= (n << 8) & 0xff00;
275	if (*p == '\0' || *p++ != '.')
276		return IP_ANYADDR;
277	p = number(p, &n);
278	addr |= n & 0xff;
279	if (*p != '\0')
280		return IP_ANYADDR;
281
282	return htonl(addr);
283}
284