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