1 /* $OpenBSD: net.c,v 1.1 2004/03/19 13:48:19 tom 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/in.h>
50 #include <netinet/if_ether.h>
51 #include <netinet/in_systm.h>
52 #include <netinet/ip.h>
53 #include <netinet/ip_var.h>
54 #include <netinet/udp.h>
55 #include <netinet/udp_var.h>
56
57 #include <lib/libsa/stand.h>
58 #include <lib/libsa/net.h>
59
60 #include <pxeboot.h>
61
62 /* Caller must leave room for ethernet, ip and udp headers in front!! */
63 ssize_t
64 sendudp(struct iodesc *d, void *pkt, size_t len)
65 {
66 return pxesendudp(d, pkt, len);
67 }
68
69 /*
70 * Receive a UDP packet and validate it is for us.
71 * Caller leaves room for the headers (Ether, IP, UDP)
72 */
73 ssize_t
74 readudp(struct iodesc *d, void *pkt, size_t len, time_t tleft)
75 {
76 return pxereadudp(d, pkt, len, tleft);
77 }
78
79 /*
80 * Send a packet and wait for a reply, with exponential backoff.
81 *
82 * The send routine must return the actual number of bytes written.
83 *
84 * The receive routine can indicate success by returning the number of
85 * bytes read; it can return 0 to indicate EOF; it can return -1 with a
86 * non-zero errno to indicate failure; finally, it can return -1 with a
87 * zero errno to indicate it isn't done yet.
88 */
89 ssize_t
90 sendrecv(struct iodesc *d, ssize_t (*sproc)(struct iodesc *, void *, size_t),
91 void *sbuf, size_t ssize,
92 ssize_t (*rproc)(struct iodesc *, void *, size_t, time_t),
93 void *rbuf, size_t rsize)
94 {
95 ssize_t cc;
96 time_t t, tmo, tlast;
97 long tleft;
98
99 #ifdef NET_DEBUG
100 if (debug)
101 printf("sendrecv: called\n");
102 #endif
103
104 tmo = MINTMO;
105 tlast = tleft = 0;
106 t = getsecs();
107 for (;;) {
108 if (tleft <= 0) {
109 if (tmo >= MAXTMO) {
110 errno = ETIMEDOUT;
111 return -1;
112 }
113 cc = (*sproc)(d, sbuf, ssize);
114 if (cc < 0 || (size_t)cc < ssize)
115 panic("sendrecv: short write! (%d < %d)",
116 cc, ssize);
117
118 tleft = tmo;
119 tmo <<= 1;
120 if (tmo > MAXTMO)
121 tmo = MAXTMO;
122 tlast = t;
123 }
124
125 /* Try to get a packet and process it. */
126 cc = (*rproc)(d, rbuf, rsize, tleft);
127 /* Return on data, EOF or real error. */
128 if (cc != -1 || errno != 0)
129 return (cc);
130
131 /* Timed out or didn't get the packet we're waiting for */
132 t = getsecs();
133 tleft -= t - tlast;
134 tlast = t;
135 }
136 }
137
138 /*
139 * Like inet_addr() in the C library, but we only accept base-10.
140 * Return values are in network order.
141 */
142 n_long
143 inet_addr(char *cp)
144 {
145 u_long val;
146 int n;
147 char c;
148 u_int parts[4];
149 u_int *pp = parts;
150
151 for (;;) {
152 /*
153 * Collect number up to ``.''.
154 * Values are specified as for C:
155 * 0x=hex, 0=octal, other=decimal.
156 */
157 val = 0;
158 while ((c = *cp) != '\0') {
159 if (c >= '0' && c <= '9') {
160 val = (val * 10) + (c - '0');
161 cp++;
162 continue;
163 }
164 break;
165 }
166 if (*cp == '.') {
167 /*
168 * Internet format:
169 * a.b.c.d
170 * a.b.c (with c treated as 16-bits)
171 * a.b (with b treated as 24 bits)
172 */
173 if (pp >= parts + 3 || val > 0xff)
174 goto bad;
175 *pp++ = val, cp++;
176 } else
177 break;
178 }
179 /*
180 * Check for trailing characters.
181 */
182 if (*cp != '\0')
183 goto bad;
184
185 /*
186 * Concoct the address according to
187 * the number of parts specified.
188 */
189 n = pp - parts + 1;
190 switch (n) {
191
192 case 1: /* a -- 32 bits */
193 break;
194
195 case 2: /* a.b -- 8.24 bits */
196 if (val > 0xffffff)
197 goto bad;
198 val |= parts[0] << 24;
199 break;
200
201 case 3: /* a.b.c -- 8.8.16 bits */
202 if (val > 0xffff)
203 goto bad;
204 val |= (parts[0] << 24) | (parts[1] << 16);
205 break;
206
207 case 4: /* a.b.c.d -- 8.8.8.8 bits */
208 if (val > 0xff)
209 goto bad;
210 val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
211 break;
212 }
213
214 return (htonl(val));
215 bad:
216 return (htonl(INADDR_NONE));
217 }
218
219 char *
220 inet_ntoa(struct in_addr ia)
221 {
222 return (intoa(ia.s_addr));
223 }
224
225 /* Similar to inet_ntoa() */
226 char *
227 intoa(n_long addr)
228 {
229 char *cp;
230 u_int byte;
231 int n;
232 static char buf[sizeof(".255.255.255.255")];
233
234 NTOHL(addr);
235 cp = &buf[sizeof buf];
236 *--cp = '\0';
237
238 n = 4;
239 do {
240 byte = addr & 0xff;
241 *--cp = byte % 10 + '0';
242 byte /= 10;
243 if (byte > 0) {
244 *--cp = byte % 10 + '0';
245 byte /= 10;
246 if (byte > 0)
247 *--cp = byte + '0';
248 }
249 *--cp = '.';
250 addr >>= 8;
251 } while (--n > 0);
252
253 return (cp+1);
254 }
255
256 static char *
257 number(char *s, int *n)
258 {
259 for (*n = 0; isdigit(*s); s++)
260 *n = (*n * 10) + *s - '0';
261 return s;
262 }
263
264 n_long
265 ip_convertaddr(char *p)
266 {
267 #define IP_ANYADDR 0
268 n_long addr = 0, n;
269
270 if (p == (char *)0 || *p == '\0')
271 return IP_ANYADDR;
272 p = number(p, &n);
273 addr |= (n << 24) & 0xff000000;
274 if (*p == '\0' || *p++ != '.')
275 return IP_ANYADDR;
276 p = number(p, &n);
277 addr |= (n << 16) & 0xff0000;
278 if (*p == '\0' || *p++ != '.')
279 return IP_ANYADDR;
280 p = number(p, &n);
281 addr |= (n << 8) & 0xff00;
282 if (*p == '\0' || *p++ != '.')
283 return IP_ANYADDR;
284 p = number(p, &n);
285 addr |= n & 0xff;
286 if (*p != '\0')
287 return IP_ANYADDR;
288
289 return htonl(addr);
290 }