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