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