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