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