138451Smsmith/*	$NetBSD: net.c,v 1.20 1997/12/26 22:41:30 scottr Exp $	*/
238451Smsmith
338451Smsmith/*
438451Smsmith * Copyright (c) 1992 Regents of the University of California.
538451Smsmith * All rights reserved.
638451Smsmith *
738451Smsmith * This software was developed by the Computer Systems Engineering group
838451Smsmith * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
938451Smsmith * contributed to Berkeley.
1038451Smsmith *
1138451Smsmith * Redistribution and use in source and binary forms, with or without
1238451Smsmith * modification, are permitted provided that the following conditions
1338451Smsmith * are met:
1438451Smsmith * 1. Redistributions of source code must retain the above copyright
1538451Smsmith *    notice, this list of conditions and the following disclaimer.
1638451Smsmith * 2. Redistributions in binary form must reproduce the above copyright
1738451Smsmith *    notice, this list of conditions and the following disclaimer in the
1838451Smsmith *    documentation and/or other materials provided with the distribution.
1938451Smsmith * 4. Neither the name of the University nor the names of its contributors
2038451Smsmith *    may be used to endorse or promote products derived from this software
2138451Smsmith *    without specific prior written permission.
2238451Smsmith *
2338451Smsmith * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2438451Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2538451Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2638451Smsmith * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2738451Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2838451Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2938451Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3038451Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3138451Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3238451Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3338451Smsmith * SUCH DAMAGE.
3438451Smsmith *
3538451Smsmith * @(#) Header: net.c,v 1.9 93/08/06 19:32:15 leres Exp  (LBL)
3638451Smsmith */
3738451Smsmith
3884221Sdillon#include <sys/cdefs.h>
3984221Sdillon__FBSDID("$FreeBSD$");
4084221Sdillon
4138451Smsmith#include <sys/param.h>
4238451Smsmith#include <sys/socket.h>
4338451Smsmith
4438451Smsmith#include <string.h>
4538451Smsmith
4638451Smsmith#include <net/if.h>
4738451Smsmith#include <netinet/in.h>
4838451Smsmith#include <netinet/if_ether.h>
4938451Smsmith#include <netinet/in_systm.h>
5038451Smsmith
51221364Srodrigc#include <netinet/in_pcb.h>
5238451Smsmith#include <netinet/ip.h>
5338451Smsmith#include <netinet/ip_var.h>
5438451Smsmith#include <netinet/udp.h>
5538451Smsmith#include <netinet/udp_var.h>
5638451Smsmith
5738451Smsmith#include "stand.h"
5838451Smsmith#include "net.h"
5938451Smsmith
6038451Smsmith/*
6138451Smsmith * Send a packet and wait for a reply, with exponential backoff.
6238451Smsmith *
6338451Smsmith * The send routine must return the actual number of bytes written,
6438451Smsmith * or -1 on error.
6538451Smsmith *
6638451Smsmith * The receive routine can indicate success by returning the number of
6738451Smsmith * bytes read; it can return 0 to indicate EOF; it can return -1 with a
6838451Smsmith * non-zero errno to indicate failure; finally, it can return -1 with a
6938451Smsmith * zero errno to indicate it isn't done yet.
7038451Smsmith */
7138451Smsmithssize_t
72197178Semastesendrecv(struct iodesc *d,
73197178Semaste	ssize_t (*sproc)(struct iodesc *, void *, size_t),
74197178Semaste	void *sbuf, size_t ssize,
75197178Semaste	ssize_t (*rproc)(struct iodesc *, void *, size_t, time_t),
76197178Semaste	void *rbuf, size_t rsize)
7738451Smsmith{
7892913Sobrien	ssize_t cc;
7992913Sobrien	time_t t, tmo, tlast;
8038451Smsmith	long tleft;
8138451Smsmith
8238451Smsmith#ifdef NET_DEBUG
8338451Smsmith	if (debug)
8438451Smsmith		printf("sendrecv: called\n");
8538451Smsmith#endif
8638451Smsmith
8738451Smsmith	tmo = MINTMO;
88197178Semaste	tlast = 0;
89197178Semaste	tleft = 0;
9038451Smsmith	t = getsecs();
9138451Smsmith	for (;;) {
9238451Smsmith		if (tleft <= 0) {
9338451Smsmith			if (tmo >= MAXTMO) {
9438451Smsmith				errno = ETIMEDOUT;
9538451Smsmith				return -1;
9638451Smsmith			}
9738451Smsmith			cc = (*sproc)(d, sbuf, ssize);
9838451Smsmith			if (cc != -1 && cc < ssize)
99146835Sjhb				panic("sendrecv: short write! (%zd < %zd)",
10038451Smsmith				    cc, ssize);
10138451Smsmith
10238451Smsmith			tleft = tmo;
103223121Srodrigc			tmo += MINTMO;
10438451Smsmith			if (tmo > MAXTMO)
10538451Smsmith				tmo = MAXTMO;
10638451Smsmith
10738451Smsmith			if (cc == -1) {
10838451Smsmith				/* Error on transmit; wait before retrying */
109197178Semaste				while ((getsecs() - t) < tmo)
110197178Semaste					;
11138451Smsmith				tleft = 0;
11238451Smsmith				continue;
11338451Smsmith			}
11438451Smsmith
11538451Smsmith			tlast = t;
11638451Smsmith		}
11738451Smsmith
11838451Smsmith		/* Try to get a packet and process it. */
11938451Smsmith		cc = (*rproc)(d, rbuf, rsize, tleft);
12038451Smsmith		/* Return on data, EOF or real error. */
12138451Smsmith		if (cc != -1 || errno != 0)
12238451Smsmith			return (cc);
12338451Smsmith
12438451Smsmith		/* Timed out or didn't get the packet we're waiting for */
12538451Smsmith		t = getsecs();
12638451Smsmith		tleft -= t - tlast;
12738451Smsmith		tlast = t;
12838451Smsmith	}
12938451Smsmith}
13038451Smsmith
13138451Smsmith/*
13238451Smsmith * Like inet_addr() in the C library, but we only accept base-10.
13338451Smsmith * Return values are in network order.
13438451Smsmith */
13538451Smsmithn_long
136197178Semasteinet_addr(char *cp)
13738451Smsmith{
13892913Sobrien	u_long val;
13992913Sobrien	int n;
14092913Sobrien	char c;
14138451Smsmith	u_int parts[4];
14292913Sobrien	u_int *pp = parts;
14338451Smsmith
14438451Smsmith	for (;;) {
14538451Smsmith		/*
14638451Smsmith		 * Collect number up to ``.''.
14738451Smsmith		 * Values are specified as for C:
14838451Smsmith		 * 0x=hex, 0=octal, other=decimal.
14938451Smsmith		 */
15038451Smsmith		val = 0;
15138451Smsmith		while ((c = *cp) != '\0') {
15238451Smsmith			if (c >= '0' && c <= '9') {
15338451Smsmith				val = (val * 10) + (c - '0');
15438451Smsmith				cp++;
15538451Smsmith				continue;
15638451Smsmith			}
15738451Smsmith			break;
15838451Smsmith		}
15938451Smsmith		if (*cp == '.') {
16038451Smsmith			/*
16138451Smsmith			 * Internet format:
16238451Smsmith			 *	a.b.c.d
16338451Smsmith			 *	a.b.c	(with c treated as 16-bits)
16438451Smsmith			 *	a.b	(with b treated as 24 bits)
16538451Smsmith			 */
16638451Smsmith			if (pp >= parts + 3 || val > 0xff)
16738451Smsmith				goto bad;
16838451Smsmith			*pp++ = val, cp++;
16938451Smsmith		} else
17038451Smsmith			break;
17138451Smsmith	}
17238451Smsmith	/*
17338451Smsmith	 * Check for trailing characters.
17438451Smsmith	 */
17538451Smsmith	if (*cp != '\0')
17638451Smsmith		goto bad;
17738451Smsmith
17838451Smsmith	/*
17938451Smsmith	 * Concoct the address according to
18038451Smsmith	 * the number of parts specified.
18138451Smsmith	 */
18238451Smsmith	n = pp - parts + 1;
18338451Smsmith	switch (n) {
18438451Smsmith
18538451Smsmith	case 1:				/* a -- 32 bits */
18638451Smsmith		break;
18738451Smsmith
18838451Smsmith	case 2:				/* a.b -- 8.24 bits */
18938451Smsmith		if (val > 0xffffff)
19038451Smsmith			goto bad;
19138451Smsmith		val |= parts[0] << 24;
19238451Smsmith		break;
19338451Smsmith
19438451Smsmith	case 3:				/* a.b.c -- 8.8.16 bits */
19538451Smsmith		if (val > 0xffff)
19638451Smsmith			goto bad;
19738451Smsmith		val |= (parts[0] << 24) | (parts[1] << 16);
19838451Smsmith		break;
19938451Smsmith
20038451Smsmith	case 4:				/* a.b.c.d -- 8.8.8.8 bits */
20138451Smsmith		if (val > 0xff)
20238451Smsmith			goto bad;
20338451Smsmith		val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
20438451Smsmith		break;
20538451Smsmith	}
20638451Smsmith
20738451Smsmith	return (htonl(val));
20838451Smsmith bad:
20938451Smsmith	return (htonl(INADDR_NONE));
21038451Smsmith}
21138451Smsmith
21238451Smsmithchar *
213197178Semasteinet_ntoa(struct in_addr ia)
21438451Smsmith{
21538451Smsmith	return (intoa(ia.s_addr));
21638451Smsmith}
21738451Smsmith
21838451Smsmith/* Similar to inet_ntoa() */
21938451Smsmithchar *
220197178Semasteintoa(n_long addr)
22138451Smsmith{
22292913Sobrien	char *cp;
22392913Sobrien	u_int byte;
22492913Sobrien	int n;
22538451Smsmith	static char buf[17];	/* strlen(".255.255.255.255") + 1 */
22638451Smsmith
22790868Smike	addr = ntohl(addr);
22838451Smsmith	cp = &buf[sizeof buf];
22938451Smsmith	*--cp = '\0';
23038451Smsmith
23138451Smsmith	n = 4;
23238451Smsmith	do {
23338451Smsmith		byte = addr & 0xff;
23438451Smsmith		*--cp = byte % 10 + '0';
23538451Smsmith		byte /= 10;
23638451Smsmith		if (byte > 0) {
23738451Smsmith			*--cp = byte % 10 + '0';
23838451Smsmith			byte /= 10;
23938451Smsmith			if (byte > 0)
24038451Smsmith				*--cp = byte + '0';
24138451Smsmith		}
24238451Smsmith		*--cp = '.';
24338451Smsmith		addr >>= 8;
24438451Smsmith	} while (--n > 0);
24538451Smsmith
24638451Smsmith	return (cp+1);
24738451Smsmith}
24838451Smsmith
24938451Smsmithstatic char *
250197178Semastenumber(char *s, int *n)
25138451Smsmith{
25238451Smsmith	for (*n = 0; isdigit(*s); s++)
25338451Smsmith		*n = (*n * 10) + *s - '0';
25438451Smsmith	return s;
25538451Smsmith}
25638451Smsmith
25738451Smsmithn_long
258197178Semasteip_convertaddr(char *p)
25938451Smsmith{
26038451Smsmith#define IP_ANYADDR	0
26138451Smsmith	n_long addr = 0, n;
26238451Smsmith
26338451Smsmith	if (p == (char *)0 || *p == '\0')
26438451Smsmith		return IP_ANYADDR;
26538451Smsmith	p = number(p, &n);
26638451Smsmith	addr |= (n << 24) & 0xff000000;
26738451Smsmith	if (*p == '\0' || *p++ != '.')
26838451Smsmith		return IP_ANYADDR;
26938451Smsmith	p = number(p, &n);
27038451Smsmith	addr |= (n << 16) & 0xff0000;
27138451Smsmith	if (*p == '\0' || *p++ != '.')
27238451Smsmith		return IP_ANYADDR;
27338451Smsmith	p = number(p, &n);
27438451Smsmith	addr |= (n << 8) & 0xff00;
27538451Smsmith	if (*p == '\0' || *p++ != '.')
27638451Smsmith		return IP_ANYADDR;
27738451Smsmith	p = number(p, &n);
27838451Smsmith	addr |= n & 0xff;
27938451Smsmith	if (*p != '\0')
28038451Smsmith		return IP_ANYADDR;
28138451Smsmith
28238451Smsmith	return htonl(addr);
28338451Smsmith}
284