summaryrefslogtreecommitdiff
path: root/src/lib/libc/net
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libc/net')
-rw-r--r--src/lib/libc/net/Makefile.inc85
-rw-r--r--src/lib/libc/net/base64.c318
-rw-r--r--src/lib/libc/net/byteorder.3183
-rw-r--r--src/lib/libc/net/ethers.3119
-rw-r--r--src/lib/libc/net/ethers.c272
-rw-r--r--src/lib/libc/net/freeaddrinfo.c49
-rw-r--r--src/lib/libc/net/gai_strerror.c76
-rw-r--r--src/lib/libc/net/getaddrinfo.3581
-rw-r--r--src/lib/libc/net/getaddrinfo.c1848
-rw-r--r--src/lib/libc/net/gethostbyname.3275
-rw-r--r--src/lib/libc/net/gethostnamadr.c1175
-rw-r--r--src/lib/libc/net/getifaddrs.3159
-rw-r--r--src/lib/libc/net/getifaddrs.c277
-rw-r--r--src/lib/libc/net/getnameinfo.3297
-rw-r--r--src/lib/libc/net/getnameinfo.c361
-rw-r--r--src/lib/libc/net/getnetbyaddr.c56
-rw-r--r--src/lib/libc/net/getnetbyname.c62
-rw-r--r--src/lib/libc/net/getnetent.3144
-rw-r--r--src/lib/libc/net/getnetent.c129
-rw-r--r--src/lib/libc/net/getnetnamadr.c391
-rw-r--r--src/lib/libc/net/getproto.c55
-rw-r--r--src/lib/libc/net/getprotoent.3134
-rw-r--r--src/lib/libc/net/getprotoent.c127
-rw-r--r--src/lib/libc/net/getprotoname.c62
-rw-r--r--src/lib/libc/net/getrrsetbyname.3166
-rw-r--r--src/lib/libc/net/getrrsetbyname.c508
-rw-r--r--src/lib/libc/net/getservbyname.c87
-rw-r--r--src/lib/libc/net/getservbyport.c60
-rw-r--r--src/lib/libc/net/getservent.3141
-rw-r--r--src/lib/libc/net/getservent.c129
-rw-r--r--src/lib/libc/net/herror.c121
-rw-r--r--src/lib/libc/net/htonl.c25
-rw-r--r--src/lib/libc/net/htons.c24
-rw-r--r--src/lib/libc/net/if_indextoname.3140
-rw-r--r--src/lib/libc/net/if_indextoname.c86
-rw-r--r--src/lib/libc/net/if_nameindex.c140
-rw-r--r--src/lib/libc/net/if_nametoindex.c81
-rw-r--r--src/lib/libc/net/inet.3349
-rw-r--r--src/lib/libc/net/inet6_option_space.3452
-rw-r--r--src/lib/libc/net/inet6_rthdr_space.3325
-rw-r--r--src/lib/libc/net/inet_addr.c187
-rw-r--r--src/lib/libc/net/inet_lnaof.c59
-rw-r--r--src/lib/libc/net/inet_makeaddr.c62
-rw-r--r--src/lib/libc/net/inet_net.3148
-rw-r--r--src/lib/libc/net/inet_net_ntop.c153
-rw-r--r--src/lib/libc/net/inet_net_pton.c206
-rw-r--r--src/lib/libc/net/inet_neta.c91
-rw-r--r--src/lib/libc/net/inet_netof.c58
-rw-r--r--src/lib/libc/net/inet_network.c92
-rw-r--r--src/lib/libc/net/inet_ntoa.c59
-rw-r--r--src/lib/libc/net/inet_ntop.c213
-rw-r--r--src/lib/libc/net/inet_pton.c222
-rw-r--r--src/lib/libc/net/ip6opt.c388
-rw-r--r--src/lib/libc/net/ipx.3127
-rw-r--r--src/lib/libc/net/ipx_addr.c228
-rw-r--r--src/lib/libc/net/ipx_ntoa.c58
-rw-r--r--src/lib/libc/net/iso_addr.3111
-rw-r--r--src/lib/libc/net/iso_addr.c119
-rw-r--r--src/lib/libc/net/link_addr.3131
-rw-r--r--src/lib/libc/net/linkaddr.c158
-rw-r--r--src/lib/libc/net/net_addrcmp.391
-rw-r--r--src/lib/libc/net/net_addrcmp.c68
-rw-r--r--src/lib/libc/net/ns.3131
-rw-r--r--src/lib/libc/net/ns_addr.c227
-rw-r--r--src/lib/libc/net/ns_ntoa.c104
-rw-r--r--src/lib/libc/net/nsap_addr.c109
-rw-r--r--src/lib/libc/net/ntohl.c25
-rw-r--r--src/lib/libc/net/ntohs.c24
-rw-r--r--src/lib/libc/net/rcmd.3270
-rw-r--r--src/lib/libc/net/rcmd.c733
-rw-r--r--src/lib/libc/net/rcmdsh.397
-rw-r--r--src/lib/libc/net/rcmdsh.c153
-rw-r--r--src/lib/libc/net/recv.c50
-rw-r--r--src/lib/libc/net/res_comp.c503
-rw-r--r--src/lib/libc/net/res_data.c117
-rw-r--r--src/lib/libc/net/res_debug.c1560
-rw-r--r--src/lib/libc/net/res_init.c639
-rw-r--r--src/lib/libc/net/res_mkquery.c242
-rw-r--r--src/lib/libc/net/res_query.c405
-rw-r--r--src/lib/libc/net/res_random.c229
-rw-r--r--src/lib/libc/net/res_send.c893
-rw-r--r--src/lib/libc/net/resolver.3345
-rw-r--r--src/lib/libc/net/rresvport.c118
-rw-r--r--src/lib/libc/net/rthdr.c310
-rw-r--r--src/lib/libc/net/send.c50
-rw-r--r--src/lib/libc/net/sethostent.c60
-rw-r--r--src/lib/libc/net/vars6.c42
87 files changed, 20534 insertions, 0 deletions
diff --git a/src/lib/libc/net/Makefile.inc b/src/lib/libc/net/Makefile.inc
new file mode 100644
index 0000000000..805ae5d224
--- /dev/null
+++ b/src/lib/libc/net/Makefile.inc
@@ -0,0 +1,85 @@
1# $OpenBSD: Makefile.inc,v 1.31 2001/08/06 14:40:47 jakob Exp $
2
3# net sources
4.PATH: ${LIBCSRCDIR}/arch/${MACHINE_ARCH}/net ${LIBCSRCDIR}/net
5
6CFLAGS+=-DRESOLVSORT
7
8SRCS+= base64.c freeaddrinfo.c gai_strerror.c getaddrinfo.c gethostnamadr.c \
9 getifaddrs.c getnameinfo.c getnetbyaddr.c getnetbyname.c getnetent.c \
10 getnetnamadr.c getproto.c getprotoent.c getprotoname.c \
11 getservbyname.c getservbyport.c getservent.c getrrsetbyname.c \
12 herror.c if_indextoname.c if_nameindex.c if_nametoindex.c inet_addr.c \
13 inet_lnaof.c inet_makeaddr.c inet_neta.c inet_netof.c inet_network.c \
14 inet_net_ntop.c inet_net_pton.c inet_ntoa.c inet_ntop.c inet_pton.c \
15 ipx_addr.c ipx_ntoa.c iso_addr.c linkaddr.c ns_addr.c ns_ntoa.c \
16 nsap_addr.c \
17 net_addrcmp.c \
18 rcmd.c rresvport.c recv.c res_comp.c res_data.c res_debug.c \
19 res_init.c res_mkquery.c res_query.c res_random.c res_send.c send.c \
20 sethostent.c ethers.c rcmdsh.c
21
22# IPv6
23SRCS+= ip6opt.c rthdr.c vars6.c
24
25# machine-dependent net sources
26# m-d Makefile.inc must include sources for:
27# htonl() htons() ntohl() ntohs()
28
29.include "${LIBCSRCDIR}/arch/${MACHINE_ARCH}/net/Makefile.inc"
30
31MAN+= byteorder.3 ethers.3 getaddrinfo.3 gethostbyname.3 getifaddrs.3 \
32 getnameinfo.3 getnetent.3 getprotoent.3 getservent.3 inet.3 \
33 if_indextoname.3 inet_net.3 iso_addr.3 link_addr.3 ns.3 ipx.3 \
34 rcmd.3 rcmdsh.3 resolver.3 net_addrcmp.3 \
35 inet6_option_space.3 inet6_rthdr_space.3 \
36 getrrsetbyname.3
37
38MLINKS+=byteorder.3 htonl.3 byteorder.3 htons.3 byteorder.3 ntohl.3 \
39 byteorder.3 ntohs.3 byteorder.3 htobe16.3 byteorder.3 htobe32.3 \
40 byteorder.3 betoh16.3 byteorder.3 betoh32.3 byteorder.3 htole16.3 \
41 byteorder.3 htole32.3 byteorder.3 letoh16.3 byteorder.3 letoh32.3 \
42 byteorder.3 swap16.3 byteorder.3 swap32.3
43MLINKS+=ethers.3 ether_aton.3 ethers.3 ether_hostton.3 ethers.3 ether_line.3 \
44 ethers.3 ether_ntoa.3 ethers.3 ether_ntohost.3 ethers.3 ether_addr.3
45MLINKS+= getaddrinfo.3 freeaddrinfo.3 getaddrinfo.3 gai_strerror.3
46MLINKS+=gethostbyname.3 endhostent.3 gethostbyname.3 gethostbyaddr.3 \
47 gethostbyname.3 sethostent.3 gethostbyname.3 gethostent.3 \
48 gethostbyname.3 herror.3 gethostbyname.3 gethostbyname2.3 \
49 gethostbyname.3 hstrerror.3
50MLINKS+=getifaddrs.3 freeifaddrs.3
51MLINKS+=getnetent.3 endnetent.3 getnetent.3 getnetbyaddr.3 \
52 getnetent.3 getnetbyname.3 getnetent.3 setnetent.3
53MLINKS+=getprotoent.3 endprotoent.3 getprotoent.3 getprotobyname.3 \
54 getprotoent.3 getprotobynumber.3 getprotoent.3 setprotoent.3
55MLINKS+=getservent.3 endservent.3 getservent.3 getservbyname.3 \
56 getservent.3 getservbyport.3 getservent.3 setservent.3
57MLINKS+= if_indextoname.3 if_nametoindex.3 if_indextoname.3 if_nameindex.3 \
58 if_indextoname.3 if_freenameindex.3
59MLINKS+=inet.3 addr.3 inet.3 inet_addr.3 inet.3 inet_aton.3 \
60 inet.3 inet_lnaof.3 inet.3 inet_makeaddr.3 inet.3 inet_netof.3 \
61 inet.3 inet_network.3 inet.3 inet_ntoa.3 inet.3 network.3 \
62 inet.3 ntoa.3 inet.3 inet_ntop.3 inet.3 inet_pton.3
63MLINKS+=inet_net.3 inet_net_ntop.3 inet_net.3 inet_net_pton.3
64MLINKS+=iso_addr.3 iso_ntoa.3
65MLINKS+=link_addr.3 link_ntoa.3
66MLINKS+=ipx.3 ipx_addr.3 ipx.3 ipx_ntoa.3
67MLINKS+=ns.3 ns_addr.3 ns.3 ns_ntoa.3
68MLINKS+=rcmd.3 iruserok.3 rcmd.3 rresvport.3 rcmd.3 ruserok.3 \
69 rcmd.3 rresvport_af.3 rcmd.3 rcmd_af.3 rcmd.3 iruserok_sa.3
70MLINKS+=resolver.3 dn_comp.3 resolver.3 dn_expand.3 resolver.3 res_init.3 \
71 resolver.3 res_mkquery.3 resolver.3 res_send.3 resolver.3 res_query.3 \
72 resolver.3 res_search.3
73MLINKS+=inet6_option_space.3 inet6_option_init.3 \
74 inet6_option_space.3 inet6_option_append.3 \
75 inet6_option_space.3 inet6_option_alloc.3 \
76 inet6_option_space.3 inet6_option_next.3 \
77 inet6_option_space.3 inet6_option_find.3
78MLINKS+=inet6_rthdr_space.3 inet6_rthdr_init.3 \
79 inet6_rthdr_space.3 inet6_rthdr_add.3 \
80 inet6_rthdr_space.3 inet6_rthdr_lasthop.3 \
81 inet6_rthdr_space.3 inet6_rthdr_reverse.3 \
82 inet6_rthdr_space.3 inet6_rthdr_segments.3 \
83 inet6_rthdr_space.3 inet6_rthdr_getaddr.3 \
84 inet6_rthdr_space.3 inet6_rthdr_getflags.3
85MLINKS+=getrrsetbyname.3 freerrset.3
diff --git a/src/lib/libc/net/base64.c b/src/lib/libc/net/base64.c
new file mode 100644
index 0000000000..33b6ffdc41
--- /dev/null
+++ b/src/lib/libc/net/base64.c
@@ -0,0 +1,318 @@
1/* $OpenBSD: base64.c,v 1.4 2002/01/02 23:00:10 deraadt Exp $ */
2
3/*
4 * Copyright (c) 1996 by Internet Software Consortium.
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
11 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
12 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
13 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
16 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
17 * SOFTWARE.
18 */
19
20/*
21 * Portions Copyright (c) 1995 by International Business Machines, Inc.
22 *
23 * International Business Machines, Inc. (hereinafter called IBM) grants
24 * permission under its copyrights to use, copy, modify, and distribute this
25 * Software with or without fee, provided that the above copyright notice and
26 * all paragraphs of this notice appear in all copies, and that the name of IBM
27 * not be used in connection with the marketing of any product incorporating
28 * the Software or modifications thereof, without specific, written prior
29 * permission.
30 *
31 * To the extent it has a right to do so, IBM grants an immunity from suit
32 * under its patents, if any, for the use, sale or manufacture of products to
33 * the extent that such products are used for performing Domain Name System
34 * dynamic updates in TCP/IP networks by means of the Software. No immunity is
35 * granted for any product per se or for any other function of any product.
36 *
37 * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
38 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
39 * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
40 * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
41 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
42 * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
43 */
44
45#include <sys/types.h>
46#include <sys/param.h>
47#include <sys/socket.h>
48#include <netinet/in.h>
49#include <arpa/inet.h>
50#include <arpa/nameser.h>
51
52#include <ctype.h>
53#include <resolv.h>
54#include <stdio.h>
55
56#include <stdlib.h>
57#include <string.h>
58
59/* XXX abort illegal in library */
60#define Assert(Cond) if (!(Cond)) abort()
61
62static const char Base64[] =
63 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
64static const char Pad64 = '=';
65
66/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
67 The following encoding technique is taken from RFC 1521 by Borenstein
68 and Freed. It is reproduced here in a slightly edited form for
69 convenience.
70
71 A 65-character subset of US-ASCII is used, enabling 6 bits to be
72 represented per printable character. (The extra 65th character, "=",
73 is used to signify a special processing function.)
74
75 The encoding process represents 24-bit groups of input bits as output
76 strings of 4 encoded characters. Proceeding from left to right, a
77 24-bit input group is formed by concatenating 3 8-bit input groups.
78 These 24 bits are then treated as 4 concatenated 6-bit groups, each
79 of which is translated into a single digit in the base64 alphabet.
80
81 Each 6-bit group is used as an index into an array of 64 printable
82 characters. The character referenced by the index is placed in the
83 output string.
84
85 Table 1: The Base64 Alphabet
86
87 Value Encoding Value Encoding Value Encoding Value Encoding
88 0 A 17 R 34 i 51 z
89 1 B 18 S 35 j 52 0
90 2 C 19 T 36 k 53 1
91 3 D 20 U 37 l 54 2
92 4 E 21 V 38 m 55 3
93 5 F 22 W 39 n 56 4
94 6 G 23 X 40 o 57 5
95 7 H 24 Y 41 p 58 6
96 8 I 25 Z 42 q 59 7
97 9 J 26 a 43 r 60 8
98 10 K 27 b 44 s 61 9
99 11 L 28 c 45 t 62 +
100 12 M 29 d 46 u 63 /
101 13 N 30 e 47 v
102 14 O 31 f 48 w (pad) =
103 15 P 32 g 49 x
104 16 Q 33 h 50 y
105
106 Special processing is performed if fewer than 24 bits are available
107 at the end of the data being encoded. A full encoding quantum is
108 always completed at the end of a quantity. When fewer than 24 input
109 bits are available in an input group, zero bits are added (on the
110 right) to form an integral number of 6-bit groups. Padding at the
111 end of the data is performed using the '=' character.
112
113 Since all base64 input is an integral number of octets, only the
114 -------------------------------------------------
115 following cases can arise:
116
117 (1) the final quantum of encoding input is an integral
118 multiple of 24 bits; here, the final unit of encoded
119 output will be an integral multiple of 4 characters
120 with no "=" padding,
121 (2) the final quantum of encoding input is exactly 8 bits;
122 here, the final unit of encoded output will be two
123 characters followed by two "=" padding characters, or
124 (3) the final quantum of encoding input is exactly 16 bits;
125 here, the final unit of encoded output will be three
126 characters followed by one "=" padding character.
127 */
128
129int
130b64_ntop(src, srclength, target, targsize)
131 u_char const *src;
132 size_t srclength;
133 char *target;
134 size_t targsize;
135{
136 size_t datalength = 0;
137 u_char input[3];
138 u_char output[4];
139 int i;
140
141 while (2 < srclength) {
142 input[0] = *src++;
143 input[1] = *src++;
144 input[2] = *src++;
145 srclength -= 3;
146
147 output[0] = input[0] >> 2;
148 output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
149 output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
150 output[3] = input[2] & 0x3f;
151 Assert(output[0] < 64);
152 Assert(output[1] < 64);
153 Assert(output[2] < 64);
154 Assert(output[3] < 64);
155
156 if (datalength + 4 > targsize)
157 return (-1);
158 target[datalength++] = Base64[output[0]];
159 target[datalength++] = Base64[output[1]];
160 target[datalength++] = Base64[output[2]];
161 target[datalength++] = Base64[output[3]];
162 }
163
164 /* Now we worry about padding. */
165 if (0 != srclength) {
166 /* Get what's left. */
167 input[0] = input[1] = input[2] = '\0';
168 for (i = 0; i < srclength; i++)
169 input[i] = *src++;
170
171 output[0] = input[0] >> 2;
172 output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
173 output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
174 Assert(output[0] < 64);
175 Assert(output[1] < 64);
176 Assert(output[2] < 64);
177
178 if (datalength + 4 > targsize)
179 return (-1);
180 target[datalength++] = Base64[output[0]];
181 target[datalength++] = Base64[output[1]];
182 if (srclength == 1)
183 target[datalength++] = Pad64;
184 else
185 target[datalength++] = Base64[output[2]];
186 target[datalength++] = Pad64;
187 }
188 if (datalength >= targsize)
189 return (-1);
190 target[datalength] = '\0'; /* Returned value doesn't count \0. */
191 return (datalength);
192}
193
194/* skips all whitespace anywhere.
195 converts characters, four at a time, starting at (or after)
196 src from base - 64 numbers into three 8 bit bytes in the target area.
197 it returns the number of data bytes stored at the target, or -1 on error.
198 */
199
200int
201b64_pton(src, target, targsize)
202 char const *src;
203 u_char *target;
204 size_t targsize;
205{
206 int tarindex, state, ch;
207 char *pos;
208
209 state = 0;
210 tarindex = 0;
211
212 while ((ch = *src++) != '\0') {
213 if (isspace(ch)) /* Skip whitespace anywhere. */
214 continue;
215
216 if (ch == Pad64)
217 break;
218
219 pos = strchr(Base64, ch);
220 if (pos == 0) /* A non-base64 character. */
221 return (-1);
222
223 switch (state) {
224 case 0:
225 if (target) {
226 if (tarindex >= targsize)
227 return (-1);
228 target[tarindex] = (pos - Base64) << 2;
229 }
230 state = 1;
231 break;
232 case 1:
233 if (target) {
234 if (tarindex + 1 >= targsize)
235 return (-1);
236 target[tarindex] |= (pos - Base64) >> 4;
237 target[tarindex+1] = ((pos - Base64) & 0x0f)
238 << 4 ;
239 }
240 tarindex++;
241 state = 2;
242 break;
243 case 2:
244 if (target) {
245 if (tarindex + 1 >= targsize)
246 return (-1);
247 target[tarindex] |= (pos - Base64) >> 2;
248 target[tarindex+1] = ((pos - Base64) & 0x03)
249 << 6;
250 }
251 tarindex++;
252 state = 3;
253 break;
254 case 3:
255 if (target) {
256 if (tarindex >= targsize)
257 return (-1);
258 target[tarindex] |= (pos - Base64);
259 }
260 tarindex++;
261 state = 0;
262 break;
263 }
264 }
265
266 /*
267 * We are done decoding Base-64 chars. Let's see if we ended
268 * on a byte boundary, and/or with erroneous trailing characters.
269 */
270
271 if (ch == Pad64) { /* We got a pad char. */
272 ch = *src++; /* Skip it, get next. */
273 switch (state) {
274 case 0: /* Invalid = in first position */
275 case 1: /* Invalid = in second position */
276 return (-1);
277
278 case 2: /* Valid, means one byte of info */
279 /* Skip any number of spaces. */
280 for (; ch != '\0'; ch = *src++)
281 if (!isspace(ch))
282 break;
283 /* Make sure there is another trailing = sign. */
284 if (ch != Pad64)
285 return (-1);
286 ch = *src++; /* Skip the = */
287 /* Fall through to "single trailing =" case. */
288 /* FALLTHROUGH */
289
290 case 3: /* Valid, means two bytes of info */
291 /*
292 * We know this char is an =. Is there anything but
293 * whitespace after it?
294 */
295 for (; ch != '\0'; ch = *src++)
296 if (!isspace(ch))
297 return (-1);
298
299 /*
300 * Now make sure for cases 2 and 3 that the "extra"
301 * bits that slopped past the last full byte were
302 * zeros. If we don't check them, they become a
303 * subliminal channel.
304 */
305 if (target && target[tarindex] != 0)
306 return (-1);
307 }
308 } else {
309 /*
310 * We ended by seeing the end of the string. Make sure we
311 * have no partial bytes lying around.
312 */
313 if (state != 0)
314 return (-1);
315 }
316
317 return (tarindex);
318}
diff --git a/src/lib/libc/net/byteorder.3 b/src/lib/libc/net/byteorder.3
new file mode 100644
index 0000000000..9d8fa7221f
--- /dev/null
+++ b/src/lib/libc/net/byteorder.3
@@ -0,0 +1,183 @@
1.\" $OpenBSD: byteorder.3,v 1.8 2000/04/18 03:01:30 aaron Exp $
2.\"
3.\" Copyright (c) 1983, 1991, 1993
4.\" The Regents of the University of California. All rights reserved.
5.\"
6.\" Redistribution and use in source and binary forms, with or without
7.\" modification, are permitted provided that the following conditions
8.\" are met:
9.\" 1. Redistributions of source code must retain the above copyright
10.\" notice, this list of conditions and the following disclaimer.
11.\" 2. Redistributions in binary form must reproduce the above copyright
12.\" notice, this list of conditions and the following disclaimer in the
13.\" documentation and/or other materials provided with the distribution.
14.\" 3. All advertising materials mentioning features or use of this software
15.\" must display the following acknowledgement:
16.\" This product includes software developed by the University of
17.\" California, Berkeley and its contributors.
18.\" 4. Neither the name of the University nor the names of its contributors
19.\" may be used to endorse or promote products derived from this software
20.\" without specific prior written permission.
21.\"
22.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32.\" SUCH DAMAGE.
33.\"
34.Dd June 4, 1993
35.Dt BYTEORDER 3
36.Os
37.Sh NAME
38.Nm htonl ,
39.Nm htons ,
40.Nm ntohl ,
41.Nm ntohs ,
42.Nm htobe32 ,
43.Nm htobe16 ,
44.Nm betoh32 ,
45.Nm betoh16 ,
46.Nm htole32 ,
47.Nm htole16 ,
48.Nm letoh32 ,
49.Nm letoh16 ,
50.Nm swap32 ,
51.Nm swap16
52.Nd convert values between different byte orderings
53.Sh SYNOPSIS
54.Fd #include <sys/types.h>
55.Fd #include <machine/endian.h>
56.Ft u_int32_t
57.Fn htonl "u_int32_t host32"
58.Ft u_int16_t
59.Fn htons "u_int16_t host16"
60.Ft u_int32_t
61.Fn ntohl "u_int32_t net32"
62.Ft u_int16_t
63.Fn ntohs "u_int16_t net16"
64.Ft u_int32_t
65.Fn htobe32 "u_int32_t host32"
66.Ft u_int16_t
67.Fn htobe16 "u_int16_t host16"
68.Ft u_int32_t
69.Fn betoh32 "u_int32_t big32"
70.Ft u_int16_t
71.Fn betoh16 "u_int16_t big16"
72.Ft u_int32_t
73.Fn htole32 "u_int32_t host32"
74.Ft u_int16_t
75.Fn htole16 "u_int16_t host16"
76.Ft u_int32_t
77.Fn letoh32 "u_int32_t little32"
78.Ft u_int16_t
79.Fn letoh16 "u_int16_t little16"
80.Ft u_int32_t
81.Fn swap32 "u_int32_t val32"
82.Ft u_int16_t
83.Fn swap16 "u_int16_t val16"
84.Sh DESCRIPTION
85These routines convert 16- and 32-bit quantities between different
86byte orderings.
87The
88.Dq swap
89functions reverse the byte ordering of
90the given quantity, the others converts either from/to the native
91byte order used by the host to/from either little- or big-endian (a.k.a
92network) order.
93.Pp
94Apart from the swap functions, the names can be described by this form:
95{src-order}to{dst-order}{size}.
96Both {src-order} and {dst-order} can take the following forms:
97.Pp
98.Bl -tag -width "be " -offset indent -compact
99.It h
100Host order.
101.It n
102Network order (big-endian).
103.It be
104Big-endian (most significant byte first).
105.It le
106Little-endian (least significant byte first).
107.El
108.Pp
109One of the specified orderings must be
110.Sq h .
111{size} will take these forms:
112.Pp
113.Bl -tag -width "32 " -offset indent -compact
114.It l
115Long (32-bit, used in conjunction with forms involving
116.Sq n ) .
117.It s
118Short (16-bit, used in conjunction with forms involving
119.Sq n ) .
120.It 16
12116-bit.
122.It 32
12332-bit.
124.El
125.Pp
126The swap functions are of the form: swap{size}.
127.Pp
128Names involving
129.Sq n
130convert quantities between network
131byte order and host byte order.
132The last letter
133.Pf ( Sq s
134or
135.Sq l )
136is a mnemonic
137for the traditional names for such quantities,
138.Li short
139and
140.Li long ,
141respectively.
142Today, the C concept of
143.Li short
144and
145.Li long
146integers need not coincide with this traditional misunderstanding.
147On machines which have a byte order which is the same as the network
148order, routines are defined as null macros.
149.Pp
150The functions involving either
151.Dq be ,
152.Dq le ,
153or
154.Dq swap
155use the numbers
15616 and 32 for specifying the bitwidth of the quantities they operate on.
157Currently all supported architectures are either big- or little-endian
158so either the
159.Dq be
160or
161.Dq le
162variants are implemented as null macros.
163.Pp
164The routines mentioned above which have either {src-order} or {dst-order}
165set to
166.Sq n
167are most often used in
168conjunction with Internet addresses and ports as returned by
169.Xr gethostbyname 3
170and
171.Xr getservent 3 .
172.Sh SEE ALSO
173.Xr gethostbyname 3 ,
174.Xr getservent 3
175.Sh HISTORY
176The
177.Nm byteorder
178functions appeared in
179.Bx 4.2 .
180.Sh BUGS
181On the vax, alpha, i386, and so far mips,
182bytes are handled backwards from most everyone else in the world.
183This is not expected to be fixed in the near future.
diff --git a/src/lib/libc/net/ethers.3 b/src/lib/libc/net/ethers.3
new file mode 100644
index 0000000000..0509c121b8
--- /dev/null
+++ b/src/lib/libc/net/ethers.3
@@ -0,0 +1,119 @@
1.\" $OpenBSD: ethers.3,v 1.14 2001/08/06 10:42:26 mpech Exp $
2.\"
3.\" Written by roland@frob.com. Public domain.
4.\"
5.Dd December 16, 1993
6.Dt ETHERS 3
7.Os
8.Sh NAME
9.Nm ether_aton ,
10.Nm ether_ntoa ,
11.Nm ether_addr ,
12.Nm ether_ntohost ,
13.Nm ether_hostton ,
14.Nm ether_line
15.Nd get ethers entry
16.Sh SYNOPSIS
17.Fd #include <netinet/if_ether.h>
18.Ft char *
19.Fn ether_ntoa "struct ether_addr *e"
20.Ft struct ether_addr *
21.Fn ether_aton "char *s"
22.Ft int
23.Fn ether_ntohost "char *hostname" "struct ether_addr *e"
24.Ft int
25.Fn ether_hostton "char *hostname" "struct ether_addr *e"
26.Ft int
27.Fn ether_line "char *l" "struct ether_addr *e" "char *hostname"
28.Sh DESCRIPTION
29Ethernet addresses are represented by the
30following structure:
31.Bd -literal -offset indent
32struct ether_addr {
33 u_int8_t ether_addr_octet[6];
34};
35.Ed
36.Pp
37The
38.Fn ether_ntoa
39function converts this structure into an
40.Tn ASCII
41string of the form
42.Dq xx:xx:xx:xx:xx:xx ,
43consisting of 6 hexadecimal numbers separated
44by colons.
45It returns a pointer to a static buffer that is reused for each call.
46The
47.Fn ether_aton
48converts an
49.Tn ASCII
50string of the same form and to a structure
51containing the 6 octets of the address.
52It returns a pointer to a static structure that is reused for each call.
53.Pp
54The
55.Fn ether_ntohost
56and
57.Fn ether_hostton
58functions interrogate the database mapping host names to Ethernet
59addresses,
60.Pa /etc/ethers .
61The
62.Fn ether_ntohost
63function looks up the given Ethernet address and writes the associated
64host name into the character buffer passed.
65This buffer should be
66.Dv MAXHOSTNAMELEN
67characters in size.
68The
69.Fn ether_hostton
70function looks up the given host name and writes the associated
71Ethernet address into the structure passed.
72Both functions return
73zero if they find the requested host name or address, and \-1 if not.
74.Pp
75Each call reads
76.Pa /etc/ethers
77from the beginning; if a
78.Ql +
79appears alone on a line in the file, then
80.Fn ether_hostton
81will consult the
82.Pa ethers.byname
83YP map, and
84.Fn ether_ntohost
85will consult the
86.Pa ethers.byaddr
87YP map.
88.Pp
89The
90.Fn ether_line
91function parses a line from the
92.Pa /etc/ethers
93file and fills in the passed
94.Li struct ether_addr
95and character buffer with the Ethernet address and host name on the line.
96It returns zero if the line was successfully parsed and \-1 if not.
97The character buffer should be
98.Dv MAXHOSTNAMELEN
99characters in size.
100.Sh FILES
101.Bl -tag -width /etc/ethers -compact
102.It Pa /etc/ethers
103.El
104.Sh SEE ALSO
105.Xr ethers 5
106.Sh HISTORY
107The
108.Fn ether_ntoa ,
109.Fn ether_aton ,
110.Fn ether_ntohost ,
111.Fn ether_hostton ,
112and
113.Fn ether_line
114functions were adopted from SunOS and appeared in
115.Nx 0.9 b.
116.Sh BUGS
117The data space used by these functions is static; if future use
118requires the data, it should be copied before any subsequent calls to
119these functions overwrite it.
diff --git a/src/lib/libc/net/ethers.c b/src/lib/libc/net/ethers.c
new file mode 100644
index 0000000000..858ac5b3f3
--- /dev/null
+++ b/src/lib/libc/net/ethers.c
@@ -0,0 +1,272 @@
1/* $OpenBSD: ethers.c,v 1.14 2002/05/24 21:22:37 deraadt Exp $ */
2
3/*
4 * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
19 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
20 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
27 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/*
31 * ethers(3) a la Sun.
32 * Originally Written by Roland McGrath <roland@frob.com> 10/14/93.
33 * Substantially modified by Todd C. Miller <Todd.Miller@courtesan.com>
34 */
35
36#if defined(LIBC_SCCS) && !defined(lint)
37static char rcsid[] = "$OpenBSD: ethers.c,v 1.14 2002/05/24 21:22:37 deraadt Exp $";
38#endif /* LIBC_SCCS and not lint */
39
40#include <sys/types.h>
41#include <sys/socket.h>
42#include <net/if.h>
43#include <netinet/in.h>
44#include <netinet/if_ether.h>
45#include <sys/param.h>
46#include <paths.h>
47#include <errno.h>
48#include <stdio.h>
49#include <stdlib.h>
50#include <string.h>
51#include <ctype.h>
52#ifdef YP
53#include <rpcsvc/ypclnt.h>
54#endif
55
56#ifndef _PATH_ETHERS
57#define _PATH_ETHERS "/etc/ethers"
58#endif
59
60static char * _ether_aton(char *, struct ether_addr *);
61
62char *
63ether_ntoa(e)
64 struct ether_addr *e;
65{
66 static char a[] = "xx:xx:xx:xx:xx:xx";
67
68 if (e->ether_addr_octet[0] > 0xFF || e->ether_addr_octet[1] > 0xFF ||
69 e->ether_addr_octet[2] > 0xFF || e->ether_addr_octet[3] > 0xFF ||
70 e->ether_addr_octet[4] > 0xFF || e->ether_addr_octet[5] > 0xFF) {
71 errno = EINVAL;
72 return (NULL);
73 }
74
75 (void)snprintf(a, sizeof a, "%02x:%02x:%02x:%02x:%02x:%02x",
76 e->ether_addr_octet[0], e->ether_addr_octet[1],
77 e->ether_addr_octet[2], e->ether_addr_octet[3],
78 e->ether_addr_octet[4], e->ether_addr_octet[5]);
79
80 return (a);
81}
82
83static char *
84_ether_aton(s, e)
85 char *s;
86 struct ether_addr *e;
87{
88 int i;
89 long l;
90 char *pp;
91
92 while (isspace(*s))
93 s++;
94
95 /* expect 6 hex octets separated by ':' or space/NUL if last octet */
96 for (i = 0; i < 6; i++) {
97 l = strtol(s, &pp, 16);
98 if (pp == s || l > 0xFF || l < 0)
99 return (NULL);
100 if (!(*pp == ':' || (i == 5 && (isspace(*pp) || *pp == '\0'))))
101 return (NULL);
102 e->ether_addr_octet[i] = (u_char)l;
103 s = pp + 1;
104 }
105
106 /* return character after the octets ala strtol(3) */
107 return (pp);
108}
109
110struct ether_addr *
111ether_aton(s)
112 char *s;
113{
114 static struct ether_addr n;
115
116 return (_ether_aton(s, &n) ? &n : NULL);
117}
118
119int
120ether_ntohost(hostname, e)
121 char *hostname;
122 struct ether_addr *e;
123{
124 FILE *f;
125 char buf[BUFSIZ+1], *p;
126 size_t len;
127 struct ether_addr try;
128#ifdef YP
129 char trybuf[sizeof("xx:xx:xx:xx:xx:xx")];
130 int trylen;
131#endif
132
133 if (e->ether_addr_octet[0] > 0xFF || e->ether_addr_octet[1] > 0xFF ||
134 e->ether_addr_octet[2] > 0xFF || e->ether_addr_octet[3] > 0xFF ||
135 e->ether_addr_octet[4] > 0xFF || e->ether_addr_octet[5] > 0xFF) {
136 errno = EINVAL;
137 return (-1);
138 }
139
140#ifdef YP
141 snprintf(trybuf, sizeof trybuf, "%x:%x:%x:%x:%x:%x",
142 e->ether_addr_octet[0], e->ether_addr_octet[1],
143 e->ether_addr_octet[2], e->ether_addr_octet[3],
144 e->ether_addr_octet[4], e->ether_addr_octet[5]);
145 trylen = strlen(trybuf);
146#endif
147
148 f = fopen(_PATH_ETHERS, "r");
149 if (f == NULL)
150 return (-1);
151 while ((p = fgetln(f, &len)) != NULL) {
152 if (p[len-1] == '\n')
153 len--;
154 if (len > sizeof(buf) - 2)
155 continue;
156 (void)memcpy(buf, p, len);
157 buf[len] = '\n'; /* code assumes newlines later on */
158 buf[len+1] = '\0';
159#ifdef YP
160 /* A + in the file means try YP now. */
161 if (!strncmp(buf, "+\n", sizeof(buf))) {
162 char *ypbuf, *ypdom;
163 int ypbuflen;
164
165 if (yp_get_default_domain(&ypdom))
166 continue;
167 if (yp_match(ypdom, "ethers.byaddr", trybuf,
168 trylen, &ypbuf, &ypbuflen))
169 continue;
170 if (ether_line(ypbuf, &try, hostname) == 0) {
171 free(ypbuf);
172 (void)fclose(f);
173 return (0);
174 }
175 free(ypbuf);
176 continue;
177 }
178#endif
179 if (ether_line(buf, &try, hostname) == 0 &&
180 memcmp((void *)&try, (void *)e, sizeof(try)) == 0) {
181 (void)fclose(f);
182 return (0);
183 }
184 }
185 (void)fclose(f);
186 errno = ENOENT;
187 return (-1);
188}
189
190int
191ether_hostton(hostname, e)
192 char *hostname;
193 struct ether_addr *e;
194{
195 FILE *f;
196 char buf[BUFSIZ+1], *p;
197 char try[MAXHOSTNAMELEN];
198 size_t len;
199#ifdef YP
200 int hostlen = strlen(hostname);
201#endif
202
203 f = fopen(_PATH_ETHERS, "r");
204 if (f==NULL)
205 return (-1);
206
207 while ((p = fgetln(f, &len)) != NULL) {
208 if (p[len-1] == '\n')
209 len--;
210 if (len > sizeof(buf) - 2)
211 continue;
212 memcpy(buf, p, len);
213 buf[len] = '\n'; /* code assumes newlines later on */
214 buf[len+1] = '\0';
215#ifdef YP
216 /* A + in the file means try YP now. */
217 if (!strncmp(buf, "+\n", sizeof(buf))) {
218 char *ypbuf, *ypdom;
219 int ypbuflen;
220
221 if (yp_get_default_domain(&ypdom))
222 continue;
223 if (yp_match(ypdom, "ethers.byname", hostname, hostlen,
224 &ypbuf, &ypbuflen))
225 continue;
226 if (ether_line(ypbuf, e, try) == 0) {
227 free(ypbuf);
228 (void)fclose(f);
229 return (0);
230 }
231 free(ypbuf);
232 continue;
233 }
234#endif
235 if (ether_line(buf, e, try) == 0 && strcmp(hostname, try) == 0) {
236 (void)fclose(f);
237 return (0);
238 }
239 }
240 (void)fclose(f);
241 errno = ENOENT;
242 return (-1);
243}
244
245int
246ether_line(line, e, hostname)
247 char *line;
248 struct ether_addr *e;
249 char *hostname;
250{
251 char *p;
252 size_t n;
253
254 /* Parse "xx:xx:xx:xx:xx:xx" */
255 if ((p = _ether_aton(line, e)) == NULL || (*p != ' ' && *p != '\t'))
256 goto bad;
257
258 /* Now get the hostname */
259 while (isspace(*p))
260 p++;
261 if (*p == '\0')
262 goto bad;
263 n = strcspn(p, " \t\n");
264 if (n >= MAXHOSTNAMELEN)
265 goto bad;
266 strlcpy(hostname, p, n + 1);
267 return (0);
268
269bad:
270 errno = EINVAL;
271 return (-1);
272}
diff --git a/src/lib/libc/net/freeaddrinfo.c b/src/lib/libc/net/freeaddrinfo.c
new file mode 100644
index 0000000000..30fbecb805
--- /dev/null
+++ b/src/lib/libc/net/freeaddrinfo.c
@@ -0,0 +1,49 @@
1/*
2 * Copyright (c) 1996, 1997, 1998, 1999, Craig Metz, All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. All advertising materials mentioning features or use of this software
13 * must display the following acknowledgement:
14 * This product includes software developed by Craig Metz and
15 * by other contributors.
16 * 4. Neither the name of the author nor the names of contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#include <stdlib.h>
34#include <netdb.h>
35
36void
37freeaddrinfo(ai)
38 struct addrinfo *ai;
39{
40 struct addrinfo *p;
41
42 do {
43 p = ai;
44 ai = ai->ai_next;
45 if (p->ai_canonname)
46 free(p->ai_canonname);
47 free((void *)p);
48 } while (ai);
49}
diff --git a/src/lib/libc/net/gai_strerror.c b/src/lib/libc/net/gai_strerror.c
new file mode 100644
index 0000000000..a191cb5b28
--- /dev/null
+++ b/src/lib/libc/net/gai_strerror.c
@@ -0,0 +1,76 @@
1/* $OpenBSD: gai_strerror.c,v 1.5 2001/06/05 02:31:34 deraadt Exp $ */
2
3/*
4 * Copyright (c) 1997-1999, Craig Metz, All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed by Craig Metz and
17 * by other contributors.
18 * 4. Neither the name of the author nor the names of contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35/* gai_strerror() v1.38 */
36
37#include <sys/types.h>
38#include <netdb.h>
39#include <errno.h>
40
41char *
42gai_strerror(int errnum)
43{
44 switch (errnum) {
45 case 0:
46 return "no error";
47 case EAI_BADFLAGS:
48 return "invalid value for ai_flags";
49 case EAI_NONAME:
50 return "name or service is not known";
51 case EAI_AGAIN:
52 return "temporary failure in name resolution";
53 case EAI_FAIL:
54 return "non-recoverable failure in name resolution";
55 case EAI_NODATA:
56 return "no address associated with name";
57 case EAI_FAMILY:
58 return "ai_family not supported";
59 case EAI_SOCKTYPE:
60 return "ai_socktype not supported";
61 case EAI_SERVICE:
62 return "service not supported for ai_socktype";
63 case EAI_ADDRFAMILY:
64 return "address family for name not supported";
65 case EAI_MEMORY:
66 return "memory allocation failure";
67 case EAI_SYSTEM:
68 return "system error";
69 case EAI_BADHINTS:
70 return "invalid value for hints";
71 case EAI_PROTOCOL:
72 return "resolved protocol is unknown";
73 default:
74 return "unknown/invalid error";
75 }
76}
diff --git a/src/lib/libc/net/getaddrinfo.3 b/src/lib/libc/net/getaddrinfo.3
new file mode 100644
index 0000000000..5c4be16732
--- /dev/null
+++ b/src/lib/libc/net/getaddrinfo.3
@@ -0,0 +1,581 @@
1.\" $OpenBSD: getaddrinfo.3,v 1.20 2002/04/30 16:31:42 mpech Exp $
2.\" $KAME: getaddrinfo.3,v 1.29 2001/02/12 09:24:45 itojun Exp $
3.\"
4.\" Copyright (c) 1983, 1987, 1991, 1993
5.\" The Regents of the University of California. All rights reserved.
6.\"
7.\" Redistribution and use in source and binary forms, with or without
8.\" modification, are permitted provided that the following conditions
9.\" are met:
10.\" 1. Redistributions of source code must retain the above copyright
11.\" notice, this list of conditions and the following disclaimer.
12.\" 2. Redistributions in binary form must reproduce the above copyright
13.\" notice, this list of conditions and the following disclaimer in the
14.\" documentation and/or other materials provided with the distribution.
15.\" 3. All advertising materials mentioning features or use of this software
16.\" must display the following acknowledgement:
17.\" This product includes software developed by the University of
18.\" California, Berkeley and its contributors.
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.\" From: @(#)gethostbyname.3 8.4 (Berkeley) 5/25/95
36.\"
37.Dd May 25, 1995
38.Dt GETADDRINFO 3
39.Os
40.\"
41.Sh NAME
42.Nm getaddrinfo ,
43.Nm freeaddrinfo ,
44.Nm gai_strerror
45.Nd nodename-to-address translation in protocol-independent manner
46.\"
47.Sh SYNOPSIS
48.Fd #include <sys/types.h>
49.Fd #include <sys/socket.h>
50.Fd #include <netdb.h>
51.Ft int
52.Fn getaddrinfo "const char *nodename" "const char *servname" \
53"const struct addrinfo *hints" "struct addrinfo **res"
54.Ft void
55.Fn freeaddrinfo "struct addrinfo *ai"
56.Ft "char *"
57.Fn gai_strerror "int ecode"
58.\"
59.Sh DESCRIPTION
60The
61.Fn getaddrinfo
62function is defined for protocol-independent nodename-to-address translation.
63It performs the functionality of
64.Xr gethostbyname 3
65and
66.Xr getservbyname 3 ,
67but in a more sophisticated manner.
68.Pp
69The
70.Li addrinfo
71structure is defined as a result of including the
72.Aq Pa netdb.h
73header:
74.Bd -literal -offset
75struct addrinfo { *
76 int ai_flags; /* AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST */
77 int ai_family; /* PF_xxx */
78 int ai_socktype; /* SOCK_xxx */
79 int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
80 size_t ai_addrlen; /* length of ai_addr */
81 char *ai_canonname; /* canonical name for nodename */
82 struct sockaddr *ai_addr; /* binary address */
83 struct addrinfo *ai_next; /* next structure in linked list */
84};
85.Ed
86.Pp
87The
88.Fa nodename
89and
90.Fa servname
91arguments are pointers to NUL-terminated strings or
92.Dv NULL .
93One or both of these two arguments must be a non-null pointer.
94In the normal client scenario, both the
95.Fa nodename
96and
97.Fa servname
98are specified.
99In the normal server scenario, only the
100.Fa servname
101is specified.
102A non-null
103.Fa nodename
104string can be either a node name or a numeric host address string
105(i.e., a dotted-decimal IPv4 address or an IPv6 hex address).
106A non-null
107.Fa servname
108string can be either a service name or a decimal port number.
109.Pp
110The caller can optionally pass an
111.Li addrinfo
112structure, pointed to by the third argument,
113to provide hints concerning the type of socket that the caller supports.
114In this
115.Fa hints
116structure all members other than
117.Fa ai_flags ,
118.Fa ai_family ,
119.Fa ai_socktype ,
120and
121.Fa ai_protocol
122must be zero or a null pointer.
123A value of
124.Dv PF_UNSPEC
125for
126.Fa ai_family
127means the caller will accept any protocol family.
128A value of 0 for
129.Fa ai_socktype
130means the caller will accept any socket type.
131A value of 0 for
132.Fa ai_protocol
133means the caller will accept any protocol.
134For example, if the caller handles only TCP and not UDP, then the
135.Fa ai_socktype
136member of the hints structure should be set to
137.Dv SOCK_STREAM
138when
139.Fn getaddrinfo
140is called.
141If the caller handles only IPv4 and not IPv6, then the
142.Fa ai_family
143member of the
144.Fa hints
145structure should be set to
146.Dv PF_INET
147when
148.Fn getaddrinfo
149is called.
150If the third argument to
151.Fn getaddrinfo
152is a null pointer, this is the same as if the caller had filled in an
153.Li addrinfo
154structure initialized to zero with
155.Fa ai_family
156set to
157.Dv PF_UNSPEC .
158.Pp
159Upon successful return a pointer to a linked list of one or more
160.Li addrinfo
161structures is returned through the final argument.
162The caller can process each
163.Li addrinfo
164structure in this list by following the
165.Fa ai_next
166pointer, until a null pointer is encountered.
167In each returned
168.Li addrinfo
169structure the three members
170.Fa ai_family ,
171.Fa ai_socktype ,
172and
173.Fa ai_protocol
174are the corresponding arguments for a call to the
175.Fn socket
176function.
177In each
178.Li addrinfo
179structure the
180.Fa ai_addr
181member points to a filled-in socket address structure whose length is
182specified by the
183.Fa ai_addrlen
184member.
185.Pp
186If the
187.Dv AI_PASSIVE
188bit is set in the
189.Fa ai_flags
190member of the
191.Fa hints
192structure, then the caller plans to use the returned socket address
193structure in a call to
194.Fn bind .
195In this case, if the
196.Fa nodename
197argument is a null pointer, then the IP address portion of the socket
198address structure will be set to
199.Dv INADDR_ANY
200for an IPv4 address or
201.Dv IN6ADDR_ANY_INIT
202for an IPv6 address.
203.Pp
204If the
205.Dv AI_PASSIVE
206bit is not set in the
207.Fa ai_flags
208member of the
209.Fa hints
210structure, then the returned socket address structure will be ready for a
211call to
212.Fn connect
213.Pq for a connection-oriented protocol
214or either
215.Fn connect ,
216.Fn sendto ,
217or
218.Fn sendmsg
219.Pq for a connectionless protocol .
220In this case, if the
221.Fa nodename
222argument is a null pointer, then the IP address portion of the
223socket address structure will be set to the loopback address.
224.Pp
225If the
226.Dv AI_CANONNAME
227bit is set in the
228.Fa ai_flags
229member of the
230.Fa hints
231structure, then upon successful return the
232.Fa ai_canonname
233member of the first
234.Li addrinfo
235structure in the linked list will point to a NUL-terminated string
236containing the canonical name of the specified
237.Fa nodename .
238.Pp
239If the
240.Dv AI_NUMERICHOST
241bit is set in the
242.Fa ai_flags
243member of the
244.Fa hints
245structure, then a non-null
246.Fa nodename
247string must be a numeric host address string.
248Otherwise an error of
249.Dv EAI_NONAME
250is returned.
251This flag prevents any type of name resolution service (e.g., the DNS)
252from being called.
253.Pp
254The arguments to
255.Fn getaddrinfo
256must sufficiently be consistent and unambiguous.
257Here are pitfall cases you may encounter:
258.Bl -bullet
259.It
260.Fn getaddrinfo
261will raise an error if members of the
262.Fa hints
263structure are not consistent.
264For example, for internet address families,
265.Fn getaddrinfo
266will raise an error if you specify
267.Dv SOCK_STREAM
268to
269.Fa ai_socktype
270while you specify
271.Dv IPPROTO_UDP
272to
273.Fa ai_protocol .
274.It
275If you specify a
276.Fa servname
277which is defined only for certain
278.Fa ai_socktype ,
279.Fn getaddrinfo
280will raise an error because the arguments are not consistent.
281For example,
282.Fn getaddrinfo
283will raise an error if you ask for
284.Dq Li tftp
285service on
286.Dv SOCK_STREAM .
287.It
288For internet address families, if you specify
289.Fa servname
290while you set
291.Fa ai_socktype
292to
293.Dv SOCK_RAW ,
294.Fn getaddrinfo
295will raise an error, because service names are not defined for the internet
296.Dv SOCK_RAW
297space.
298.It
299If you specify a numeric
300.Fa servname ,
301while leaving
302.Fa ai_socktype
303and
304.Fa ai_protocol
305unspecified,
306.Fn getaddrinfo
307will raise an error.
308This is because the numeric
309.Fa servname
310does not identify any socket type, and
311.Fn getaddrinfo
312is not allowed to glob the argument in such case.
313.El
314.Pp
315All of the information returned by
316.Fn getaddrinfo
317is dynamically allocated:
318the
319.Li addrinfo
320structures, the socket address structures, and canonical node name
321strings pointed to by the addrinfo structures.
322To return this information to the system the function
323.Fn freeaddrinfo
324is called.
325The
326.Fa addrinfo
327structure pointed to by the
328.Fa ai argument
329is freed, along with any dynamic storage pointed to by the structure.
330This operation is repeated until a
331.Dv NULL
332.Fa ai_next
333pointer is encountered.
334.Pp
335To aid applications in printing error messages based on the
336.Dv EAI_xxx
337codes returned by
338.Fn getaddrinfo ,
339.Fn gai_strerror
340is defined.
341The argument is one of the
342.Dv EAI_xxx
343values defined earlier and the return value points to a string describing
344the error.
345If the argument is not one of the
346.Dv EAI_xxx
347values, the function still returns a pointer to a string whose contents
348indicate an unknown error.
349.\"
350.Ss Extension for scoped IPv6 address
351The implementation allows experimental numeric IPv6 address notation with
352scope identifier.
353By appending the percent character and scope identifier to addresses,
354you can fill
355.Li sin6_scope_id
356field for addresses.
357This would make management of scoped address easier,
358and allows cut-and-paste input of scoped address.
359.Pp
360At this moment the code supports only link-local addresses with the format.
361Scope identifier is hardcoded to name of hardware interface associated
362with the link.
363.Po
364such as
365.Li ne0
366.Pc .
367Example would be like
368.Dq Li fe80::1%ne0 ,
369which means
370.Do
371.Li fe80::1
372on the link associated with
373.Li ne0
374interface
375.Dc .
376.Pp
377The implementation is still very experimental and non-standard.
378The current implementation assumes one-by-one relationship between
379interface and link, which is not necessarily true from the specification.
380.\"
381.Sh EXAMPLES
382The following code tries to connect to
383.Dq Li www.kame.net
384service
385.Dq Li http .
386via stream socket.
387It loops through all the addresses available, regardless from address family.
388If the destination resolves to IPv4 address, it will use
389.Dv AF_INET
390socket.
391Similarly, if it resolves to IPv6,
392.Dv AF_INET6
393socket is used.
394Observe that there is no hardcoded reference to particular address family.
395The code works even if
396.Nm getaddrinfo
397returns addresses that are not IPv4/v6.
398.Bd -literal -offset indent
399struct addrinfo hints, *res, *res0;
400int error;
401int s;
402const char *cause = NULL;
403
404memset(&hints, 0, sizeof(hints));
405hints.ai_family = PF_UNSPEC;
406hints.ai_socktype = SOCK_STREAM;
407error = getaddrinfo("www.kame.net", "http", &hints, &res0);
408if (error) {
409 errx(1, "%s", gai_strerror(error));
410 /*NOTREACHED*/
411}
412s = -1;
413for (res = res0; res; res = res->ai_next) {
414 s = socket(res->ai_family, res->ai_socktype,
415 res->ai_protocol);
416 if (s < 0) {
417 cause = "socket";
418 continue;
419 }
420
421 if (connect(s, res->ai_addr, res->ai_addrlen) < 0) {
422 cause = "connect";
423 close(s);
424 s = -1;
425 continue;
426 }
427
428 break; /* okay we got one */
429}
430if (s < 0) {
431 err(1, cause);
432 /*NOTREACHED*/
433}
434freeaddrinfo(res0);
435.Ed
436.Pp
437The following example tries to open a wildcard listening socket onto service
438.Dq Li http ,
439for all the address families available.
440.Bd -literal -offset indent
441struct addrinfo hints, *res, *res0;
442int error;
443int s[MAXSOCK];
444int nsock;
445const char *cause = NULL;
446
447memset(&hints, 0, sizeof(hints));
448hints.ai_family = PF_UNSPEC;
449hints.ai_socktype = SOCK_STREAM;
450hints.ai_flags = AI_PASSIVE;
451error = getaddrinfo(NULL, "http", &hints, &res0);
452if (error) {
453 errx(1, "%s", gai_strerror(error));
454 /*NOTREACHED*/
455}
456nsock = 0;
457for (res = res0; res && nsock < MAXSOCK; res = res->ai_next) {
458 s[nsock] = socket(res->ai_family, res->ai_socktype,
459 res->ai_protocol);
460 if (s[nsock] < 0) {
461 cause = "socket";
462 continue;
463 }
464
465 if (bind(s[nsock], res->ai_addr, res->ai_addrlen) < 0) {
466 cause = "bind";
467 close(s[nsock]);
468 continue;
469 }
470 (void) listen(s[nsock], 5);
471
472 nsock++;
473}
474if (nsock == 0) {
475 err(1, cause);
476 /*NOTREACHED*/
477}
478freeaddrinfo(res0);
479.Ed
480.\"
481.Sh DIAGNOSTICS
482Error return status from
483.Fn getaddrinfo
484is zero on success and non-zero on errors.
485Non-zero error codes are defined in
486.Aq Pa netdb.h ,
487and as follows:
488.Pp
489.Bl -tag -width EAI_ADDRFAMILY -compact
490.It Dv EAI_ADDRFAMILY
491Address family for
492.Fa nodename
493not supported.
494.It Dv EAI_AGAIN
495Temporary failure in name resolution.
496.It Dv EAI_BADFLAGS
497Invalid value for
498.Fa ai_flags .
499.It Dv EAI_FAIL
500Non-recoverable failure in name resolution.
501.It Dv EAI_FAMILY
502.Fa ai_family
503not supported.
504.It Dv EAI_MEMORY
505Memory allocation failure.
506.It Dv EAI_NODATA
507No address associated with
508.Fa nodename .
509.It Dv EAI_NONAME
510.Fa nodename
511nor
512.Fa servname
513provided, or not known.
514.It Dv EAI_SERVICE
515.Fa servname
516not supported for
517.Fa ai_socktype .
518.It Dv EAI_SOCKTYPE
519.Fa ai_socktype
520not supported.
521.It Dv EAI_SYSTEM
522System error returned in
523.Va errno .
524.El
525.Pp
526If called with proper argument,
527.Fn gai_strerror
528returns a pointer to a string describing the given error code.
529If the argument is not one of the
530.Dv EAI_xxx
531values, the function still returns a pointer to a string whose contents
532indicate an unknown error.
533.\"
534.Sh SEE ALSO
535.Xr getnameinfo 3 ,
536.Xr gethostbyname 3 ,
537.Xr getservbyname 3 ,
538.Xr hosts 5 ,
539.Xr resolv.conf 5 ,
540.Xr services 5 ,
541.Xr hostname 7 ,
542.Xr named 8
543.Rs
544.%A R. Gilligan
545.%A S. Thomson
546.%A J. Bound
547.%A W. Stevens
548.%T Basic Socket Interface Extensions for IPv6
549.%R RFC2553
550.%D March 1999
551.Re
552.Rs
553.%A Tatsuya Jinmei
554.%A Atsushi Onoe
555.%T "An Extension of Format for IPv6 Scoped Addresses"
556.%R internet draft
557.%N draft-ietf-ipngwg-scopedaddr-format-02.txt
558.%O work in progress material
559.Re
560.Rs
561.%A Craig Metz
562.%T Protocol Independence Using the Sockets API
563.%B "Proceedings of the freenix track: 2000 USENIX annual technical conference"
564.%D June 2000
565.Re
566.\"
567.Sh HISTORY
568The implementation first appeared in WIDE Hydrangea IPv6 protocol stack kit.
569.\"
570.Sh STANDARDS
571The
572.Fn getaddrinfo
573function is defined in IEEE POSIX 1003.1g draft specification,
574and documented in
575.Dq Basic Socket Interface Extensions for IPv6
576.Pq RFC2553 .
577.\"
578.Sh BUGS
579The current implementation is not thread-safe.
580.Pp
581The text was shamelessly copied from RFC2553.
diff --git a/src/lib/libc/net/getaddrinfo.c b/src/lib/libc/net/getaddrinfo.c
new file mode 100644
index 0000000000..915286a404
--- /dev/null
+++ b/src/lib/libc/net/getaddrinfo.c
@@ -0,0 +1,1848 @@
1/* $OpenBSD: getaddrinfo.c,v 1.43 2002/08/27 08:53:13 itojun Exp $ */
2/* $KAME: getaddrinfo.c,v 1.31 2000/08/31 17:36:43 itojun Exp $ */
3
4/*
5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the project nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33/*
34 * Issues to be discussed:
35 * - Thread safe-ness must be checked.
36 * - Return values. There are nonstandard return values defined and used
37 * in the source code. This is because RFC2553 is silent about which error
38 * code must be returned for which situation.
39 * - IPv4 classful (shortened) form. RFC2553 is silent about it. XNET 5.2
40 * says to use inet_aton() to convert IPv4 numeric to binary (alows
41 * classful form as a result).
42 * current code - disallow classful form for IPv4 (due to use of inet_pton).
43 * - freeaddrinfo(NULL). RFC2553 is silent about it. XNET 5.2 says it is
44 * invalid.
45 * current code - SEGV on freeaddrinfo(NULL)
46 * Note:
47 * - We use getipnodebyname() just for thread-safeness. There's no intent
48 * to let it do PF_UNSPEC (actually we never pass PF_UNSPEC to
49 * getipnodebyname().
50 * - The code filters out AFs that are not supported by the kernel,
51 * when globbing NULL hostname (to loopback, or wildcard). Is it the right
52 * thing to do? What is the relationship with post-RFC2553 AI_ADDRCONFIG
53 * in ai_flags?
54 * - (post-2553) semantics of AI_ADDRCONFIG itself is too vague.
55 * (1) what should we do against numeric hostname (2) what should we do
56 * against NULL hostname (3) what is AI_ADDRCONFIG itself. AF not ready?
57 * non-loopback address configured? global address configured?
58 * - To avoid search order issue, we have a big amount of code duplicate
59 * from gethnamaddr.c and some other places. The issues that there's no
60 * lower layer function to lookup "IPv4 or IPv6" record. Calling
61 * gethostbyname2 from getaddrinfo will end up in wrong search order, as
62 * follows:
63 * - The code makes use of following calls when asked to resolver with
64 * ai_family = PF_UNSPEC:
65 * getipnodebyname(host, AF_INET6);
66 * getipnodebyname(host, AF_INET);
67 * This will result in the following queries if the node is configure to
68 * prefer /etc/hosts than DNS:
69 * lookup /etc/hosts for IPv6 address
70 * lookup DNS for IPv6 address
71 * lookup /etc/hosts for IPv4 address
72 * lookup DNS for IPv4 address
73 * which may not meet people's requirement.
74 * The right thing to happen is to have underlying layer which does
75 * PF_UNSPEC lookup (lookup both) and return chain of addrinfos.
76 * This would result in a bit of code duplicate with _dns_ghbyname() and
77 * friends.
78 */
79
80#ifndef INET6
81#define INET6
82#endif
83
84#include <sys/types.h>
85#include <sys/param.h>
86#include <sys/socket.h>
87#include <net/if.h>
88#include <netinet/in.h>
89#include <arpa/inet.h>
90#include <arpa/nameser.h>
91#include <netdb.h>
92#include <resolv.h>
93#include <string.h>
94#include <stdlib.h>
95#include <stddef.h>
96#include <ctype.h>
97#include <unistd.h>
98#include <stdio.h>
99#include <errno.h>
100
101#include <syslog.h>
102#include <stdarg.h>
103
104#ifdef YP
105#include <rpc/rpc.h>
106#include <rpcsvc/yp.h>
107#include <rpcsvc/ypclnt.h>
108#include "ypinternal.h"
109#endif
110
111#include "thread_private.h"
112
113#define SUCCESS 0
114#define ANY 0
115#define YES 1
116#define NO 0
117
118static const char in_addrany[] = { 0, 0, 0, 0 };
119static const char in6_addrany[] = {
120 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
121};
122static const char in_loopback[] = { 127, 0, 0, 1 };
123static const char in6_loopback[] = {
124 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
125};
126
127static const struct afd {
128 int a_af;
129 int a_addrlen;
130 int a_socklen;
131 int a_off;
132 const char *a_addrany;
133 const char *a_loopback;
134 int a_scoped;
135} afdl [] = {
136#ifdef INET6
137 {PF_INET6, sizeof(struct in6_addr),
138 sizeof(struct sockaddr_in6),
139 offsetof(struct sockaddr_in6, sin6_addr),
140 in6_addrany, in6_loopback, 1},
141#endif
142 {PF_INET, sizeof(struct in_addr),
143 sizeof(struct sockaddr_in),
144 offsetof(struct sockaddr_in, sin_addr),
145 in_addrany, in_loopback, 0},
146 {0, 0, 0, 0, NULL, NULL, 0},
147};
148
149struct explore {
150 int e_af;
151 int e_socktype;
152 int e_protocol;
153 const char *e_protostr;
154 int e_wild;
155#define WILD_AF(ex) ((ex)->e_wild & 0x01)
156#define WILD_SOCKTYPE(ex) ((ex)->e_wild & 0x02)
157#define WILD_PROTOCOL(ex) ((ex)->e_wild & 0x04)
158};
159
160static const struct explore explore[] = {
161#if 0
162 { PF_LOCAL, 0, ANY, ANY, NULL, 0x01 },
163#endif
164#ifdef INET6
165 { PF_INET6, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
166 { PF_INET6, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
167 { PF_INET6, SOCK_RAW, ANY, NULL, 0x05 },
168#endif
169 { PF_INET, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
170 { PF_INET, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
171 { PF_INET, SOCK_RAW, ANY, NULL, 0x05 },
172 { PF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
173 { PF_UNSPEC, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
174 { PF_UNSPEC, SOCK_RAW, ANY, NULL, 0x05 },
175 { -1, 0, 0, NULL, 0 },
176};
177
178#ifdef INET6
179#define PTON_MAX 16
180#else
181#define PTON_MAX 4
182#endif
183
184#define MAXPACKET (64*1024)
185
186typedef union {
187 HEADER hdr;
188 u_char buf[MAXPACKET];
189} querybuf;
190
191struct res_target {
192 struct res_target *next;
193 const char *name; /* domain name */
194 int qclass, qtype; /* class and type of query */
195 u_char *answer; /* buffer to put answer */
196 int anslen; /* size of answer buffer */
197 int n; /* result length */
198};
199
200static int str_isnumber(const char *);
201static int explore_fqdn(const struct addrinfo *, const char *,
202 const char *, struct addrinfo **);
203static int explore_null(const struct addrinfo *,
204 const char *, struct addrinfo **);
205static int explore_numeric(const struct addrinfo *, const char *,
206 const char *, struct addrinfo **);
207static int explore_numeric_scope(const struct addrinfo *, const char *,
208 const char *, struct addrinfo **);
209static int get_canonname(const struct addrinfo *,
210 struct addrinfo *, const char *);
211static struct addrinfo *get_ai(const struct addrinfo *,
212 const struct afd *, const char *);
213static int get_portmatch(const struct addrinfo *, const char *);
214static int get_port(struct addrinfo *, const char *, int);
215static const struct afd *find_afd(int);
216#if 0
217static int addrconfig(const struct addrinfo *);
218#endif
219#ifdef INET6
220static int ip6_str2scopeid(char *, struct sockaddr_in6 *, u_int32_t *);
221#endif
222
223static void _sethtent(void);
224static void _endhtent(void);
225static struct addrinfo * _gethtent(const char *, const struct addrinfo *);
226static struct addrinfo *_files_getaddrinfo(const char *,
227 const struct addrinfo *);
228
229#ifdef YP
230static struct addrinfo *_yphostent(char *, const struct addrinfo *);
231static struct addrinfo *_yp_getaddrinfo(const char *,
232 const struct addrinfo *);
233#endif
234
235static struct addrinfo *getanswer(const querybuf *, int, const char *, int,
236 const struct addrinfo *);
237static int res_queryN(const char *, struct res_target *);
238static int res_searchN(const char *, struct res_target *);
239static int res_querydomainN(const char *, const char *, struct res_target *);
240static struct addrinfo *_dns_getaddrinfo(const char *, const struct addrinfo *);
241
242
243/* XXX macros that make external reference is BAD. */
244
245#define GET_AI(ai, afd, addr) \
246do { \
247 /* external reference: pai, error, and label free */ \
248 (ai) = get_ai(pai, (afd), (addr)); \
249 if ((ai) == NULL) { \
250 error = EAI_MEMORY; \
251 goto free; \
252 } \
253} while (/*CONSTCOND*/0)
254
255#define GET_PORT(ai, serv) \
256do { \
257 /* external reference: error and label free */ \
258 error = get_port((ai), (serv), 0); \
259 if (error != 0) \
260 goto free; \
261} while (/*CONSTCOND*/0)
262
263#define GET_CANONNAME(ai, str) \
264do { \
265 /* external reference: pai, error and label free */ \
266 error = get_canonname(pai, (ai), (str)); \
267 if (error != 0) \
268 goto free; \
269} while (/*CONSTCOND*/0)
270
271#define ERR(err) \
272do { \
273 /* external reference: error, and label bad */ \
274 error = (err); \
275 goto bad; \
276 /*NOTREACHED*/ \
277} while (/*CONSTCOND*/0)
278
279#define MATCH_FAMILY(x, y, w) \
280 ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == PF_UNSPEC || (y) == PF_UNSPEC)))
281#define MATCH(x, y, w) \
282 ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == ANY || (y) == ANY)))
283
284static int
285str_isnumber(p)
286 const char *p;
287{
288 char *ep;
289
290 if (*p == '\0')
291 return NO;
292 ep = NULL;
293 errno = 0;
294 (void)strtoul(p, &ep, 10);
295 if (errno == 0 && ep && *ep == '\0')
296 return YES;
297 else
298 return NO;
299}
300
301int
302getaddrinfo(hostname, servname, hints, res)
303 const char *hostname, *servname;
304 const struct addrinfo *hints;
305 struct addrinfo **res;
306{
307 struct addrinfo sentinel;
308 struct addrinfo *cur;
309 int error = 0;
310 struct addrinfo ai;
311 struct addrinfo ai0;
312 struct addrinfo *pai;
313 const struct explore *ex;
314
315 memset(&sentinel, 0, sizeof(sentinel));
316 cur = &sentinel;
317 pai = &ai;
318 pai->ai_flags = 0;
319 pai->ai_family = PF_UNSPEC;
320 pai->ai_socktype = ANY;
321 pai->ai_protocol = ANY;
322 pai->ai_addrlen = 0;
323 pai->ai_canonname = NULL;
324 pai->ai_addr = NULL;
325 pai->ai_next = NULL;
326
327 if (hostname == NULL && servname == NULL)
328 return EAI_NONAME;
329 if (hints) {
330 /* error check for hints */
331 if (hints->ai_addrlen || hints->ai_canonname ||
332 hints->ai_addr || hints->ai_next)
333 ERR(EAI_BADHINTS); /* xxx */
334 if (hints->ai_flags & ~AI_MASK)
335 ERR(EAI_BADFLAGS);
336 switch (hints->ai_family) {
337 case PF_UNSPEC:
338 case PF_INET:
339#ifdef INET6
340 case PF_INET6:
341#endif
342 break;
343 default:
344 ERR(EAI_FAMILY);
345 }
346 memcpy(pai, hints, sizeof(*pai));
347
348 /*
349 * if both socktype/protocol are specified, check if they
350 * are meaningful combination.
351 */
352 if (pai->ai_socktype != ANY && pai->ai_protocol != ANY) {
353 for (ex = explore; ex->e_af >= 0; ex++) {
354 if (pai->ai_family != ex->e_af)
355 continue;
356 if (ex->e_socktype == ANY)
357 continue;
358 if (ex->e_protocol == ANY)
359 continue;
360 if (pai->ai_socktype == ex->e_socktype
361 && pai->ai_protocol != ex->e_protocol) {
362 ERR(EAI_BADHINTS);
363 }
364 }
365 }
366 }
367
368 /*
369 * check for special cases. (1) numeric servname is disallowed if
370 * socktype/protocol are left unspecified. (2) servname is disallowed
371 * for raw and other inet{,6} sockets.
372 */
373 if (MATCH_FAMILY(pai->ai_family, PF_INET, 1)
374#ifdef PF_INET6
375 || MATCH_FAMILY(pai->ai_family, PF_INET6, 1)
376#endif
377 ) {
378 ai0 = *pai; /* backup *pai */
379
380 if (pai->ai_family == PF_UNSPEC) {
381#ifdef PF_INET6
382 pai->ai_family = PF_INET6;
383#else
384 pai->ai_family = PF_INET;
385#endif
386 }
387 error = get_portmatch(pai, servname);
388 if (error)
389 ERR(error);
390
391 *pai = ai0;
392 }
393
394 ai0 = *pai;
395
396 /* NULL hostname, or numeric hostname */
397 for (ex = explore; ex->e_af >= 0; ex++) {
398 *pai = ai0;
399
400 /* PF_UNSPEC entries are prepared for DNS queries only */
401 if (ex->e_af == PF_UNSPEC)
402 continue;
403
404 if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex)))
405 continue;
406 if (!MATCH(pai->ai_socktype, ex->e_socktype, WILD_SOCKTYPE(ex)))
407 continue;
408 if (!MATCH(pai->ai_protocol, ex->e_protocol, WILD_PROTOCOL(ex)))
409 continue;
410
411 if (pai->ai_family == PF_UNSPEC)
412 pai->ai_family = ex->e_af;
413 if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
414 pai->ai_socktype = ex->e_socktype;
415 if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
416 pai->ai_protocol = ex->e_protocol;
417
418 if (hostname == NULL)
419 error = explore_null(pai, servname, &cur->ai_next);
420 else
421 error = explore_numeric_scope(pai, hostname, servname, &cur->ai_next);
422
423 if (error)
424 goto free;
425
426 while (cur && cur->ai_next)
427 cur = cur->ai_next;
428 }
429
430 /*
431 * XXX
432 * If numreic representation of AF1 can be interpreted as FQDN
433 * representation of AF2, we need to think again about the code below.
434 */
435 if (sentinel.ai_next)
436 goto good;
437
438 if (pai->ai_flags & AI_NUMERICHOST)
439 ERR(EAI_NODATA);
440 if (hostname == NULL)
441 ERR(EAI_NODATA);
442
443 /*
444 * hostname as alphabetical name.
445 * we would like to prefer AF_INET6 than AF_INET, so we'll make a
446 * outer loop by AFs.
447 */
448 for (ex = explore; ex->e_af >= 0; ex++) {
449 *pai = ai0;
450
451 /* require exact match for family field */
452 if (pai->ai_family != ex->e_af)
453 continue;
454
455 if (!MATCH(pai->ai_socktype, ex->e_socktype,
456 WILD_SOCKTYPE(ex))) {
457 continue;
458 }
459 if (!MATCH(pai->ai_protocol, ex->e_protocol,
460 WILD_PROTOCOL(ex))) {
461 continue;
462 }
463
464 if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
465 pai->ai_socktype = ex->e_socktype;
466 if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
467 pai->ai_protocol = ex->e_protocol;
468
469 error = explore_fqdn(pai, hostname, servname,
470 &cur->ai_next);
471
472 while (cur && cur->ai_next)
473 cur = cur->ai_next;
474 }
475
476 /* XXX */
477 if (sentinel.ai_next)
478 error = 0;
479
480 if (error)
481 goto free;
482 if (error == 0) {
483 if (sentinel.ai_next) {
484 good:
485 *res = sentinel.ai_next;
486 return SUCCESS;
487 } else
488 error = EAI_FAIL;
489 }
490 free:
491 bad:
492 if (sentinel.ai_next)
493 freeaddrinfo(sentinel.ai_next);
494 *res = NULL;
495 return error;
496}
497
498/*
499 * FQDN hostname, DNS lookup
500 */
501
502_THREAD_PRIVATE_MUTEX(getaddrinfo_explore_fqdn);
503
504static int
505explore_fqdn(pai, hostname, servname, res)
506 const struct addrinfo *pai;
507 const char *hostname;
508 const char *servname;
509 struct addrinfo **res;
510{
511 struct addrinfo *result;
512 struct addrinfo *cur;
513 int error = 0;
514 char lookups[MAXDNSLUS];
515 int i;
516
517 _THREAD_PRIVATE_MUTEX_LOCK(getaddrinfo_explore_fqdn);
518
519 result = NULL;
520
521#if 0
522 /*
523 * If AI_ADDRCONFIG is specified, check if we are expected to
524 * return the address family or not.
525 * XXX does not handle PF_UNSPEC case, should filter final result
526 */
527 if ((pai->ai_flags & AI_ADDRCONFIG) != 0 && !addrconfig(pai)) {
528 _THREAD_PRIVATE_MUTEX_UNLOCK(getaddrinfo_explore_fqdn);
529 return 0;
530 }
531#endif
532
533 /*
534 * if the servname does not match socktype/protocol, ignore it.
535 */
536 if (get_portmatch(pai, servname) != 0) {
537 _THREAD_PRIVATE_MUTEX_UNLOCK(getaddrinfo_explore_fqdn);
538 return 0;
539 }
540
541 if ((_res.options & RES_INIT) == 0 && res_init() == -1)
542 strlcpy(lookups, "f", sizeof lookups);
543 else {
544 bcopy(_res.lookups, lookups, sizeof lookups);
545 if (lookups[0] == '\0')
546 strlcpy(lookups, "bf", sizeof lookups);
547 }
548
549 for (i = 0; i < MAXDNSLUS && result == NULL && lookups[i]; i++) {
550 switch (lookups[i]) {
551#ifdef YP
552 case 'y':
553 result = _yp_getaddrinfo(hostname, pai);
554 break;
555#endif
556 case 'b':
557 result = _dns_getaddrinfo(hostname, pai);
558 break;
559 case 'f':
560 result = _files_getaddrinfo(hostname, pai);
561 break;
562 }
563 }
564 if (result) {
565 for (cur = result; cur; cur = cur->ai_next) {
566 GET_PORT(cur, servname);
567 /* canonname should be filled already */
568 }
569 *res = result;
570 _THREAD_PRIVATE_MUTEX_UNLOCK(getaddrinfo_explore_fqdn);
571 return 0;
572 } else {
573 /* translate error code */
574 switch (h_errno) {
575 case NETDB_SUCCESS:
576 error = EAI_FAIL; /*XXX strange */
577 break;
578 case HOST_NOT_FOUND:
579 error = EAI_NODATA;
580 break;
581 case TRY_AGAIN:
582 error = EAI_AGAIN;
583 break;
584 case NO_RECOVERY:
585 error = EAI_FAIL;
586 break;
587 case NO_DATA:
588#if NO_ADDRESS != NO_DATA
589 case NO_ADDRESS:
590#endif
591 error = EAI_NODATA;
592 break;
593 default: /* unknown ones */
594 error = EAI_FAIL;
595 break;
596 }
597 }
598
599free:
600 if (result)
601 freeaddrinfo(result);
602 _THREAD_PRIVATE_MUTEX_UNLOCK(getaddrinfo_explore_fqdn);
603 return error;
604}
605
606/*
607 * hostname == NULL.
608 * passive socket -> anyaddr (0.0.0.0 or ::)
609 * non-passive socket -> localhost (127.0.0.1 or ::1)
610 */
611static int
612explore_null(pai, servname, res)
613 const struct addrinfo *pai;
614 const char *servname;
615 struct addrinfo **res;
616{
617 int s;
618 const struct afd *afd;
619 struct addrinfo *cur;
620 struct addrinfo sentinel;
621 int error;
622
623 *res = NULL;
624 sentinel.ai_next = NULL;
625 cur = &sentinel;
626
627 /*
628 * filter out AFs that are not supported by the kernel
629 * XXX errno?
630 */
631 s = socket(pai->ai_family, SOCK_DGRAM, 0);
632 if (s < 0) {
633 if (errno != EMFILE)
634 return 0;
635 } else
636 close(s);
637
638 /*
639 * if the servname does not match socktype/protocol, ignore it.
640 */
641 if (get_portmatch(pai, servname) != 0)
642 return 0;
643
644 afd = find_afd(pai->ai_family);
645 if (afd == NULL)
646 return 0;
647
648 if (pai->ai_flags & AI_PASSIVE) {
649 GET_AI(cur->ai_next, afd, afd->a_addrany);
650 /* xxx meaningless?
651 * GET_CANONNAME(cur->ai_next, "anyaddr");
652 */
653 GET_PORT(cur->ai_next, servname);
654 } else {
655 GET_AI(cur->ai_next, afd, afd->a_loopback);
656 /* xxx meaningless?
657 * GET_CANONNAME(cur->ai_next, "localhost");
658 */
659 GET_PORT(cur->ai_next, servname);
660 }
661 cur = cur->ai_next;
662
663 *res = sentinel.ai_next;
664 return 0;
665
666free:
667 if (sentinel.ai_next)
668 freeaddrinfo(sentinel.ai_next);
669 return error;
670}
671
672/*
673 * numeric hostname
674 */
675static int
676explore_numeric(pai, hostname, servname, res)
677 const struct addrinfo *pai;
678 const char *hostname;
679 const char *servname;
680 struct addrinfo **res;
681{
682 const struct afd *afd;
683 struct addrinfo *cur;
684 struct addrinfo sentinel;
685 int error;
686 char pton[PTON_MAX];
687
688 *res = NULL;
689 sentinel.ai_next = NULL;
690 cur = &sentinel;
691
692 /*
693 * if the servname does not match socktype/protocol, ignore it.
694 */
695 if (get_portmatch(pai, servname) != 0)
696 return 0;
697
698 afd = find_afd(pai->ai_family);
699 if (afd == NULL)
700 return 0;
701
702 switch (afd->a_af) {
703#if 0 /*X/Open spec*/
704 case AF_INET:
705 if (inet_aton(hostname, (struct in_addr *)pton) == 1) {
706 if (pai->ai_family == afd->a_af ||
707 pai->ai_family == PF_UNSPEC /*?*/) {
708 GET_AI(cur->ai_next, afd, pton);
709 GET_PORT(cur->ai_next, servname);
710 while (cur && cur->ai_next)
711 cur = cur->ai_next;
712 } else
713 ERR(EAI_FAMILY); /*xxx*/
714 }
715 break;
716#endif
717 default:
718 if (inet_pton(afd->a_af, hostname, pton) == 1) {
719 if (pai->ai_family == afd->a_af ||
720 pai->ai_family == PF_UNSPEC /*?*/) {
721 GET_AI(cur->ai_next, afd, pton);
722 GET_PORT(cur->ai_next, servname);
723 while (cur && cur->ai_next)
724 cur = cur->ai_next;
725 } else
726 ERR(EAI_FAMILY); /*xxx*/
727 }
728 break;
729 }
730
731 *res = sentinel.ai_next;
732 return 0;
733
734free:
735bad:
736 if (sentinel.ai_next)
737 freeaddrinfo(sentinel.ai_next);
738 return error;
739}
740
741/*
742 * numeric hostname with scope
743 */
744static int
745explore_numeric_scope(pai, hostname, servname, res)
746 const struct addrinfo *pai;
747 const char *hostname;
748 const char *servname;
749 struct addrinfo **res;
750{
751#if !defined(SCOPE_DELIMITER) || !defined(INET6)
752 return explore_numeric(pai, hostname, servname, res);
753#else
754 const struct afd *afd;
755 struct addrinfo *cur;
756 int error;
757 char *cp, *hostname2 = NULL, *scope, *addr;
758 struct sockaddr_in6 *sin6;
759
760 /*
761 * if the servname does not match socktype/protocol, ignore it.
762 */
763 if (get_portmatch(pai, servname) != 0)
764 return 0;
765
766 afd = find_afd(pai->ai_family);
767 if (afd == NULL)
768 return 0;
769
770 if (!afd->a_scoped)
771 return explore_numeric(pai, hostname, servname, res);
772
773 cp = strchr(hostname, SCOPE_DELIMITER);
774 if (cp == NULL)
775 return explore_numeric(pai, hostname, servname, res);
776
777 /*
778 * Handle special case of <scoped_address><delimiter><scope id>
779 */
780 hostname2 = strdup(hostname);
781 if (hostname2 == NULL)
782 return EAI_MEMORY;
783 /* terminate at the delimiter */
784 hostname2[cp - hostname] = '\0';
785 addr = hostname2;
786 scope = cp + 1;
787
788 error = explore_numeric(pai, addr, servname, res);
789 if (error == 0) {
790 u_int32_t scopeid;
791
792 for (cur = *res; cur; cur = cur->ai_next) {
793 if (cur->ai_family != AF_INET6)
794 continue;
795 sin6 = (struct sockaddr_in6 *)(void *)cur->ai_addr;
796 if (ip6_str2scopeid(scope, sin6, &scopeid) == -1) {
797 free(hostname2);
798 return(EAI_NODATA); /* XXX: is return OK? */
799 }
800 sin6->sin6_scope_id = scopeid;
801 }
802 }
803
804 free(hostname2);
805
806 return error;
807#endif
808}
809
810static int
811get_canonname(pai, ai, str)
812 const struct addrinfo *pai;
813 struct addrinfo *ai;
814 const char *str;
815{
816 if ((pai->ai_flags & AI_CANONNAME) != 0) {
817 ai->ai_canonname = strdup(str);
818 if (ai->ai_canonname == NULL)
819 return EAI_MEMORY;
820 }
821 return 0;
822}
823
824static struct addrinfo *
825get_ai(pai, afd, addr)
826 const struct addrinfo *pai;
827 const struct afd *afd;
828 const char *addr;
829{
830 char *p;
831 struct addrinfo *ai;
832
833 ai = (struct addrinfo *)malloc(sizeof(struct addrinfo)
834 + (afd->a_socklen));
835 if (ai == NULL)
836 return NULL;
837
838 memcpy(ai, pai, sizeof(struct addrinfo));
839 ai->ai_addr = (struct sockaddr *)(void *)(ai + 1);
840 memset(ai->ai_addr, 0, (size_t)afd->a_socklen);
841 ai->ai_addr->sa_len = afd->a_socklen;
842 ai->ai_addrlen = afd->a_socklen;
843 ai->ai_addr->sa_family = ai->ai_family = afd->a_af;
844 p = (char *)(void *)(ai->ai_addr);
845 memcpy(p + afd->a_off, addr, (size_t)afd->a_addrlen);
846 return ai;
847}
848
849static int
850get_portmatch(ai, servname)
851 const struct addrinfo *ai;
852 const char *servname;
853{
854
855 /* get_port does not touch first argument. when matchonly == 1. */
856 /* LINTED const cast */
857 return get_port((struct addrinfo *)ai, servname, 1);
858}
859
860static int
861get_port(ai, servname, matchonly)
862 struct addrinfo *ai;
863 const char *servname;
864 int matchonly;
865{
866 const char *proto;
867 struct servent *sp;
868 int port;
869 int allownumeric;
870
871 if (servname == NULL)
872 return 0;
873 switch (ai->ai_family) {
874 case AF_INET:
875#ifdef AF_INET6
876 case AF_INET6:
877#endif
878 break;
879 default:
880 return 0;
881 }
882
883 switch (ai->ai_socktype) {
884 case SOCK_RAW:
885 return EAI_SERVICE;
886 case SOCK_DGRAM:
887 case SOCK_STREAM:
888 allownumeric = 1;
889 break;
890 case ANY:
891 allownumeric = 0;
892 break;
893 default:
894 return EAI_SOCKTYPE;
895 }
896
897 if (str_isnumber(servname)) {
898 if (!allownumeric)
899 return EAI_SERVICE;
900 port = atoi(servname);
901 if (port < 0 || port > 65535)
902 return EAI_SERVICE;
903 port = htons(port);
904 } else {
905 switch (ai->ai_socktype) {
906 case SOCK_DGRAM:
907 proto = "udp";
908 break;
909 case SOCK_STREAM:
910 proto = "tcp";
911 break;
912 default:
913 proto = NULL;
914 break;
915 }
916
917 if ((sp = getservbyname(servname, proto)) == NULL)
918 return EAI_SERVICE;
919 port = sp->s_port;
920 }
921
922 if (!matchonly) {
923 switch (ai->ai_family) {
924 case AF_INET:
925 ((struct sockaddr_in *)(void *)
926 ai->ai_addr)->sin_port = port;
927 break;
928#ifdef INET6
929 case AF_INET6:
930 ((struct sockaddr_in6 *)(void *)
931 ai->ai_addr)->sin6_port = port;
932 break;
933#endif
934 }
935 }
936
937 return 0;
938}
939
940static const struct afd *
941find_afd(af)
942 int af;
943{
944 const struct afd *afd;
945
946 if (af == PF_UNSPEC)
947 return NULL;
948 for (afd = afdl; afd->a_af; afd++) {
949 if (afd->a_af == af)
950 return afd;
951 }
952 return NULL;
953}
954
955#if 0
956/*
957 * post-2553: AI_ADDRCONFIG check. if we use getipnodeby* as backend, backend
958 * will take care of it.
959 * the semantics of AI_ADDRCONFIG is not defined well. we are not sure
960 * if the code is right or not.
961 */
962static int
963addrconfig(pai)
964 const struct addrinfo *pai;
965{
966 int s;
967
968 /* XXX errno */
969 s = socket(pai->ai_family, SOCK_DGRAM, 0);
970 if (s < 0)
971 return 0;
972 close(s);
973 return 1;
974}
975#endif
976
977#ifdef INET6
978/* convert a string to a scope identifier. XXX: IPv6 specific */
979static int
980ip6_str2scopeid(scope, sin6, scopeid)
981 char *scope;
982 struct sockaddr_in6 *sin6;
983 u_int32_t *scopeid;
984{
985 u_long lscopeid;
986 struct in6_addr *a6 = &sin6->sin6_addr;
987 char *ep;
988
989 /* empty scopeid portion is invalid */
990 if (*scope == '\0')
991 return -1;
992
993 if (IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6)) {
994 /*
995 * We currently assume a one-to-one mapping between links
996 * and interfaces, so we simply use interface indices for
997 * like-local scopes.
998 */
999 *scopeid = if_nametoindex(scope);
1000 if (*scopeid == 0)
1001 goto trynumeric;
1002 return 0;
1003 }
1004
1005 /* still unclear about literal, allow numeric only - placeholder */
1006 if (IN6_IS_ADDR_SITELOCAL(a6) || IN6_IS_ADDR_MC_SITELOCAL(a6))
1007 goto trynumeric;
1008 if (IN6_IS_ADDR_MC_ORGLOCAL(a6))
1009 goto trynumeric;
1010 else
1011 goto trynumeric; /* global */
1012
1013 /* try to convert to a numeric id as a last resort */
1014 trynumeric:
1015 errno = 0;
1016 lscopeid = strtoul(scope, &ep, 10);
1017 *scopeid = (u_int32_t)(lscopeid & 0xffffffffUL);
1018 if (errno == 0 && ep && *ep == '\0' && *scopeid == lscopeid)
1019 return 0;
1020 else
1021 return -1;
1022}
1023#endif
1024
1025/* code duplicate with gethnamaddr.c */
1026
1027static const char AskedForGot[] =
1028 "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
1029static FILE *hostf = NULL;
1030
1031static struct addrinfo *
1032getanswer(answer, anslen, qname, qtype, pai)
1033 const querybuf *answer;
1034 int anslen;
1035 const char *qname;
1036 int qtype;
1037 const struct addrinfo *pai;
1038{
1039 struct addrinfo sentinel, *cur;
1040 struct addrinfo ai;
1041 const struct afd *afd;
1042 char *canonname;
1043 const HEADER *hp;
1044 const u_char *cp;
1045 int n;
1046 const u_char *eom;
1047 char *bp, *ep;
1048 int type, class, ancount, qdcount;
1049 int haveanswer, had_error;
1050 char tbuf[MAXDNAME];
1051 int (*name_ok)(const char *);
1052 char hostbuf[8*1024];
1053
1054 memset(&sentinel, 0, sizeof(sentinel));
1055 cur = &sentinel;
1056
1057 canonname = NULL;
1058 eom = answer->buf + anslen;
1059 switch (qtype) {
1060 case T_A:
1061 case T_AAAA:
1062 case T_ANY: /*use T_ANY only for T_A/T_AAAA lookup*/
1063 name_ok = res_hnok;
1064 break;
1065 default:
1066 return (NULL); /* XXX should be abort() -- but that is illegal */
1067 }
1068 /*
1069 * find first satisfactory answer
1070 */
1071 hp = &answer->hdr;
1072 ancount = ntohs(hp->ancount);
1073 qdcount = ntohs(hp->qdcount);
1074 bp = hostbuf;
1075 ep = hostbuf + sizeof hostbuf;
1076 cp = answer->buf + HFIXEDSZ;
1077 if (qdcount != 1) {
1078 h_errno = NO_RECOVERY;
1079 return (NULL);
1080 }
1081 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
1082 if ((n < 0) || !(*name_ok)(bp)) {
1083 h_errno = NO_RECOVERY;
1084 return (NULL);
1085 }
1086 cp += n + QFIXEDSZ;
1087 if (qtype == T_A || qtype == T_AAAA || qtype == T_ANY) {
1088 /* res_send() has already verified that the query name is the
1089 * same as the one we sent; this just gets the expanded name
1090 * (i.e., with the succeeding search-domain tacked on).
1091 */
1092 n = strlen(bp) + 1; /* for the \0 */
1093 if (n >= MAXHOSTNAMELEN) {
1094 h_errno = NO_RECOVERY;
1095 return (NULL);
1096 }
1097 canonname = bp;
1098 bp += n;
1099 /* The qname can be abbreviated, but h_name is now absolute. */
1100 qname = canonname;
1101 }
1102 haveanswer = 0;
1103 had_error = 0;
1104 while (ancount-- > 0 && cp < eom && !had_error) {
1105 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
1106 if ((n < 0) || !(*name_ok)(bp)) {
1107 had_error++;
1108 continue;
1109 }
1110 cp += n; /* name */
1111 type = _getshort(cp);
1112 cp += INT16SZ; /* type */
1113 class = _getshort(cp);
1114 cp += INT16SZ + INT32SZ; /* class, TTL */
1115 n = _getshort(cp);
1116 cp += INT16SZ; /* len */
1117 if (class != C_IN) {
1118 /* XXX - debug? syslog? */
1119 cp += n;
1120 continue; /* XXX - had_error++ ? */
1121 }
1122 if ((qtype == T_A || qtype == T_AAAA || qtype == T_ANY) &&
1123 type == T_CNAME) {
1124 n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
1125 if ((n < 0) || !(*name_ok)(tbuf)) {
1126 had_error++;
1127 continue;
1128 }
1129 cp += n;
1130 /* Get canonical name. */
1131 n = strlen(tbuf) + 1; /* for the \0 */
1132 if (n > ep - bp || n >= MAXHOSTNAMELEN) {
1133 had_error++;
1134 continue;
1135 }
1136 strcpy(bp, tbuf);
1137 canonname = bp;
1138 bp += n;
1139 continue;
1140 }
1141 if (qtype == T_ANY) {
1142 if (!(type == T_A || type == T_AAAA)) {
1143 cp += n;
1144 continue;
1145 }
1146 } else if (type != qtype) {
1147 if (type != T_KEY && type != T_SIG)
1148 syslog(LOG_NOTICE|LOG_AUTH,
1149 "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
1150 qname, p_class(C_IN), p_type(qtype),
1151 p_type(type));
1152 cp += n;
1153 continue; /* XXX - had_error++ ? */
1154 }
1155 switch (type) {
1156 case T_A:
1157 case T_AAAA:
1158 if (strcasecmp(canonname, bp) != 0) {
1159 syslog(LOG_NOTICE|LOG_AUTH,
1160 AskedForGot, canonname, bp);
1161 cp += n;
1162 continue; /* XXX - had_error++ ? */
1163 }
1164 if (type == T_A && n != INADDRSZ) {
1165 cp += n;
1166 continue;
1167 }
1168 if (type == T_AAAA && n != IN6ADDRSZ) {
1169 cp += n;
1170 continue;
1171 }
1172 if (type == T_AAAA) {
1173 struct in6_addr in6;
1174 memcpy(&in6, cp, IN6ADDRSZ);
1175 if (IN6_IS_ADDR_V4MAPPED(&in6)) {
1176 cp += n;
1177 continue;
1178 }
1179 }
1180 if (!haveanswer) {
1181 int nn;
1182
1183 canonname = bp;
1184 nn = strlen(bp) + 1; /* for the \0 */
1185 bp += nn;
1186 }
1187
1188 /* don't overwrite pai */
1189 ai = *pai;
1190 ai.ai_family = (type == T_A) ? AF_INET : AF_INET6;
1191 afd = find_afd(ai.ai_family);
1192 if (afd == NULL) {
1193 cp += n;
1194 continue;
1195 }
1196 cur->ai_next = get_ai(&ai, afd, (const char *)cp);
1197 if (cur->ai_next == NULL)
1198 had_error++;
1199 while (cur && cur->ai_next)
1200 cur = cur->ai_next;
1201 cp += n;
1202 break;
1203 default:
1204 abort(); /* XXX abort illegal in library */
1205 }
1206 if (!had_error)
1207 haveanswer++;
1208 }
1209 if (haveanswer) {
1210 if (!canonname)
1211 (void)get_canonname(pai, sentinel.ai_next, qname);
1212 else
1213 (void)get_canonname(pai, sentinel.ai_next, canonname);
1214 h_errno = NETDB_SUCCESS;
1215 return sentinel.ai_next;
1216 }
1217
1218 h_errno = NO_RECOVERY;
1219 return NULL;
1220}
1221
1222/*ARGSUSED*/
1223static struct addrinfo *
1224_dns_getaddrinfo(name, pai)
1225 const char *name;
1226 const struct addrinfo *pai;
1227{
1228 struct addrinfo *ai;
1229 querybuf *buf, *buf2;
1230 struct addrinfo sentinel, *cur;
1231 struct res_target q, q2;
1232
1233 memset(&q, 0, sizeof(q2));
1234 memset(&q2, 0, sizeof(q2));
1235 memset(&sentinel, 0, sizeof(sentinel));
1236 cur = &sentinel;
1237
1238 buf = malloc(sizeof(*buf));
1239 if (buf == NULL) {
1240 h_errno = NETDB_INTERNAL;
1241 return NULL;
1242 }
1243 buf2 = malloc(sizeof(*buf2));
1244 if (buf2 == NULL) {
1245 free(buf);
1246 h_errno = NETDB_INTERNAL;
1247 return NULL;
1248 }
1249
1250 switch (pai->ai_family) {
1251 case AF_UNSPEC:
1252 /* prefer IPv6 */
1253 q.qclass = C_IN;
1254 q.qtype = T_AAAA;
1255 q.answer = buf->buf;
1256 q.anslen = sizeof(buf->buf);
1257 q.next = &q2;
1258 q2.qclass = C_IN;
1259 q2.qtype = T_A;
1260 q2.answer = buf2->buf;
1261 q2.anslen = sizeof(buf2->buf);
1262 break;
1263 case AF_INET:
1264 q.qclass = C_IN;
1265 q.qtype = T_A;
1266 q.answer = buf->buf;
1267 q.anslen = sizeof(buf->buf);
1268 break;
1269 case AF_INET6:
1270 q.qclass = C_IN;
1271 q.qtype = T_AAAA;
1272 q.answer = buf->buf;
1273 q.anslen = sizeof(buf->buf);
1274 break;
1275 default:
1276 free(buf);
1277 free(buf2);
1278 return NULL;
1279 }
1280 if (res_searchN(name, &q) < 0) {
1281 free(buf);
1282 free(buf2);
1283 return NULL;
1284 }
1285 ai = getanswer(buf, q.n, q.name, q.qtype, pai);
1286 if (ai) {
1287 cur->ai_next = ai;
1288 while (cur && cur->ai_next)
1289 cur = cur->ai_next;
1290 }
1291 if (q.next) {
1292 ai = getanswer(buf2, q2.n, q2.name, q2.qtype, pai);
1293 if (ai)
1294 cur->ai_next = ai;
1295 }
1296 free(buf);
1297 free(buf2);
1298 return sentinel.ai_next;
1299}
1300
1301static FILE *hostf;
1302
1303static void
1304_sethtent()
1305{
1306 if (!hostf)
1307 hostf = fopen(_PATH_HOSTS, "r" );
1308 else
1309 rewind(hostf);
1310}
1311
1312static void
1313_endhtent()
1314{
1315 if (hostf) {
1316 (void) fclose(hostf);
1317 hostf = NULL;
1318 }
1319}
1320
1321static struct addrinfo *
1322_gethtent(name, pai)
1323 const char *name;
1324 const struct addrinfo *pai;
1325{
1326 char *p;
1327 char *cp, *tname, *cname;
1328 struct addrinfo hints, *res0, *res;
1329 int error;
1330 const char *addr;
1331 char hostbuf[8*1024];
1332
1333 if (!hostf && !(hostf = fopen(_PATH_HOSTS, "r" )))
1334 return (NULL);
1335 again:
1336 if (!(p = fgets(hostbuf, sizeof hostbuf, hostf)))
1337 return (NULL);
1338 if (*p == '#')
1339 goto again;
1340 if (!(cp = strpbrk(p, "#\n")))
1341 goto again;
1342 *cp = '\0';
1343 if (!(cp = strpbrk(p, " \t")))
1344 goto again;
1345 *cp++ = '\0';
1346 addr = p;
1347 /* if this is not something we're looking for, skip it. */
1348 cname = NULL;
1349 while (cp && *cp) {
1350 if (*cp == ' ' || *cp == '\t') {
1351 cp++;
1352 continue;
1353 }
1354 if (!cname)
1355 cname = cp;
1356 tname = cp;
1357 if ((cp = strpbrk(cp, " \t")) != NULL)
1358 *cp++ = '\0';
1359 if (strcasecmp(name, tname) == 0)
1360 goto found;
1361 }
1362 goto again;
1363
1364found:
1365 hints = *pai;
1366 hints.ai_flags = AI_NUMERICHOST;
1367 error = getaddrinfo(addr, NULL, &hints, &res0);
1368 if (error)
1369 goto again;
1370 for (res = res0; res; res = res->ai_next) {
1371 /* cover it up */
1372 res->ai_flags = pai->ai_flags;
1373
1374 if (pai->ai_flags & AI_CANONNAME) {
1375 if (get_canonname(pai, res, cname) != 0) {
1376 freeaddrinfo(res0);
1377 goto again;
1378 }
1379 }
1380 }
1381 return res0;
1382}
1383
1384/*ARGSUSED*/
1385static struct addrinfo *
1386_files_getaddrinfo(name, pai)
1387 const char *name;
1388 const struct addrinfo *pai;
1389{
1390 struct addrinfo sentinel, *cur;
1391 struct addrinfo *p;
1392
1393 memset(&sentinel, 0, sizeof(sentinel));
1394 cur = &sentinel;
1395
1396 _sethtent();
1397 while ((p = _gethtent(name, pai)) != NULL) {
1398 cur->ai_next = p;
1399 while (cur && cur->ai_next)
1400 cur = cur->ai_next;
1401 }
1402 _endhtent();
1403
1404 return sentinel.ai_next;
1405}
1406
1407#ifdef YP
1408static char *__ypdomain;
1409
1410/*ARGSUSED*/
1411static struct addrinfo *
1412_yphostent(line, pai)
1413 char *line;
1414 const struct addrinfo *pai;
1415{
1416 struct addrinfo sentinel, *cur;
1417 struct addrinfo hints, *res, *res0;
1418 int error;
1419 char *p = line;
1420 const char *addr, *canonname;
1421 char *nextline;
1422 char *cp;
1423
1424 addr = canonname = NULL;
1425
1426 memset(&sentinel, 0, sizeof(sentinel));
1427 cur = &sentinel;
1428
1429nextline:
1430 /* terminate line */
1431 cp = strchr(p, '\n');
1432 if (cp) {
1433 *cp++ = '\0';
1434 nextline = cp;
1435 } else
1436 nextline = NULL;
1437
1438 cp = strpbrk(p, " \t");
1439 if (cp == NULL) {
1440 if (canonname == NULL)
1441 return (NULL);
1442 else
1443 goto done;
1444 }
1445 *cp++ = '\0';
1446
1447 addr = p;
1448
1449 while (cp && *cp) {
1450 if (*cp == ' ' || *cp == '\t') {
1451 cp++;
1452 continue;
1453 }
1454 if (!canonname)
1455 canonname = cp;
1456 if ((cp = strpbrk(cp, " \t")) != NULL)
1457 *cp++ = '\0';
1458 }
1459
1460 hints = *pai;
1461 hints.ai_flags = AI_NUMERICHOST;
1462 error = getaddrinfo(addr, NULL, &hints, &res0);
1463 if (error == 0) {
1464 for (res = res0; res; res = res->ai_next) {
1465 /* cover it up */
1466 res->ai_flags = pai->ai_flags;
1467
1468 if (pai->ai_flags & AI_CANONNAME)
1469 (void)get_canonname(pai, res, canonname);
1470 }
1471 } else
1472 res0 = NULL;
1473 if (res0) {
1474 cur->ai_next = res0;
1475 while (cur && cur->ai_next)
1476 cur = cur->ai_next;
1477 }
1478
1479 if (nextline) {
1480 p = nextline;
1481 goto nextline;
1482 }
1483
1484done:
1485 return sentinel.ai_next;
1486}
1487
1488/*ARGSUSED*/
1489static struct addrinfo *
1490_yp_getaddrinfo(name, pai)
1491 const char *name;
1492 const struct addrinfo *pai;
1493{
1494 struct addrinfo sentinel, *cur;
1495 struct addrinfo *ai = NULL;
1496 static char *__ypcurrent;
1497 int __ypcurrentlen, r;
1498
1499 memset(&sentinel, 0, sizeof(sentinel));
1500 cur = &sentinel;
1501
1502 if (!__ypdomain) {
1503 if (_yp_check(&__ypdomain) == 0)
1504 return NULL;
1505 }
1506 if (__ypcurrent)
1507 free(__ypcurrent);
1508 __ypcurrent = NULL;
1509
1510 /* hosts.byname is only for IPv4 (Solaris8) */
1511 if (pai->ai_family == PF_UNSPEC || pai->ai_family == PF_INET) {
1512 r = yp_match(__ypdomain, "hosts.byname", name,
1513 (int)strlen(name), &__ypcurrent, &__ypcurrentlen);
1514 if (r == 0) {
1515 struct addrinfo ai4;
1516
1517 ai4 = *pai;
1518 ai4.ai_family = AF_INET;
1519 ai = _yphostent(__ypcurrent, &ai4);
1520 if (ai) {
1521 cur->ai_next = ai;
1522 while (cur && cur->ai_next)
1523 cur = cur->ai_next;
1524 }
1525 }
1526 }
1527
1528 /* ipnodes.byname can hold both IPv4/v6 */
1529 r = yp_match(__ypdomain, "ipnodes.byname", name,
1530 (int)strlen(name), &__ypcurrent, &__ypcurrentlen);
1531 if (r == 0) {
1532 ai = _yphostent(__ypcurrent, pai);
1533 if (ai) {
1534 cur->ai_next = ai;
1535 while (cur && cur->ai_next)
1536 cur = cur->ai_next;
1537 }
1538 }
1539
1540 return sentinel.ai_next;
1541}
1542#endif
1543
1544
1545/* resolver logic */
1546
1547extern const char *__hostalias(const char *);
1548extern int h_errno;
1549extern int res_opt(int, u_char *, int, int);
1550
1551/*
1552 * Formulate a normal query, send, and await answer.
1553 * Returned answer is placed in supplied buffer "answer".
1554 * Perform preliminary check of answer, returning success only
1555 * if no error is indicated and the answer count is nonzero.
1556 * Return the size of the response on success, -1 on error.
1557 * Error number is left in h_errno.
1558 *
1559 * Caller must parse answer and determine whether it answers the question.
1560 */
1561static int
1562res_queryN(name, target)
1563 const char *name; /* domain name */
1564 struct res_target *target;
1565{
1566 u_char buf[MAXPACKET];
1567 HEADER *hp;
1568 int n;
1569 struct res_target *t;
1570 int rcode;
1571 int ancount;
1572
1573 rcode = NOERROR;
1574 ancount = 0;
1575
1576 if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
1577 h_errno = NETDB_INTERNAL;
1578 return (-1);
1579 }
1580
1581 for (t = target; t; t = t->next) {
1582 int class, type;
1583 u_char *answer;
1584 int anslen;
1585
1586 hp = (HEADER *)(void *)t->answer;
1587 hp->rcode = NOERROR; /* default */
1588
1589 /* make it easier... */
1590 class = t->qclass;
1591 type = t->qtype;
1592 answer = t->answer;
1593 anslen = t->anslen;
1594#ifdef DEBUG
1595 if (_res.options & RES_DEBUG)
1596 printf(";; res_query(%s, %d, %d)\n", name, class, type);
1597#endif
1598
1599 n = res_mkquery(QUERY, name, class, type, NULL, 0, NULL,
1600 buf, sizeof(buf));
1601 if (n > 0 && (_res.options & RES_USE_EDNS0) != 0)
1602 n = res_opt(n, buf, sizeof(buf), anslen);
1603 if (n <= 0) {
1604#ifdef DEBUG
1605 if (_res.options & RES_DEBUG)
1606 printf(";; res_query: mkquery failed\n");
1607#endif
1608 h_errno = NO_RECOVERY;
1609 return (n);
1610 }
1611 n = res_send(buf, n, answer, anslen);
1612#if 0
1613 if (n < 0) {
1614#ifdef DEBUG
1615 if (_res.options & RES_DEBUG)
1616 printf(";; res_query: send error\n");
1617#endif
1618 h_errno = TRY_AGAIN;
1619 return (n);
1620 }
1621#endif
1622
1623 if (n < 0 || hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
1624 rcode = hp->rcode; /* record most recent error */
1625#ifdef DEBUG
1626 if (_res.options & RES_DEBUG)
1627 printf(";; rcode = %u, ancount=%u\n", hp->rcode,
1628 ntohs(hp->ancount));
1629#endif
1630 continue;
1631 }
1632
1633 ancount += ntohs(hp->ancount);
1634
1635 t->n = n;
1636 }
1637
1638 if (ancount == 0) {
1639 switch (rcode) {
1640 case NXDOMAIN:
1641 h_errno = HOST_NOT_FOUND;
1642 break;
1643 case SERVFAIL:
1644 h_errno = TRY_AGAIN;
1645 break;
1646 case NOERROR:
1647 h_errno = NO_DATA;
1648 break;
1649 case FORMERR:
1650 case NOTIMP:
1651 case REFUSED:
1652 default:
1653 h_errno = NO_RECOVERY;
1654 break;
1655 }
1656 return (-1);
1657 }
1658 return (ancount);
1659}
1660
1661/*
1662 * Formulate a normal query, send, and retrieve answer in supplied buffer.
1663 * Return the size of the response on success, -1 on error.
1664 * If enabled, implement search rules until answer or unrecoverable failure
1665 * is detected. Error code, if any, is left in h_errno.
1666 */
1667static int
1668res_searchN(name, target)
1669 const char *name; /* domain name */
1670 struct res_target *target;
1671{
1672 const char *cp, * const *domain;
1673 HEADER *hp = (HEADER *)(void *)target->answer; /*XXX*/
1674 u_int dots;
1675 int trailing_dot, ret, saved_herrno;
1676 int got_nodata = 0, got_servfail = 0, tried_as_is = 0;
1677
1678 if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
1679 h_errno = NETDB_INTERNAL;
1680 return (-1);
1681 }
1682
1683 errno = 0;
1684 h_errno = HOST_NOT_FOUND; /* default, if we never query */
1685 dots = 0;
1686 for (cp = name; *cp; cp++)
1687 dots += (*cp == '.');
1688 trailing_dot = 0;
1689 if (cp > name && *--cp == '.')
1690 trailing_dot++;
1691
1692 /*
1693 * if there aren't any dots, it could be a user-level alias
1694 */
1695 if (!dots && (cp = __hostalias(name)) != NULL)
1696 return (res_queryN(cp, target));
1697
1698 /*
1699 * If there are dots in the name already, let's just give it a try
1700 * 'as is'. The threshold can be set with the "ndots" option.
1701 */
1702 saved_herrno = -1;
1703 if (dots >= _res.ndots) {
1704 ret = res_querydomainN(name, NULL, target);
1705 if (ret > 0)
1706 return (ret);
1707 saved_herrno = h_errno;
1708 tried_as_is++;
1709 }
1710
1711 /*
1712 * We do at least one level of search if
1713 * - there is no dot and RES_DEFNAME is set, or
1714 * - there is at least one dot, there is no trailing dot,
1715 * and RES_DNSRCH is set.
1716 */
1717 if ((!dots && (_res.options & RES_DEFNAMES)) ||
1718 (dots && !trailing_dot && (_res.options & RES_DNSRCH))) {
1719 int done = 0;
1720
1721 for (domain = (const char * const *)_res.dnsrch;
1722 *domain && !done;
1723 domain++) {
1724
1725 ret = res_querydomainN(name, *domain, target);
1726 if (ret > 0)
1727 return (ret);
1728
1729 /*
1730 * If no server present, give up.
1731 * If name isn't found in this domain,
1732 * keep trying higher domains in the search list
1733 * (if that's enabled).
1734 * On a NO_DATA error, keep trying, otherwise
1735 * a wildcard entry of another type could keep us
1736 * from finding this entry higher in the domain.
1737 * If we get some other error (negative answer or
1738 * server failure), then stop searching up,
1739 * but try the input name below in case it's
1740 * fully-qualified.
1741 */
1742 if (errno == ECONNREFUSED) {
1743 h_errno = TRY_AGAIN;
1744 return (-1);
1745 }
1746
1747 switch (h_errno) {
1748 case NO_DATA:
1749 got_nodata++;
1750 /* FALLTHROUGH */
1751 case HOST_NOT_FOUND:
1752 /* keep trying */
1753 break;
1754 case TRY_AGAIN:
1755 if (hp->rcode == SERVFAIL) {
1756 /* try next search element, if any */
1757 got_servfail++;
1758 break;
1759 }
1760 /* FALLTHROUGH */
1761 default:
1762 /* anything else implies that we're done */
1763 done++;
1764 }
1765 /*
1766 * if we got here for some reason other than DNSRCH,
1767 * we only wanted one iteration of the loop, so stop.
1768 */
1769 if (!(_res.options & RES_DNSRCH))
1770 done++;
1771 }
1772 }
1773
1774 /*
1775 * if we have not already tried the name "as is", do that now.
1776 * note that we do this regardless of how many dots were in the
1777 * name or whether it ends with a dot.
1778 */
1779 if (!tried_as_is) {
1780 ret = res_querydomainN(name, NULL, target);
1781 if (ret > 0)
1782 return (ret);
1783 }
1784
1785 /*
1786 * if we got here, we didn't satisfy the search.
1787 * if we did an initial full query, return that query's h_errno
1788 * (note that we wouldn't be here if that query had succeeded).
1789 * else if we ever got a nodata, send that back as the reason.
1790 * else send back meaningless h_errno, that being the one from
1791 * the last DNSRCH we did.
1792 */
1793 if (saved_herrno != -1)
1794 h_errno = saved_herrno;
1795 else if (got_nodata)
1796 h_errno = NO_DATA;
1797 else if (got_servfail)
1798 h_errno = TRY_AGAIN;
1799 return (-1);
1800}
1801
1802/*
1803 * Perform a call on res_query on the concatenation of name and domain,
1804 * removing a trailing dot from name if domain is NULL.
1805 */
1806static int
1807res_querydomainN(name, domain, target)
1808 const char *name, *domain;
1809 struct res_target *target;
1810{
1811 char nbuf[MAXDNAME];
1812 const char *longname = nbuf;
1813 size_t n, d;
1814
1815 if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
1816 h_errno = NETDB_INTERNAL;
1817 return (-1);
1818 }
1819#ifdef DEBUG
1820 if (_res.options & RES_DEBUG)
1821 printf(";; res_querydomain(%s, %s)\n",
1822 name, domain?domain:"<Nil>");
1823#endif
1824 if (domain == NULL) {
1825 /*
1826 * Check for trailing '.';
1827 * copy without '.' if present.
1828 */
1829 n = strlen(name);
1830 if (n >= MAXDNAME) {
1831 h_errno = NO_RECOVERY;
1832 return (-1);
1833 }
1834 if (n > 0 && name[--n] == '.') {
1835 strlcpy(nbuf, name, n + 1);
1836 } else
1837 longname = name;
1838 } else {
1839 n = strlen(name);
1840 d = strlen(domain);
1841 if (n + d + 1 >= MAXDNAME) {
1842 h_errno = NO_RECOVERY;
1843 return (-1);
1844 }
1845 snprintf(nbuf, sizeof(nbuf), "%s.%s", name, domain);
1846 }
1847 return (res_queryN(longname, target));
1848}
diff --git a/src/lib/libc/net/gethostbyname.3 b/src/lib/libc/net/gethostbyname.3
new file mode 100644
index 0000000000..d90ea55542
--- /dev/null
+++ b/src/lib/libc/net/gethostbyname.3
@@ -0,0 +1,275 @@
1.\" $OpenBSD: gethostbyname.3,v 1.17 2002/04/30 16:31:42 mpech Exp $
2.\"
3.\" Copyright (c) 1983, 1987, 1991, 1993
4.\" The Regents of the University of California. All rights reserved.
5.\"
6.\" Redistribution and use in source and binary forms, with or without
7.\" modification, are permitted provided that the following conditions
8.\" are met:
9.\" 1. Redistributions of source code must retain the above copyright
10.\" notice, this list of conditions and the following disclaimer.
11.\" 2. Redistributions in binary form must reproduce the above copyright
12.\" notice, this list of conditions and the following disclaimer in the
13.\" documentation and/or other materials provided with the distribution.
14.\" 3. All advertising materials mentioning features or use of this software
15.\" must display the following acknowledgement:
16.\" This product includes software developed by the University of
17.\" California, Berkeley and its contributors.
18.\" 4. Neither the name of the University nor the names of its contributors
19.\" may be used to endorse or promote products derived from this software
20.\" without specific prior written permission.
21.\"
22.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32.\" SUCH DAMAGE.
33.\"
34.Dd March 13, 1997
35.Dt GETHOSTBYNAME 3
36.Os
37.Sh NAME
38.Nm gethostbyname ,
39.Nm gethostbyname2 ,
40.Nm gethostbyaddr ,
41.Nm gethostent ,
42.Nm sethostent ,
43.Nm endhostent ,
44.Nm hstrerror ,
45.Nm herror
46.Nd get network host entry
47.Sh SYNOPSIS
48.Fd #include <netdb.h>
49.Fd extern int h_errno;
50.Ft struct hostent *
51.Fn gethostbyname "const char *name"
52.Ft struct hostent *
53.Fn gethostbyname2 "const char *name" "int af"
54.Ft struct hostent *
55.Fn gethostbyaddr "const char *addr" "int len" "int af"
56.Ft struct hostent *
57.Fn gethostent void
58.Ft void
59.Fn sethostent "int stayopen"
60.Ft void
61.Fn endhostent void
62.Ft void
63.Fn herror "const char *string"
64.Ft const char *
65.Fn hstrerror "int err"
66.Sh DESCRIPTION
67The
68.Fn gethostbyname
69and
70.Fn gethostbyaddr
71functions each return a pointer to an object with the following structure
72describing an internet host referenced by name or by address, respectively.
73This structure contains either information obtained from the name server (i.e.,
74.Xr resolver 3
75and
76.Xr named 8 ) ,
77broken-out fields from a line in
78.Pa /etc/hosts ,
79or database entries supplied by the
80.Xr yp 8
81system.
82.Xr resolv.conf 5
83describes how the particular database is chosen.
84.Bd -literal
85struct hostent {
86 char *h_name; /* official name of host */
87 char **h_aliases; /* alias list */
88 int h_addrtype; /* host address type */
89 int h_length; /* length of address */
90 char **h_addr_list; /* list of addresses from name server */
91};
92#define h_addr h_addr_list[0] /* address, for backward compatibility */
93.Ed
94.Pp
95The members of this structure are:
96.Bl -tag -width h_addr_list
97.It Fa h_name
98Official name of the host.
99.It Fa h_aliases
100A zero-terminated array of alternate names for the host.
101.It Fa h_addrtype
102The type of address being returned.
103.It Fa h_length
104The length, in bytes, of the address.
105.It Fa h_addr_list
106A zero-terminated array of network addresses for the host.
107Host addresses are returned in network byte order.
108.It Fa h_addr
109The first address in
110.Fa h_addr_list ;
111this is for backward compatibility.
112.El
113.Pp
114The function
115.Fn gethostbyname
116will search for the named host in the current domain and its parents
117using the search lookup semantics detailed in
118.Xr resolv.conf 5
119and
120.Xr hostname 7 .
121.Pp
122.Fn gethostbyname2
123is an advanced form of
124.Fn gethostbyname
125which allows lookups in address families other than
126.Dv AF_INET ,
127for example
128.Dv AF_INET6 .
129.Pp
130The
131.Fn gethostbyaddr
132function will search for the specified address of length
133.Fa len
134in the address family
135.Fa af .
136The only address family currently supported is
137.Dv AF_INET .
138.Pp
139The
140.Fn sethostent
141function may be used to request the use of a connected
142.Tn TCP
143socket for queries.
144If the
145.Fa stayopen
146flag is non-zero,
147this sets the option to send all queries to the name server using
148.Tn TCP
149and to retain the connection after each call to
150.Fn gethostbyname
151or
152.Fn gethostbyaddr .
153Otherwise, queries are performed using
154.Tn UDP
155datagrams.
156.Pp
157The
158.Fn endhostent
159function closes the
160.Tn TCP
161connection.
162.Pp
163The
164.Fn herror
165function prints an error message describing the failure.
166If its argument
167.Fa string
168is non-null,
169it is prepended to the message string and separated from it by a colon
170.Pq Ql \&:
171and a space.
172The error message is printed with a trailing newline.
173The contents of the error message is the same as that returned by
174.Fn hstrerror
175with argument
176.Fa h_errno .
177.Sh FILES
178.Bl -tag -width /etc/resolv.conf -compact
179.It Pa /etc/hosts
180.It Pa /etc/resolv.conf
181.El
182.Sh DIAGNOSTICS
183Error return status from
184.Fn gethostbyname ,
185.Fn gethostbyname2 ,
186and
187.Fn gethostbyaddr
188is indicated by return of a null pointer.
189The external integer
190.Va h_errno
191may then be checked to see whether this is a temporary failure
192or an invalid or unknown host.
193.Pp
194The variable
195.Va h_errno
196can have the following values:
197.Bl -tag -width HOST_NOT_FOUND
198.It Dv HOST_NOT_FOUND
199No such host is known.
200.It Dv TRY_AGAIN
201This is usually a temporary error
202and means that the local server did not receive
203a response from an authoritative server.
204A retry at some later time may succeed.
205.It Dv NO_RECOVERY
206Some unexpected server failure was encountered.
207This is a non-recoverable error.
208.It Dv NO_DATA
209The requested name is valid but does not have an IP address;
210this is not a temporary error.
211This means that the name is known to the name server but there is no address
212associated with this name.
213Another type of request to the name server using this domain name
214will result in an answer;
215for example, a mail-forwarder may be registered for this domain.
216.El
217.Sh SEE ALSO
218.Xr resolver 3 ,
219.Xr getaddrinfo 3 ,
220.Xr getnameinfo 3 ,
221.Xr hosts 5 ,
222.Xr resolv.conf 5 ,
223.Xr hostname 7 ,
224.Xr named 8
225.Sh CAVEATS
226If the search routines in
227.Xr resolv.conf 5
228decide to read the
229.Pa /etc/hosts
230file,
231.Fn gethostent
232and other functions will
233read the next line of the file,
234re-opening the file if necessary.
235.Pp
236The
237.Fn sethostent
238function opens and/or rewinds the file
239.Pa /etc/hosts .
240If the
241.Fa stayopen
242argument is non-zero, the file will not be closed after each call to
243.Fn gethostbyname ,
244.Fn gethostbyname2 ,
245or
246.Fn gethostbyaddr .
247.Pp
248The
249.Fn endhostent
250function closes the file.
251.Sh HISTORY
252The
253.Fn herror
254function appeared in
255.Bx 4.3 .
256The
257.Fn endhostent ,
258.Fn gethostbyaddr ,
259.Fn gethostbyname ,
260.Fn gethostent ,
261and
262.Fn sethostent
263functions appeared in
264.Bx 4.2 .
265.Sh BUGS
266These functions use static data storage;
267if the data is needed for future use, it should be
268copied before any subsequent calls overwrite it.
269Only the Internet
270address formats are currently understood.
271.Pp
272YP does not support any address families other than
273.Dv AF_INET
274and uses
275the traditional database format.
diff --git a/src/lib/libc/net/gethostnamadr.c b/src/lib/libc/net/gethostnamadr.c
new file mode 100644
index 0000000000..909ce573b7
--- /dev/null
+++ b/src/lib/libc/net/gethostnamadr.c
@@ -0,0 +1,1175 @@
1/*-
2 * Copyright (c) 1985, 1988, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 * -
33 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
34 *
35 * Permission to use, copy, modify, and distribute this software for any
36 * purpose with or without fee is hereby granted, provided that the above
37 * copyright notice and this permission notice appear in all copies, and that
38 * the name of Digital Equipment Corporation not be used in advertising or
39 * publicity pertaining to distribution of the document or software without
40 * specific, written prior permission.
41 *
42 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
43 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
44 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
45 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
46 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
47 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
48 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
49 * SOFTWARE.
50 * -
51 * --Copyright--
52 */
53
54#if defined(LIBC_SCCS) && !defined(lint)
55static char rcsid[] = "$OpenBSD: gethostnamadr.c,v 1.53 2002/08/27 08:53:13 itojun Exp $";
56#endif /* LIBC_SCCS and not lint */
57
58#include <sys/param.h>
59#include <sys/socket.h>
60#include <netinet/in.h>
61#include <arpa/inet.h>
62#include <arpa/nameser.h>
63#include <netdb.h>
64#include <resolv.h>
65#include <stdio.h>
66#include <ctype.h>
67#include <errno.h>
68#include <string.h>
69#include <syslog.h>
70#include <stdlib.h>
71#ifdef YP
72#include <rpc/rpc.h>
73#include <rpcsvc/yp.h>
74#include <rpcsvc/ypclnt.h>
75#include "ypinternal.h"
76#endif
77#include "thread_private.h"
78
79#define MULTI_PTRS_ARE_ALIASES 1 /* XXX - experimental */
80
81#define MAXALIASES 35
82#define MAXADDRS 35
83
84static char *h_addr_ptrs[MAXADDRS + 1];
85
86#ifdef YP
87static char *__ypdomain;
88#endif
89
90static struct hostent host;
91static char *host_aliases[MAXALIASES];
92static char hostbuf[BUFSIZ+1];
93static union {
94 struct in_addr _host_in_addr;
95 u_char _host_addr[16]; /* IPv4 or IPv6 */
96} _host_addr_u;
97#define host_addr _host_addr_u._host_addr
98static FILE *hostf = NULL;
99static int stayopen = 0;
100
101static void map_v4v6_address(const char *src, char *dst);
102static void map_v4v6_hostent(struct hostent *hp, char **bp, char *);
103
104#ifdef RESOLVSORT
105static void addrsort(char **, int);
106#endif
107
108int _hokchar(const char *);
109
110static const char AskedForGot[] =
111 "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
112
113#define MAXPACKET (64*1024)
114
115typedef union {
116 HEADER hdr;
117 u_char buf[MAXPACKET];
118} querybuf;
119
120typedef union {
121 int32_t al;
122 char ac;
123} align;
124
125static struct hostent *getanswer(const querybuf *, int, const char *, int);
126
127extern int h_errno;
128
129int
130_hokchar(p)
131 const char *p;
132{
133 char c;
134
135 /*
136 * Many people do not obey RFC 822 and 1035. The valid
137 * characters are a-z, A-Z, 0-9, '-' and . But the others
138 * tested for below can happen, and we must be more permissive
139 * than the resolver until those idiots clean up their act.
140 * We let '/' through, but not '..'
141 */
142 while ((c = *p++)) {
143 if (('a' <= c && c <= 'z') ||
144 ('A' <= c && c <= 'Z') ||
145 ('0' <= c && c <= '9'))
146 continue;
147 if (strchr("-_/", c))
148 continue;
149 if (c == '.' && *p != '.')
150 continue;
151 return 0;
152 }
153 return 1;
154}
155
156static struct hostent *
157getanswer(answer, anslen, qname, qtype)
158 const querybuf *answer;
159 int anslen;
160 const char *qname;
161 int qtype;
162{
163 register const HEADER *hp;
164 register const u_char *cp;
165 register int n;
166 const u_char *eom;
167 char *bp, **ap, **hap, *ep;
168 int type, class, ancount, qdcount;
169 int haveanswer, had_error;
170 int toobig = 0;
171 char tbuf[MAXDNAME];
172 const char *tname;
173 int (*name_ok)(const char *);
174
175 tname = qname;
176 host.h_name = NULL;
177 eom = answer->buf + anslen;
178 switch (qtype) {
179 case T_A:
180 case T_AAAA:
181#ifdef USE_RESOLV_NAME_OK
182 name_ok = res_hnok;
183 break;
184#endif
185 case T_PTR:
186#ifdef USE_RESOLV_NAME_OK
187 name_ok = res_dnok;
188#else
189 name_ok = _hokchar;
190#endif
191 break;
192 default:
193 return (NULL);
194 }
195 /*
196 * find first satisfactory answer
197 */
198 hp = &answer->hdr;
199 ancount = ntohs(hp->ancount);
200 qdcount = ntohs(hp->qdcount);
201 bp = hostbuf;
202 ep = hostbuf + sizeof hostbuf;
203 cp = answer->buf + HFIXEDSZ;
204 if (qdcount != 1) {
205 h_errno = NO_RECOVERY;
206 return (NULL);
207 }
208 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
209 if ((n < 0) || !(*name_ok)(bp)) {
210 h_errno = NO_RECOVERY;
211 return (NULL);
212 }
213 cp += n + QFIXEDSZ;
214 if (qtype == T_A || qtype == T_AAAA) {
215 /* res_send() has already verified that the query name is the
216 * same as the one we sent; this just gets the expanded name
217 * (i.e., with the succeeding search-domain tacked on).
218 */
219 n = strlen(bp) + 1; /* for the \0 */
220 host.h_name = bp;
221 bp += n;
222 /* The qname can be abbreviated, but h_name is now absolute. */
223 qname = host.h_name;
224 }
225 ap = host_aliases;
226 *ap = NULL;
227 host.h_aliases = host_aliases;
228 hap = h_addr_ptrs;
229 *hap = NULL;
230 host.h_addr_list = h_addr_ptrs;
231 haveanswer = 0;
232 had_error = 0;
233 while (ancount-- > 0 && cp < eom && !had_error) {
234 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
235 if ((n < 0) || !(*name_ok)(bp)) {
236 had_error++;
237 continue;
238 }
239 cp += n; /* name */
240 type = _getshort(cp);
241 cp += INT16SZ; /* type */
242 class = _getshort(cp);
243 cp += INT16SZ + INT32SZ; /* class, TTL */
244 n = _getshort(cp);
245 cp += INT16SZ; /* len */
246 if (type == T_SIG) {
247 /* XXX - ignore signatures as we don't use them yet */
248 cp += n;
249 continue;
250 }
251 if (class != C_IN) {
252 /* XXX - debug? syslog? */
253 cp += n;
254 continue; /* XXX - had_error++ ? */
255 }
256 if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) {
257 if (ap >= &host_aliases[MAXALIASES-1])
258 continue;
259 n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
260 if ((n < 0) || !(*name_ok)(tbuf)) {
261 had_error++;
262 continue;
263 }
264 cp += n;
265 /* Store alias. */
266 *ap++ = bp;
267 n = strlen(bp) + 1; /* for the \0 */
268 bp += n;
269 /* Get canonical name. */
270 n = strlen(tbuf) + 1; /* for the \0 */
271 if (n > ep - bp) {
272 had_error++;
273 continue;
274 }
275 strlcpy(bp, tbuf, ep - bp);
276 host.h_name = bp;
277 bp += n;
278 continue;
279 }
280 if (qtype == T_PTR && type == T_CNAME) {
281 n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
282#ifdef USE_RESOLV_NAME_OK
283 if ((n < 0) || !res_hnok(tbuf)) {
284#else
285 if ((n < 0) || !_hokchar(tbuf)) {
286#endif
287 had_error++;
288 continue;
289 }
290 cp += n;
291 /* Get canonical name. */
292 n = strlen(tbuf) + 1; /* for the \0 */
293 if (n > ep - bp) {
294 had_error++;
295 continue;
296 }
297 strlcpy(bp, tbuf, ep - bp);
298 tname = bp;
299 bp += n;
300 continue;
301 }
302 if (type != qtype) {
303 syslog(LOG_NOTICE|LOG_AUTH,
304 "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
305 qname, p_class(C_IN), p_type(qtype),
306 p_type(type));
307 cp += n;
308 continue; /* XXX - had_error++ ? */
309 }
310 switch (type) {
311 case T_PTR:
312 if (strcasecmp(tname, bp) != 0) {
313 syslog(LOG_NOTICE|LOG_AUTH,
314 AskedForGot, qname, bp);
315 cp += n;
316 continue; /* XXX - had_error++ ? */
317 }
318 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
319#ifdef USE_RESOLV_NAME_OK
320 if ((n < 0) || !res_hnok(bp)) {
321#else
322 if ((n < 0) || !_hokchar(bp)) {
323#endif
324 had_error++;
325 break;
326 }
327#if MULTI_PTRS_ARE_ALIASES
328 cp += n;
329 if (!haveanswer)
330 host.h_name = bp;
331 else if (ap < &host_aliases[MAXALIASES-1])
332 *ap++ = bp;
333 else
334 n = -1;
335 if (n != -1) {
336 n = strlen(bp) + 1; /* for the \0 */
337 bp += n;
338 }
339 break;
340#else
341 host.h_name = bp;
342 if (_res.options & RES_USE_INET6) {
343 n = strlen(bp) + 1; /* for the \0 */
344 bp += n;
345 map_v4v6_hostent(&host, &bp, ep);
346 }
347 h_errno = NETDB_SUCCESS;
348 return (&host);
349#endif
350 case T_A:
351 case T_AAAA:
352 if (strcasecmp(host.h_name, bp) != 0) {
353 syslog(LOG_NOTICE|LOG_AUTH,
354 AskedForGot, host.h_name, bp);
355 cp += n;
356 continue; /* XXX - had_error++ ? */
357 }
358 if (n != host.h_length) {
359 cp += n;
360 continue;
361 }
362 if (type == T_AAAA) {
363 struct in6_addr in6;
364 memcpy(&in6, cp, IN6ADDRSZ);
365 if (IN6_IS_ADDR_V4MAPPED(&in6)) {
366 cp += n;
367 continue;
368 }
369 }
370 if (!haveanswer) {
371 register int nn;
372
373 host.h_name = bp;
374 nn = strlen(bp) + 1; /* for the \0 */
375 bp += nn;
376 }
377
378 bp += sizeof(align) - ((u_long)bp % sizeof(align));
379
380 if (bp + n >= &hostbuf[sizeof hostbuf]) {
381#ifdef DEBUG
382 if (_res.options & RES_DEBUG)
383 printf("size (%d) too big\n", n);
384#endif
385 had_error++;
386 continue;
387 }
388 if (hap >= &h_addr_ptrs[MAXADDRS-1]) {
389 if (!toobig++)
390#ifdef DEBUG
391 if (_res.options & RES_DEBUG)
392 printf("Too many addresses (%d)\n", MAXADDRS);
393#endif
394 cp += n;
395 continue;
396 }
397 bcopy(cp, *hap++ = bp, n);
398 bp += n;
399 cp += n;
400 break;
401 }
402 if (!had_error)
403 haveanswer++;
404 }
405 if (haveanswer) {
406 *ap = NULL;
407 *hap = NULL;
408# if defined(RESOLVSORT)
409 /*
410 * Note: we sort even if host can take only one address
411 * in its return structures - should give it the "best"
412 * address in that case, not some random one
413 */
414 if (_res.nsort && haveanswer > 1 && qtype == T_A)
415 addrsort(h_addr_ptrs, haveanswer);
416# endif /*RESOLVSORT*/
417 if (!host.h_name) {
418 n = strlen(qname) + 1; /* for the \0 */
419 if (n > ep - bp)
420 goto try_again;
421 strlcpy(bp, qname, ep - bp);
422 host.h_name = bp;
423 bp += n;
424 }
425 if (_res.options & RES_USE_INET6)
426 map_v4v6_hostent(&host, &bp, ep);
427 h_errno = NETDB_SUCCESS;
428 return (&host);
429 }
430 try_again:
431 h_errno = TRY_AGAIN;
432 return (NULL);
433}
434
435#ifdef notyet
436/*
437 * XXX This is an extremely bogus implementation.
438 *
439 * FreeBSD has this interface:
440 * int gethostbyaddr_r(const char *addr, int len, int type,
441 * struct hostent *result, struct hostent_data *buffer)
442 */
443
444struct hostent *
445gethostbyname_r(name, hp, buf, buflen, errorp)
446 const char * name;
447 struct hostent * hp;
448 char * buf;
449 int buflen;
450 int * errorp;
451{
452 struct hostent *res;
453
454 res = gethostbyname(name);
455 *errorp = h_errno;
456 if (res == NULL)
457 return NULL;
458 memcpy(hp, res, sizeof *hp); /* XXX not sufficient */
459 return hp;
460}
461
462/*
463 * XXX This is an extremely bogus implementation.
464 */
465struct hostent *
466gethostbyaddr_r(addr, len, af, he, buf, buflen, errorp)
467 const char *addr; /* XXX should have been def'd as u_char! */
468 int len, af;
469 struct hostent * he;
470 char * buf;
471 int buflen;
472 int * errorp;
473{
474 struct hostent * res;
475
476 res = gethostbyaddr(addr, len, af);
477 *errorp = h_errno;
478 if (res == NULL)
479 return NULL;
480 memcpy(he, res, sizeof *he); /* XXX not sufficient */
481 return he;
482}
483
484/* XXX RFC2133 expects a gethostbyname2_r() -- unimplemented */
485#endif
486
487_THREAD_PRIVATE_MUTEX(gethostnamadr);
488
489struct hostent *
490gethostbyname(name)
491 const char *name;
492{
493 struct hostent *hp;
494 extern struct hostent *_gethtbyname2();
495
496 _THREAD_PRIVATE_MUTEX_LOCK(gethostnamadr);
497 if ((_res.options & RES_INIT) == 0 && res_init() == -1)
498 hp = _gethtbyname2(name, AF_INET);
499
500 else if (_res.options & RES_USE_INET6) {
501 hp = gethostbyname2(name, AF_INET6);
502 if (hp == NULL)
503 hp = gethostbyname2(name, AF_INET);
504 }
505 else
506 hp = gethostbyname2(name, AF_INET);
507 _THREAD_PRIVATE_MUTEX_UNLOCK(gethostnamadr);
508 return hp;
509}
510
511struct hostent *
512gethostbyname2(name, af)
513 const char *name;
514 int af;
515{
516 querybuf *buf;
517 register const char *cp;
518 char *bp, *ep;
519 int n, size, type, i;
520 extern struct hostent *_gethtbyname2(), *_yp_gethtbyname();
521 register struct hostent *hp;
522 char lookups[MAXDNSLUS];
523
524 if ((_res.options & RES_INIT) == 0 && res_init() == -1)
525 return (_gethtbyname2(name, af));
526
527 switch (af) {
528 case AF_INET:
529 size = INADDRSZ;
530 type = T_A;
531 break;
532 case AF_INET6:
533 size = IN6ADDRSZ;
534 type = T_AAAA;
535 break;
536 default:
537 h_errno = NETDB_INTERNAL;
538 errno = EAFNOSUPPORT;
539 return (NULL);
540 }
541
542 host.h_addrtype = af;
543 host.h_length = size;
544
545 /*
546 * if there aren't any dots, it could be a user-level alias.
547 * this is also done in res_query() since we are not the only
548 * function that looks up host names.
549 */
550 if (!strchr(name, '.') && (cp = __hostalias(name)))
551 name = cp;
552
553 /*
554 * disallow names consisting only of digits/dots, unless
555 * they end in a dot.
556 */
557 if (isdigit(name[0]))
558 for (cp = name;; ++cp) {
559 if (!*cp) {
560 if (*--cp == '.')
561 break;
562 /*
563 * All-numeric, no dot at the end.
564 * Fake up a hostent as if we'd actually
565 * done a lookup.
566 */
567 if (inet_pton(af, name, host_addr) <= 0) {
568 h_errno = HOST_NOT_FOUND;
569 return (NULL);
570 }
571 strlcpy(hostbuf, name, MAXHOSTNAMELEN);
572 bp = hostbuf + MAXHOSTNAMELEN;
573 ep = hostbuf + sizeof(hostbuf);
574 host.h_name = hostbuf;
575 host.h_aliases = host_aliases;
576 host_aliases[0] = NULL;
577 h_addr_ptrs[0] = (char *)host_addr;
578 h_addr_ptrs[1] = NULL;
579 host.h_addr_list = h_addr_ptrs;
580 if (_res.options & RES_USE_INET6)
581 map_v4v6_hostent(&host, &bp, ep);
582 h_errno = NETDB_SUCCESS;
583 return (&host);
584 }
585 if (!isdigit(*cp) && *cp != '.')
586 break;
587 }
588 if ((isxdigit(name[0]) && strchr(name, ':') != NULL) ||
589 name[0] == ':')
590 for (cp = name;; ++cp) {
591 if (!*cp) {
592 if (*--cp == '.')
593 break;
594 /*
595 * All-IPv6-legal, no dot at the end.
596 * Fake up a hostent as if we'd actually
597 * done a lookup.
598 */
599 if (inet_pton(af, name, host_addr) <= 0) {
600 h_errno = HOST_NOT_FOUND;
601 return (NULL);
602 }
603 strlcpy(hostbuf, name, MAXHOSTNAMELEN);
604 bp = hostbuf + MAXHOSTNAMELEN;
605 ep = hostbuf + sizeof(hostbuf);
606 host.h_name = hostbuf;
607 host.h_aliases = host_aliases;
608 host_aliases[0] = NULL;
609 h_addr_ptrs[0] = (char *)host_addr;
610 h_addr_ptrs[1] = NULL;
611 host.h_addr_list = h_addr_ptrs;
612 h_errno = NETDB_SUCCESS;
613 return (&host);
614 }
615 if (!isxdigit(*cp) && *cp != ':' && *cp != '.')
616 break;
617 }
618
619 bcopy(_res.lookups, lookups, sizeof lookups);
620 if (lookups[0] == '\0')
621 strlcpy(lookups, "bf", sizeof lookups);
622
623 hp = (struct hostent *)NULL;
624 for (i = 0; i < MAXDNSLUS && hp == NULL && lookups[i]; i++) {
625 switch (lookups[i]) {
626#ifdef YP
627 case 'y':
628 /* YP only supports AF_INET. */
629 if (af == AF_INET)
630 hp = _yp_gethtbyname(name);
631 break;
632#endif
633 case 'b':
634 buf = malloc(sizeof(*buf));
635 if (buf == NULL)
636 break;
637 if ((n = res_search(name, C_IN, type, buf->buf,
638 sizeof(buf->buf))) < 0) {
639 free(buf);
640#ifdef DEBUG
641 if (_res.options & RES_DEBUG)
642 printf("res_search failed\n");
643#endif
644 break;
645 }
646 hp = getanswer(buf, n, name, type);
647 free(buf);
648 break;
649 case 'f':
650 hp = _gethtbyname2(name, af);
651 break;
652 }
653 }
654 /* XXX h_errno not correct in all cases... */
655 return (hp);
656}
657
658struct hostent *
659gethostbyaddr(addr, len, af)
660 const char *addr; /* XXX should have been def'd as u_char! */
661 int len, af;
662{
663 const u_char *uaddr = (const u_char *)addr;
664 int n, size, i;
665 querybuf *buf;
666 register struct hostent *hp;
667 char qbuf[MAXDNAME+1], *qp;
668 extern struct hostent *_gethtbyaddr(), *_yp_gethtbyaddr();
669 char lookups[MAXDNSLUS];
670 struct hostent *res;
671
672 _THREAD_PRIVATE_MUTEX_LOCK(gethostnamadr);
673 if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
674 res = _gethtbyaddr(addr, len, af);
675 _THREAD_PRIVATE_MUTEX_UNLOCK(gethostnamadr);
676 return (res);
677 }
678
679 if (af == AF_INET6 && len == IN6ADDRSZ &&
680 (IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)uaddr) ||
681 IN6_IS_ADDR_SITELOCAL((struct in6_addr *)uaddr))) {
682 h_errno = HOST_NOT_FOUND;
683 return (NULL);
684 }
685 if (af == AF_INET6 && len == IN6ADDRSZ &&
686 (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)uaddr) ||
687 IN6_IS_ADDR_V4COMPAT((struct in6_addr *)uaddr))) {
688 /* Unmap. */
689 addr += IN6ADDRSZ - INADDRSZ;
690 uaddr += IN6ADDRSZ - INADDRSZ;
691 af = AF_INET;
692 len = INADDRSZ;
693 }
694 switch (af) {
695 case AF_INET:
696 size = INADDRSZ;
697 break;
698 case AF_INET6:
699 size = IN6ADDRSZ;
700 break;
701 default:
702 errno = EAFNOSUPPORT;
703 h_errno = NETDB_INTERNAL;
704 _THREAD_PRIVATE_MUTEX_UNLOCK(gethostnamadr);
705 return (NULL);
706 }
707 if (size != len) {
708 errno = EINVAL;
709 h_errno = NETDB_INTERNAL;
710 _THREAD_PRIVATE_MUTEX_UNLOCK(gethostnamadr);
711 return (NULL);
712 }
713 switch (af) {
714 case AF_INET:
715 (void) snprintf(qbuf, sizeof qbuf, "%u.%u.%u.%u.in-addr.arpa",
716 (uaddr[3] & 0xff), (uaddr[2] & 0xff),
717 (uaddr[1] & 0xff), (uaddr[0] & 0xff));
718 break;
719 case AF_INET6:
720 qp = qbuf;
721 for (n = IN6ADDRSZ - 1; n >= 0; n--) {
722 qp += sprintf(qp, "%x.%x.",
723 uaddr[n] & 0xf, (uaddr[n] >> 4) & 0xf);
724 }
725 break;
726 }
727
728 bcopy(_res.lookups, lookups, sizeof lookups);
729 if (lookups[0] == '\0')
730 strlcpy(lookups, "bf", sizeof lookups);
731
732 hp = (struct hostent *)NULL;
733 for (i = 0; i < MAXDNSLUS && hp == NULL && lookups[i]; i++) {
734 switch (lookups[i]) {
735#ifdef YP
736 case 'y':
737 /* YP only supports AF_INET. */
738 if (af == AF_INET)
739 hp = _yp_gethtbyaddr(addr);
740 break;
741#endif
742 case 'b':
743 if (af == AF_INET6)
744 strcpy(qp, "ip6.arpa");
745 buf = malloc(sizeof(*buf));
746 if (!buf)
747 break;
748 n = res_query(qbuf, C_IN, T_PTR, buf->buf,
749 sizeof(buf->buf));
750 if (n < 0 && af == AF_INET6) {
751 strcpy(qp, "ip6.int");
752 n = res_query(qbuf, C_IN, T_PTR,
753 buf->buf, sizeof(buf->buf));
754 }
755 if (n < 0) {
756 free(buf);
757#ifdef DEBUG
758 if (_res.options & RES_DEBUG)
759 printf("res_query failed\n");
760#endif
761 break;
762 }
763 if (!(hp = getanswer(buf, n, qbuf, T_PTR))) {
764 free(buf);
765 break;
766 }
767 free(buf);
768 hp->h_addrtype = af;
769 hp->h_length = len;
770 bcopy(addr, host_addr, len);
771 h_addr_ptrs[0] = (char *)host_addr;
772 h_addr_ptrs[1] = NULL;
773 if (af == AF_INET && (_res.options & RES_USE_INET6)) {
774 map_v4v6_address((char*)host_addr,
775 (char*)host_addr);
776 hp->h_addrtype = AF_INET6;
777 hp->h_length = IN6ADDRSZ;
778 }
779 h_errno = NETDB_SUCCESS;
780 break;
781 case 'f':
782 hp = _gethtbyaddr(addr, len, af);
783 break;
784 }
785 }
786 _THREAD_PRIVATE_MUTEX_UNLOCK(gethostnamadr);
787 /* XXX h_errno not correct in all cases... */
788 return (hp);
789}
790
791void
792_sethtent(f)
793 int f;
794{
795 if (hostf == NULL)
796 hostf = fopen(_PATH_HOSTS, "r" );
797 else
798 rewind(hostf);
799 stayopen = f;
800}
801
802void
803_endhtent()
804{
805 if (hostf && !stayopen) {
806 (void) fclose(hostf);
807 hostf = NULL;
808 }
809}
810
811struct hostent *
812_gethtent()
813{
814 char *p;
815 register char *cp, **q;
816 int af;
817 size_t len;
818
819 if (!hostf && !(hostf = fopen(_PATH_HOSTS, "r" ))) {
820 h_errno = NETDB_INTERNAL;
821 return (NULL);
822 }
823 again:
824 if ((p = fgetln(hostf, &len)) == NULL) {
825 h_errno = HOST_NOT_FOUND;
826 return (NULL);
827 }
828 if (p[len-1] == '\n')
829 len--;
830 if (len >= sizeof(hostbuf) || len == 0)
831 goto again;
832 p = memcpy(hostbuf, p, len);
833 hostbuf[len] = '\0';
834 if (*p == '#')
835 goto again;
836 if ((cp = strchr(p, '#')))
837 *cp = '\0';
838 if (!(cp = strpbrk(p, " \t")))
839 goto again;
840 *cp++ = '\0';
841 if (inet_pton(AF_INET6, p, host_addr) > 0) {
842 af = AF_INET6;
843 len = IN6ADDRSZ;
844 } else if (inet_pton(AF_INET, p, host_addr) > 0) {
845 if (_res.options & RES_USE_INET6) {
846 map_v4v6_address((char*)host_addr, (char*)host_addr);
847 af = AF_INET6;
848 len = IN6ADDRSZ;
849 } else {
850 af = AF_INET;
851 len = INADDRSZ;
852 }
853 } else {
854 goto again;
855 }
856 /* if this is not something we're looking for, skip it. */
857 if (host.h_addrtype != af)
858 goto again;
859 if (host.h_length != len)
860 goto again;
861 h_addr_ptrs[0] = (char *)host_addr;
862 h_addr_ptrs[1] = NULL;
863 host.h_addr_list = h_addr_ptrs;
864 host.h_length = len;
865 host.h_addrtype = af;
866 while (*cp == ' ' || *cp == '\t')
867 cp++;
868 host.h_name = cp;
869 q = host.h_aliases = host_aliases;
870 if ((cp = strpbrk(cp, " \t")))
871 *cp++ = '\0';
872 while (cp && *cp) {
873 if (*cp == ' ' || *cp == '\t') {
874 cp++;
875 continue;
876 }
877 if (q < &host_aliases[MAXALIASES - 1])
878 *q++ = cp;
879 if ((cp = strpbrk(cp, " \t")))
880 *cp++ = '\0';
881 }
882 *q = NULL;
883 if (_res.options & RES_USE_INET6) {
884 char *bp = hostbuf;
885 char *ep = hostbuf + sizeof hostbuf;
886
887 map_v4v6_hostent(&host, &bp, ep);
888 }
889 h_errno = NETDB_SUCCESS;
890 return (&host);
891}
892
893struct hostent *
894_gethtbyname(name)
895 const char *name;
896{
897 extern struct hostent *_gethtbyname2();
898 struct hostent *hp;
899
900 if (_res.options & RES_USE_INET6) {
901 hp = _gethtbyname2(name, AF_INET6);
902 if (hp)
903 return (hp);
904 }
905 return (_gethtbyname2(name, AF_INET));
906}
907
908struct hostent *
909_gethtbyname2(name, af)
910 const char *name;
911 int af;
912{
913 register struct hostent *p;
914 register char **cp;
915
916 _sethtent(0);
917 while ((p = _gethtent())) {
918 if (p->h_addrtype != af)
919 continue;
920 if (strcasecmp(p->h_name, name) == 0)
921 break;
922 for (cp = p->h_aliases; *cp != 0; cp++)
923 if (strcasecmp(*cp, name) == 0)
924 goto found;
925 }
926 found:
927 _endhtent();
928 return (p);
929}
930
931struct hostent *
932_gethtbyaddr(addr, len, af)
933 const char *addr;
934 int len, af;
935{
936 register struct hostent *p;
937
938 host.h_length = len;
939 host.h_addrtype = af;
940
941 _sethtent(0);
942 while ((p = _gethtent()))
943 if (p->h_addrtype == af && !bcmp(p->h_addr, addr, len))
944 break;
945 _endhtent();
946 return (p);
947}
948
949#ifdef YP
950struct hostent *
951_yphostent(line)
952 char *line;
953{
954 static struct in_addr host_addrs[MAXADDRS];
955 char *p = line;
956 char *cp, **q;
957 char **hap;
958 struct in_addr *buf;
959 int more;
960
961 host.h_name = NULL;
962 host.h_addr_list = h_addr_ptrs;
963 host.h_length = INADDRSZ;
964 host.h_addrtype = AF_INET;
965 hap = h_addr_ptrs;
966 buf = host_addrs;
967 q = host.h_aliases = host_aliases;
968
969nextline:
970 /* check for host_addrs overflow */
971 if (buf >= &host_addrs[sizeof(host_addrs) / sizeof(host_addrs[0])])
972 goto done;
973
974 more = 0;
975 cp = strpbrk(p, " \t");
976 if (cp == NULL)
977 goto done;
978 *cp++ = '\0';
979
980 *hap++ = (char *)buf;
981 (void) inet_aton(p, buf++);
982
983 while (*cp == ' ' || *cp == '\t')
984 cp++;
985 p = cp;
986 cp = strpbrk(p, " \t\n");
987 if (cp != NULL) {
988 if (*cp == '\n')
989 more = 1;
990 *cp++ = '\0';
991 }
992 if (!host.h_name)
993 host.h_name = p;
994 else if (strcmp(host.h_name, p)==0)
995 ;
996 else if (q < &host_aliases[MAXALIASES - 1])
997 *q++ = p;
998 p = cp;
999 if (more)
1000 goto nextline;
1001
1002 while (cp && *cp) {
1003 if (*cp == ' ' || *cp == '\t') {
1004 cp++;
1005 continue;
1006 }
1007 if (*cp == '\n') {
1008 cp++;
1009 goto nextline;
1010 }
1011 if (q < &host_aliases[MAXALIASES - 1])
1012 *q++ = cp;
1013 cp = strpbrk(cp, " \t");
1014 if (cp != NULL)
1015 *cp++ = '\0';
1016 }
1017done:
1018 if (host.h_name == NULL)
1019 return (NULL);
1020 *q = NULL;
1021 *hap = NULL;
1022 return (&host);
1023}
1024
1025struct hostent *
1026_yp_gethtbyaddr(addr)
1027 const char *addr;
1028{
1029 struct hostent *hp = (struct hostent *)NULL;
1030 static char *__ypcurrent;
1031 int __ypcurrentlen, r;
1032 char name[sizeof("xxx.xxx.xxx.xxx")];
1033
1034 if (!__ypdomain) {
1035 if (_yp_check(&__ypdomain) == 0)
1036 return (hp);
1037 }
1038 snprintf(name, sizeof name, "%u.%u.%u.%u",
1039 ((unsigned)addr[0] & 0xff), ((unsigned)addr[1] & 0xff),
1040 ((unsigned)addr[2] & 0xff), ((unsigned)addr[3] & 0xff));
1041 if (__ypcurrent)
1042 free(__ypcurrent);
1043 __ypcurrent = NULL;
1044 r = yp_match(__ypdomain, "hosts.byaddr", name,
1045 strlen(name), &__ypcurrent, &__ypcurrentlen);
1046 if (r==0)
1047 hp = _yphostent(__ypcurrent);
1048 if (hp==NULL)
1049 h_errno = HOST_NOT_FOUND;
1050 return (hp);
1051}
1052
1053struct hostent *
1054_yp_gethtbyname(name)
1055 const char *name;
1056{
1057 struct hostent *hp = (struct hostent *)NULL;
1058 static char *__ypcurrent;
1059 int __ypcurrentlen, r;
1060
1061 if (strlen(name) >= MAXHOSTNAMELEN)
1062 return (NULL);
1063 if (!__ypdomain) {
1064 if (_yp_check(&__ypdomain) == 0)
1065 return (hp);
1066 }
1067 if (__ypcurrent)
1068 free(__ypcurrent);
1069 __ypcurrent = NULL;
1070 r = yp_match(__ypdomain, "hosts.byname", name,
1071 strlen(name), &__ypcurrent, &__ypcurrentlen);
1072 if (r == 0)
1073 hp = _yphostent(__ypcurrent);
1074 if (hp == NULL)
1075 h_errno = HOST_NOT_FOUND;
1076 return (hp);
1077}
1078#endif
1079
1080static void
1081map_v4v6_address(src, dst)
1082 const char *src;
1083 char *dst;
1084{
1085 u_char *p = (u_char *)dst;
1086 char tmp[INADDRSZ];
1087 int i;
1088
1089 /* Stash a temporary copy so our caller can update in place. */
1090 bcopy(src, tmp, INADDRSZ);
1091 /* Mark this ipv6 addr as a mapped ipv4. */
1092 for (i = 0; i < 10; i++)
1093 *p++ = 0x00;
1094 *p++ = 0xff;
1095 *p++ = 0xff;
1096 /* Retrieve the saved copy and we're done. */
1097 bcopy(tmp, (void*)p, INADDRSZ);
1098}
1099
1100static void
1101map_v4v6_hostent(hp, bpp, ep)
1102 struct hostent *hp;
1103 char **bpp;
1104 char *ep;
1105{
1106 char **ap;
1107
1108 if (hp->h_addrtype != AF_INET || hp->h_length != INADDRSZ)
1109 return;
1110 hp->h_addrtype = AF_INET6;
1111 hp->h_length = IN6ADDRSZ;
1112 for (ap = hp->h_addr_list; *ap; ap++) {
1113 int i = sizeof(align) - ((u_long)*bpp % sizeof(align));
1114
1115 if (ep - *bpp < (i + IN6ADDRSZ)) {
1116 /* Out of memory. Truncate address list here. XXX */
1117 *ap = NULL;
1118 return;
1119 }
1120 *bpp += i;
1121 map_v4v6_address(*ap, *bpp);
1122 *ap = *bpp;
1123 *bpp += IN6ADDRSZ;
1124 }
1125}
1126
1127struct hostent *
1128gethostent()
1129{
1130 return (_gethtent());
1131}
1132
1133#ifdef RESOLVSORT
1134static void
1135addrsort(ap, num)
1136 char **ap;
1137 int num;
1138{
1139 int i, j;
1140 char **p;
1141 short aval[MAXADDRS];
1142 int needsort = 0;
1143
1144 p = ap;
1145 for (i = 0; i < num; i++, p++) {
1146 for (j = 0 ; (unsigned)j < _res.nsort; j++)
1147 if (_res.sort_list[j].addr.s_addr ==
1148 (((struct in_addr *)(*p))->s_addr & _res.sort_list[j].mask))
1149 break;
1150 aval[i] = j;
1151 if (needsort == 0 && i > 0 && j < aval[i-1])
1152 needsort = i;
1153 }
1154 if (!needsort)
1155 return;
1156
1157 while (needsort < num) {
1158 for (j = needsort - 1; j >= 0; j--) {
1159 if (aval[j] > aval[j+1]) {
1160 char *hp;
1161
1162 i = aval[j];
1163 aval[j] = aval[j+1];
1164 aval[j+1] = i;
1165
1166 hp = ap[j];
1167 ap[j] = ap[j+1];
1168 ap[j+1] = hp;
1169 } else
1170 break;
1171 }
1172 needsort++;
1173 }
1174}
1175#endif
diff --git a/src/lib/libc/net/getifaddrs.3 b/src/lib/libc/net/getifaddrs.3
new file mode 100644
index 0000000000..2743bf6fc2
--- /dev/null
+++ b/src/lib/libc/net/getifaddrs.3
@@ -0,0 +1,159 @@
1.\" $OpenBSD: getifaddrs.3,v 1.8 2002/01/02 06:08:55 nordin Exp $
2.\" BSDI getifaddrs.3,v 2.5 2000/02/23 14:51:59 dab Exp
3.\"
4.\" Copyright (c) 1995, 1999
5.\" Berkeley Software Design, Inc. All rights reserved.
6.\"
7.\" Redistribution and use in source and binary forms, with or without
8.\" modification, are permitted provided that the following conditions
9.\" are met:
10.\" 1. Redistributions of source code must retain the above copyright
11.\" notice, this list of conditions and the following disclaimer.
12.\"
13.\" THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
14.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16.\" ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
17.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23.\" SUCH DAMAGE.
24.Dd "October 12, 1995"
25.Dt GETIFADDRS 3
26.Os
27.Sh NAME
28.Nm getifaddrs
29.Nd get interface addresses
30.Sh SYNOPSIS
31.Fd #include <sys/types.h>
32.Fd #include <sys/socket.h>
33.Fd #include <ifaddrs.h>
34.Ft int
35.Fn getifaddrs "struct ifaddrs **ifap"
36.Ft void
37.Fn freeifaddrs "struct ifaddrs *ifap"
38.Sh DESCRIPTION
39The
40.Fn getifaddrs
41function stores a reference to a linked list of the network interfaces
42on the local machine in the memory referenced by
43.Fa ifap .
44The list consists of
45.Nm ifaddrs
46structures, as defined in the include file
47.Aq Pa ifaddrs.h .
48The
49.Nm ifaddrs
50structure contains at least the following entries:
51.Bd -literal
52 struct ifaddrs *ifa_next; /* Pointer to next struct */
53 char *ifa_name; /* Interface name */
54 u_int ifa_flags; /* Interface flags */
55 struct sockaddr *ifa_addr; /* Interface address */
56 struct sockaddr *ifa_netmask; /* Interface netmask */
57 struct sockaddr *ifa_broadaddr; /* Interface broadcast address */
58 struct sockaddr *ifa_dstaddr; /* P2P interface destination */
59 void *ifa_data; /* Address specific data */
60.Ed
61.Pp
62.Bl -tag -width Ds
63.It Fa ifa_next
64Contains a pointer to the next structure on the list.
65This field is set to
66.Dv NULL
67in last structure on the list.
68.It Fa ifa_name
69Contains the interface name.
70.It Fa ifa_flags
71Contains the interface flags, as set by
72.Xr ifconfig 8 .
73.It Fa ifa_addr
74References either the address of the interface or the link level
75address of the interface, if one exists, otherwise it is
76.Dv NULL .
77(The
78.Fa sa_family
79field of the
80.Fa ifa_addr
81field should be consulted to determine the format of the
82.Fa ifa_addr
83address.)
84.It Fa ifa_netmask
85References the netmask associated with
86.Fa ifa_addr ,
87if one is set, otherwise it is
88.Dv NULL .
89.It Fa ifa_broadaddr
90This field, which should only be referenced for non-P2P interfaces,
91references the broadcast address associated with
92.Fa ifa_addr ,
93if one exists, otherwise it is
94.Dv NULL .
95.It Fa ifa_dstaddr
96References the destination address on a P2P interface,
97if one exists, otherwise it is
98.Dv NULL .
99.It Fa ifa_data
100References address family specific data.
101For
102.Dv AF_LINK
103addresses it contains a pointer to the
104.Li struct if_data
105(as defined in include file
106.Aq Pa net/if.h )
107which contains various interface attributes and statistics.
108For all other address families, it contains a pointer to the
109.Li struct ifa_data
110(as defined in include file
111.Aq Pa net/if.h )
112which contains per-address interface statistics.
113.El
114.Pp
115The data returned by
116.Fn getifaddrs
117is dynamically allocated and should be freed using
118.Fn freeifaddrs
119when no longer needed.
120.Sh RETURN VALUES
121Upon successful completion, a value of 0 is returned.
122Otherwise, a value of \-1 is returned and
123.Va errno
124is set to indicate the error.
125.Sh ERRORS
126The
127.Fn getifaddrs
128may fail and set
129.Va errno
130for any of the errors specified for the library routines
131.Xr ioctl 2 ,
132.Xr socket 2 ,
133.Xr malloc 3 ,
134or
135.Xr sysctl 3 .
136.Sh BUGS
137If both
138.Aq Pa net/if.h
139and
140.Aq Pa ifaddrs.h
141are being included,
142.Aq Pa net/if.h
143.Em must
144be included before
145.Aq Pa ifaddrs.h .
146.Sh SEE ALSO
147.Xr ioctl 2 ,
148.Xr socket 2 ,
149.Xr sysctl 3 ,
150.Xr networking 4 ,
151.Xr ifconfig 8
152.Sh HISTORY
153The
154.Fn getifaddrs
155function first appeared in BSDI BSD/OS.
156The function is supplied on
157.Ox
158since
159.Ox 2.7 .
diff --git a/src/lib/libc/net/getifaddrs.c b/src/lib/libc/net/getifaddrs.c
new file mode 100644
index 0000000000..0db89f6c19
--- /dev/null
+++ b/src/lib/libc/net/getifaddrs.c
@@ -0,0 +1,277 @@
1/* $OpenBSD: getifaddrs.c,v 1.9 2002/08/09 06:12:25 itojun Exp $ */
2
3/*
4 * Copyright (c) 1995, 1999
5 * Berkeley Software Design, Inc. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
24 *
25 * BSDI getifaddrs.c,v 2.12 2000/02/23 14:51:59 dab Exp
26 */
27
28#include <sys/types.h>
29#include <sys/ioctl.h>
30#include <sys/socket.h>
31#include <net/if.h>
32#include <sys/param.h>
33#include <net/route.h>
34#include <sys/sysctl.h>
35#include <net/if_dl.h>
36
37#include <errno.h>
38#include <ifaddrs.h>
39#include <stdlib.h>
40#include <string.h>
41#include <unistd.h>
42
43#define SALIGN (sizeof(long) - 1)
44#define SA_RLEN(sa) ((sa)->sa_len ? (((sa)->sa_len + SALIGN) & ~SALIGN) : (SALIGN + 1))
45
46int
47getifaddrs(struct ifaddrs **pif)
48{
49 int icnt = 1;
50 int dcnt = 0;
51 int ncnt = 0;
52 int mib[6];
53 size_t needed;
54 char *buf;
55 char *next;
56 struct ifaddrs *cif = 0;
57 char *p, *p0;
58 struct rt_msghdr *rtm;
59 struct if_msghdr *ifm;
60 struct ifa_msghdr *ifam;
61 struct sockaddr_dl *dl;
62 struct sockaddr *sa;
63 u_short index = 0;
64 size_t len, alen;
65 struct ifaddrs *ifa, *ift;
66 int i;
67 char *data;
68 char *names;
69
70 mib[0] = CTL_NET;
71 mib[1] = PF_ROUTE;
72 mib[2] = 0; /* protocol */
73 mib[3] = 0; /* wildcard address family */
74 mib[4] = NET_RT_IFLIST;
75 mib[5] = 0; /* no flags */
76 if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
77 return (-1);
78 if ((buf = malloc(needed)) == NULL)
79 return (-1);
80 if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
81 free(buf);
82 return (-1);
83 }
84
85 for (next = buf; next < buf + needed; next += rtm->rtm_msglen) {
86 rtm = (struct rt_msghdr *)next;
87 if (rtm->rtm_version != RTM_VERSION)
88 continue;
89 switch (rtm->rtm_type) {
90 case RTM_IFINFO:
91 ifm = (struct if_msghdr *)rtm;
92 if (ifm->ifm_addrs & RTA_IFP) {
93 index = ifm->ifm_index;
94 ++icnt;
95 dl = (struct sockaddr_dl *)(ifm + 1);
96 dcnt += SA_RLEN((struct sockaddr *)dl) +
97 ALIGNBYTES;
98 dcnt += sizeof(ifm->ifm_data);
99 ncnt += dl->sdl_nlen + 1;
100 } else
101 index = 0;
102 break;
103
104 case RTM_NEWADDR:
105 ifam = (struct ifa_msghdr *)rtm;
106 if (index && ifam->ifam_index != index)
107 abort(); /* XXX abort illegal in library */
108
109#define RTA_MASKS (RTA_NETMASK | RTA_IFA | RTA_BRD)
110 if (index == 0 || (ifam->ifam_addrs & RTA_MASKS) == 0)
111 break;
112 p = (char *)(ifam + 1);
113 ++icnt;
114 /* Scan to look for length of address */
115 alen = 0;
116 for (p0 = p, i = 0; i < RTAX_MAX; i++) {
117 if ((RTA_MASKS & ifam->ifam_addrs & (1 << i))
118 == 0)
119 continue;
120 sa = (struct sockaddr *)p;
121 len = SA_RLEN(sa);
122 if (i == RTAX_IFA) {
123 alen = len;
124 break;
125 }
126 p += len;
127 }
128 for (p = p0, i = 0; i < RTAX_MAX; i++) {
129 if ((RTA_MASKS & ifam->ifam_addrs & (1 << i))
130 == 0)
131 continue;
132 sa = (struct sockaddr *)p;
133 len = SA_RLEN(sa);
134 if (i == RTAX_NETMASK && sa->sa_len == 0)
135 dcnt += alen;
136 else
137 dcnt += len;
138 p += len;
139 }
140 break;
141 }
142 }
143
144 if (icnt + dcnt + ncnt == 1) {
145 *pif = NULL;
146 free(buf);
147 return (0);
148 }
149 data = malloc(sizeof(struct ifaddrs) * icnt + dcnt + ncnt);
150 if (data == NULL) {
151 free(buf);
152 return(-1);
153 }
154
155 ifa = (struct ifaddrs *)data;
156 data += sizeof(struct ifaddrs) * icnt;
157 names = data + dcnt;
158
159 memset(ifa, 0, sizeof(struct ifaddrs) * icnt);
160 ift = ifa;
161
162 index = 0;
163 for (next = buf; next < buf + needed; next += rtm->rtm_msglen) {
164 rtm = (struct rt_msghdr *)next;
165 if (rtm->rtm_version != RTM_VERSION)
166 continue;
167 switch (rtm->rtm_type) {
168 case RTM_IFINFO:
169 ifm = (struct if_msghdr *)rtm;
170 if (ifm->ifm_addrs & RTA_IFP) {
171 index = ifm->ifm_index;
172 dl = (struct sockaddr_dl *)(ifm + 1);
173
174 cif = ift;
175 ift->ifa_name = names;
176 ift->ifa_flags = (int)ifm->ifm_flags;
177 memcpy(names, dl->sdl_data, dl->sdl_nlen);
178 names[dl->sdl_nlen] = 0;
179 names += dl->sdl_nlen + 1;
180
181 ift->ifa_addr = (struct sockaddr *)data;
182 memcpy(data, dl,
183 ((struct sockaddr *)dl)->sa_len);
184 data += SA_RLEN((struct sockaddr *)dl);
185
186 /* ifm_data needs to be aligned */
187 ift->ifa_data = data = (void *)ALIGN(data);
188 memcpy(data, &ifm->ifm_data, sizeof(ifm->ifm_data));
189 data += sizeof(ifm->ifm_data);
190
191 ift = (ift->ifa_next = ift + 1);
192 } else
193 index = 0;
194 break;
195
196 case RTM_NEWADDR:
197 ifam = (struct ifa_msghdr *)rtm;
198 if (index && ifam->ifam_index != index)
199 abort(); /* XXX abort illegal in library */
200
201 if (index == 0 || (ifam->ifam_addrs & RTA_MASKS) == 0)
202 break;
203 ift->ifa_name = cif->ifa_name;
204 ift->ifa_flags = cif->ifa_flags;
205 ift->ifa_data = NULL;
206 p = (char *)(ifam + 1);
207 /* Scan to look for length of address */
208 alen = 0;
209 for (p0 = p, i = 0; i < RTAX_MAX; i++) {
210 if ((RTA_MASKS & ifam->ifam_addrs & (1 << i))
211 == 0)
212 continue;
213 sa = (struct sockaddr *)p;
214 len = SA_RLEN(sa);
215 if (i == RTAX_IFA) {
216 alen = len;
217 break;
218 }
219 p += len;
220 }
221 for (p = p0, i = 0; i < RTAX_MAX; i++) {
222 if ((RTA_MASKS & ifam->ifam_addrs & (1 << i))
223 == 0)
224 continue;
225 sa = (struct sockaddr *)p;
226 len = SA_RLEN(sa);
227 switch (i) {
228 case RTAX_IFA:
229 ift->ifa_addr = (struct sockaddr *)data;
230 memcpy(data, p, len);
231 data += len;
232 break;
233
234 case RTAX_NETMASK:
235 ift->ifa_netmask =
236 (struct sockaddr *)data;
237 if (sa->sa_len == 0) {
238 memset(data, 0, alen);
239 data += alen;
240 break;
241 }
242 memcpy(data, p, len);
243 data += len;
244 break;
245
246 case RTAX_BRD:
247 ift->ifa_broadaddr =
248 (struct sockaddr *)data;
249 memcpy(data, p, len);
250 data += len;
251 break;
252 }
253 p += len;
254 }
255
256
257 ift = (ift->ifa_next = ift + 1);
258 break;
259 }
260 }
261
262 free(buf);
263 if (--ift >= ifa) {
264 ift->ifa_next = NULL;
265 *pif = ifa;
266 } else {
267 *pif = NULL;
268 free(ifa);
269 }
270 return (0);
271}
272
273void
274freeifaddrs(struct ifaddrs *ifp)
275{
276 free(ifp);
277}
diff --git a/src/lib/libc/net/getnameinfo.3 b/src/lib/libc/net/getnameinfo.3
new file mode 100644
index 0000000000..76c6449906
--- /dev/null
+++ b/src/lib/libc/net/getnameinfo.3
@@ -0,0 +1,297 @@
1.\" $OpenBSD: getnameinfo.3,v 1.17 2001/11/15 06:53:09 itojun Exp $
2.\" $KAME: getnameinfo.3,v 1.20 2001/01/05 13:37:37 itojun Exp $
3.\"
4.\" Copyright (c) 1983, 1987, 1991, 1993
5.\" The Regents of the University of California. All rights reserved.
6.\"
7.\" Redistribution and use in source and binary forms, with or without
8.\" modification, are permitted provided that the following conditions
9.\" are met:
10.\" 1. Redistributions of source code must retain the above copyright
11.\" notice, this list of conditions and the following disclaimer.
12.\" 2. Redistributions in binary form must reproduce the above copyright
13.\" notice, this list of conditions and the following disclaimer in the
14.\" documentation and/or other materials provided with the distribution.
15.\" 3. All advertising materials mentioning features or use of this software
16.\" must display the following acknowledgement:
17.\" This product includes software developed by the University of
18.\" California, Berkeley and its contributors.
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.\" From: @(#)gethostbyname.3 8.4 (Berkeley) 5/25/95
36.\"
37.Dd May 25, 1995
38.Dt GETNAMEINFO 3
39.Os
40.\"
41.Sh NAME
42.Nm getnameinfo
43.Nd address-to-nodename translation in protocol-independent manner
44.\"
45.Sh SYNOPSIS
46.Fd #include <sys/types.h>
47.Fd #include <sys/socket.h>
48.Fd #include <netdb.h>
49.Ft int
50.Fn getnameinfo "const struct sockaddr *sa" "socklen_t salen" \
51"char *host" "size_t hostlen" "char *serv" "size_t servlen" "int flags"
52.\"
53.Sh DESCRIPTION
54The
55.Fn getnameinfo
56function is defined for protocol-independent address-to-nodename translation.
57Its functionality is a reverse conversion of
58.Xr getaddrinfo 3 ,
59and implements similar functionality with
60.Xr gethostbyaddr 3
61and
62.Xr getservbyport 3
63in more sophisticated manner.
64.Pp
65This function looks up an IP address and port number provided by the
66caller in the DNS and system-specific database, and returns text
67strings for both in buffers provided by the caller.
68The function indicates successful completion by a zero return value;
69a non-zero return value indicates failure.
70.Pp
71The first argument,
72.Fa sa ,
73points to either a
74.Li sockaddr_in
75structure (for IPv4) or a
76.Li sockaddr_in6
77structure (for IPv6) that holds the IP address and port number.
78The
79.Fa salen
80argument gives the length of the
81.Li sockaddr_in
82or
83.Li sockaddr_in6
84structure.
85.Pp
86The function returns the nodename associated with the IP address in
87the buffer pointed to by the
88.Fa host
89argument.
90The caller provides the size of this buffer via the
91.Fa hostlen
92argument.
93The service name associated with the port number is returned in the buffer
94pointed to by
95.Fa serv ,
96and the
97.Fa servlen
98argument gives the length of this buffer.
99The caller specifies not to return either string by providing a zero
100value for the
101.Fa hostlen
102or
103.Fa servlen
104arguments.
105Otherwise, the caller must provide buffers large enough to hold the
106nodename and the service name, including the terminating null characters.
107.Pp
108Unfortunately most systems do not provide constants that specify the
109maximum size of either a fully-qualified domain name or a service name.
110Therefore to aid the application in allocating buffers for these two
111returned strings the following constants are defined in
112.Aq Pa netdb.h :
113.Bd -literal -offset
114#define NI_MAXHOST MAXHOSTNAMELEN
115#define NI_MAXSERV 32
116.Ed
117.Pp
118The first value is actually defined as the constant
119.Dv MAXDNAME
120in recent versions of BIND's
121.Aq Pa arpa/nameser.h
122header (older versions of BIND define this constant to be 256)
123and the second is a guess based on the services listed in the current
124Assigned Numbers RFC.
125.Pp
126The final argument is a
127.Fa flag
128that changes the default actions of this function.
129By default the fully-qualified domain name (FQDN) for the host is
130looked up in the DNS and returned.
131If the flag bit
132.Dv NI_NOFQDN
133is set, only the nodename portion of the FQDN is returned for local hosts.
134.Pp
135If the
136.Fa flag
137bit
138.Dv NI_NUMERICHOST
139is set, or if the host's name cannot be located in the DNS,
140the numeric form of the host's address is returned instead of its name
141.Po
142e.g., by calling
143.Fn inet_ntop
144instead of
145.Fn gethostbyaddr
146.Pc .
147If the
148.Fa flag
149bit
150.Dv NI_NAMEREQD
151is set, an error is returned if the host's name cannot be located in the DNS.
152.Pp
153If the flag bit
154.Dv NI_NUMERICSERV
155is set, the numeric form of the service address is returned
156.Pq e.g., its port number
157instead of its name.
158The two
159.Dv NI_NUMERICxxx
160flags are required to support the
161.Fl n
162flag that many commands provide.
163.Pp
164A fifth flag bit,
165.Dv NI_DGRAM ,
166specifies that the service is a datagram service, and causes
167.Fn getservbyport
168to be called with a second argument of
169.Qq udp
170instead of its default of
171.Qq tcp .
172This is required for the few ports (512-514)
173that have different services for UDP and TCP.
174.Pp
175These
176.Dv NI_xxx
177flags are defined in
178.Aq Pa netdb.h .
179.\"
180.Ss Extension for scoped IPv6 address
181The implementation allows experimental numeric IPv6 address notation with
182scope identifier.
183IPv6 link-local address will appear as string like
184.Dq Li fe80::1%ne0 .
185Refer to
186.Xr getaddrinfo 3
187for the notation.
188.\"
189.Sh EXAMPLES
190The following code tries to get numeric hostname, and service name,
191for given socket address.
192Observe that there is no hardcoded reference to particular address family.
193.Bd -literal -offset indent
194struct sockaddr *sa; /* input */
195char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
196
197if (getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf), sbuf,
198 sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV)) {
199 errx(1, "could not get numeric hostname");
200 /*NOTREACHED*/
201}
202printf("host=%s, serv=%s\en", hbuf, sbuf);
203.Ed
204.Pp
205The following version checks if the socket address has reverse address mapping.
206.Bd -literal -offset indent
207struct sockaddr *sa; /* input */
208char hbuf[NI_MAXHOST];
209
210if (getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf), NULL, 0,
211 NI_NAMEREQD)) {
212 errx(1, "could not resolve hostname");
213 /*NOTREACHED*/
214}
215printf("host=%s\en", hbuf);
216.Ed
217.\"
218.Sh DIAGNOSTICS
219The function indicates successful completion by a zero return value;
220a non-zero return value indicates failure.
221Error codes are as below:
222.Bl -tag -width Er
223.It Dv EAI_AGAIN
224The name could not be resolved at this time.
225Future attempts may succeed.
226.It Dv EAI_BADFLAGS
227The flags had an invalid value.
228.It Dv EAI_FAIL
229A non-recoverable error occurred.
230.It Dv EAI_FAMILY
231The address family was not recognized or the address length was invalid
232for the specified family.
233.It Dv EAI_MEMORY
234There was a memory allocation failure.
235.It Dv EAI_NONAME
236The name does not resolve for the supplied parameters.
237.Dv NI_NAMEREQD
238is set and the host's name cannot be located,
239or both nodename and servname were null.
240.It Dv EAI_SYSTEM
241A system error occurred.
242The error code can be found in errno.
243.El
244.\"
245.Sh SEE ALSO
246.Xr getaddrinfo 3 ,
247.Xr gethostbyaddr 3 ,
248.Xr getservbyport 3 ,
249.Xr hosts 5 ,
250.Xr resolv.conf 5 ,
251.Xr services 5 ,
252.Xr hostname 7 ,
253.Xr named 8
254.Rs
255.%A R. Gilligan
256.%A S. Thomson
257.%A J. Bound
258.%A W. Stevens
259.%T Basic Socket Interface Extensions for IPv6
260.%R RFC2553
261.%D March 1999
262.Re
263.Rs
264.%A Tatsuya Jinmei
265.%A Atsushi Onoe
266.%T "An Extension of Format for IPv6 Scoped Addresses"
267.%R internet draft
268.%N draft-ietf-ipngwg-scopedaddr-format-02.txt
269.%O work in progress material
270.Re
271.Rs
272.%A Craig Metz
273.%T Protocol Independence Using the Sockets API
274.%B "Proceedings of the freenix track: 2000 USENIX annual technical conference"
275.%D June 2000
276.Re
277.\"
278.Sh HISTORY
279The implementation first appeared in WIDE Hydrangea IPv6 protocol stack kit.
280.\"
281.Sh STANDARDS
282The
283.Fn getaddrinfo
284function is defined IEEE POSIX 1003.1g draft specification,
285and documented in
286.Dq Basic Socket Interface Extensions for IPv6
287.Pq RFC2553 .
288.\"
289.Sh BUGS
290The current implementation is not thread-safe.
291.Pp
292The text was shamelessly copied from RFC2553.
293.Pp
294.Ox
295intentionally uses different
296.Dv NI_MAXHOST
297value from what RFC2553 suggests, to avoid buffer length handling mistakes.
diff --git a/src/lib/libc/net/getnameinfo.c b/src/lib/libc/net/getnameinfo.c
new file mode 100644
index 0000000000..2311eba7a0
--- /dev/null
+++ b/src/lib/libc/net/getnameinfo.c
@@ -0,0 +1,361 @@
1/* $OpenBSD: getnameinfo.c,v 1.25 2002/06/27 09:24:28 itojun Exp $ */
2/* $KAME: getnameinfo.c,v 1.45 2000/09/25 22:43:56 itojun Exp $ */
3
4/*
5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the project nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33/*
34 * Issues to be discussed:
35 * - Thread safe-ness must be checked
36 * - RFC2553 says that we should raise error on short buffer. X/Open says
37 * we need to truncate the result. We obey RFC2553 (and X/Open should be
38 * modified). ipngwg rough consensus seems to follow RFC2553.
39 * - What is "local" in NI_FQDN?
40 * - NI_NAMEREQD and NI_NUMERICHOST conflict with each other.
41 * - (KAME extension) always attach textual scopeid (fe80::1%lo0), if
42 * sin6_scope_id is filled - standardization status?
43 * XXX breaks backward compat for code that expects no scopeid.
44 * beware on merge.
45 */
46
47#ifndef INET6
48#define INET6
49#endif
50
51#include <sys/types.h>
52#include <sys/socket.h>
53#include <net/if.h>
54#include <netinet/in.h>
55#include <arpa/inet.h>
56#include <arpa/nameser.h>
57#include <netdb.h>
58#include <resolv.h>
59#include <string.h>
60#include <stddef.h>
61
62static const struct afd {
63 int a_af;
64 int a_addrlen;
65 int a_socklen;
66 int a_off;
67} afdl [] = {
68#ifdef INET6
69 {PF_INET6, sizeof(struct in6_addr), sizeof(struct sockaddr_in6),
70 offsetof(struct sockaddr_in6, sin6_addr)},
71#endif
72 {PF_INET, sizeof(struct in_addr), sizeof(struct sockaddr_in),
73 offsetof(struct sockaddr_in, sin_addr)},
74 {0, 0, 0},
75};
76
77struct sockinet {
78 u_char si_len;
79 u_char si_family;
80 u_short si_port;
81};
82
83#ifdef INET6
84static int ip6_parsenumeric(const struct sockaddr *, const char *, char *,
85 size_t, int);
86static int ip6_sa2str(const struct sockaddr_in6 *, char *, size_t, int);
87#endif
88
89int
90getnameinfo(sa, salen, host, hostlen, serv, servlen, flags)
91 const struct sockaddr *sa;
92 socklen_t salen;
93 char *host;
94 size_t hostlen;
95 char *serv;
96 size_t servlen;
97 int flags;
98{
99 const struct afd *afd;
100 struct servent *sp;
101 struct hostent *hp;
102 u_short port;
103 int family, i;
104 const char *addr;
105 u_int32_t v4a;
106 int h_error;
107 char numserv[512];
108 char numaddr[512];
109
110 if (sa == NULL)
111 return EAI_FAIL;
112
113 if (sa->sa_len != salen)
114 return EAI_FAIL;
115
116 family = sa->sa_family;
117 for (i = 0; afdl[i].a_af; i++)
118 if (afdl[i].a_af == family) {
119 afd = &afdl[i];
120 goto found;
121 }
122 return EAI_FAMILY;
123
124 found:
125 if (salen != afd->a_socklen)
126 return EAI_FAIL;
127
128 /* network byte order */
129 port = ((const struct sockinet *)sa)->si_port;
130 addr = (const char *)sa + afd->a_off;
131
132 if (serv == NULL || servlen == 0) {
133 /*
134 * do nothing in this case.
135 * in case you are wondering if "&&" is more correct than
136 * "||" here: rfc2553bis-03 says that serv == NULL OR
137 * servlen == 0 means that the caller does not want the result.
138 */
139 } else {
140 if (flags & NI_NUMERICSERV)
141 sp = NULL;
142 else {
143 sp = getservbyport(port,
144 (flags & NI_DGRAM) ? "udp" : "tcp");
145 }
146 if (sp) {
147 if (strlen(sp->s_name) + 1 > servlen)
148 return EAI_MEMORY;
149 strlcpy(serv, sp->s_name, servlen);
150 } else {
151 snprintf(numserv, sizeof(numserv), "%u", ntohs(port));
152 if (strlen(numserv) + 1 > servlen)
153 return EAI_MEMORY;
154 strlcpy(serv, numserv, servlen);
155 }
156 }
157
158 switch (sa->sa_family) {
159 case AF_INET:
160 v4a = (u_int32_t)
161 ntohl(((const struct sockaddr_in *)sa)->sin_addr.s_addr);
162 if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))
163 flags |= NI_NUMERICHOST;
164 v4a >>= IN_CLASSA_NSHIFT;
165 if (v4a == 0)
166 flags |= NI_NUMERICHOST;
167 break;
168#ifdef INET6
169 case AF_INET6:
170 {
171 const struct sockaddr_in6 *sin6;
172 sin6 = (const struct sockaddr_in6 *)sa;
173 switch (sin6->sin6_addr.s6_addr[0]) {
174 case 0x00:
175 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr))
176 ;
177 else if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr))
178 ;
179 else
180 flags |= NI_NUMERICHOST;
181 break;
182 default:
183 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
184 flags |= NI_NUMERICHOST;
185 }
186 else if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
187 flags |= NI_NUMERICHOST;
188 break;
189 }
190 }
191 break;
192#endif
193 }
194 if (host == NULL || hostlen == 0) {
195 /*
196 * do nothing in this case.
197 * in case you are wondering if "&&" is more correct than
198 * "||" here: rfc2553bis-03 says that host == NULL or
199 * hostlen == 0 means that the caller does not want the result.
200 */
201 } else if (flags & NI_NUMERICHOST) {
202 int numaddrlen;
203
204 /* NUMERICHOST and NAMEREQD conflicts with each other */
205 if (flags & NI_NAMEREQD)
206 return EAI_NONAME;
207
208 switch(afd->a_af) {
209#ifdef INET6
210 case AF_INET6:
211 {
212 int error;
213
214 if ((error = ip6_parsenumeric(sa, addr, host,
215 hostlen, flags)) != 0)
216 return(error);
217 break;
218 }
219#endif
220 default:
221 if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr))
222 == NULL)
223 return EAI_SYSTEM;
224 numaddrlen = strlen(numaddr);
225 if (numaddrlen + 1 > hostlen) /* don't forget terminator */
226 return EAI_MEMORY;
227 strlcpy(host, numaddr, hostlen);
228 break;
229 }
230 } else {
231 hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af);
232 h_error = h_errno;
233
234 if (hp) {
235#if 0
236 /*
237 * commented out, since "for local host" is not
238 * implemented here - see RFC2553 p30
239 */
240 if (flags & NI_NOFQDN) {
241 char *p;
242 p = strchr(hp->h_name, '.');
243 if (p)
244 *p = '\0';
245 }
246#endif
247 if (strlen(hp->h_name) + 1 > hostlen) {
248 return EAI_MEMORY;
249 }
250 strlcpy(host, hp->h_name, hostlen);
251 } else {
252 if (flags & NI_NAMEREQD)
253 return EAI_NONAME;
254 switch(afd->a_af) {
255#ifdef INET6
256 case AF_INET6:
257 {
258 int error;
259
260 if ((error = ip6_parsenumeric(sa, addr, host,
261 hostlen,
262 flags)) != 0)
263 return(error);
264 break;
265 }
266#endif
267 default:
268 if (inet_ntop(afd->a_af, addr, host,
269 hostlen) == NULL)
270 return EAI_SYSTEM;
271 break;
272 }
273 }
274 }
275 return(0);
276}
277
278#ifdef INET6
279static int
280ip6_parsenumeric(sa, addr, host, hostlen, flags)
281 const struct sockaddr *sa;
282 const char *addr;
283 char *host;
284 size_t hostlen;
285 int flags;
286{
287 int numaddrlen;
288 char numaddr[512];
289
290 if (inet_ntop(AF_INET6, addr, numaddr, sizeof(numaddr)) == NULL)
291 return EAI_SYSTEM;
292
293 numaddrlen = strlen(numaddr);
294 if (numaddrlen + 1 > hostlen) /* don't forget terminator */
295 return EAI_MEMORY;
296 strlcpy(host, numaddr, hostlen);
297
298 if (((const struct sockaddr_in6 *)sa)->sin6_scope_id) {
299 char zonebuf[MAXHOSTNAMELEN];
300 int zonelen;
301
302 zonelen = ip6_sa2str(
303 (const struct sockaddr_in6 *)(const void *)sa,
304 zonebuf, sizeof(zonebuf), flags);
305 if (zonelen < 0)
306 return EAI_MEMORY;
307 if (zonelen + 1 + numaddrlen + 1 > hostlen)
308 return EAI_MEMORY;
309
310 /* construct <numeric-addr><delim><zoneid> */
311 memcpy(host + numaddrlen + 1, zonebuf,
312 (size_t)zonelen);
313 host[numaddrlen] = SCOPE_DELIMITER;
314 host[numaddrlen + 1 + zonelen] = '\0';
315 }
316
317 return 0;
318}
319
320/* ARGSUSED */
321static int
322ip6_sa2str(sa6, buf, bufsiz, flags)
323 const struct sockaddr_in6 *sa6;
324 char *buf;
325 size_t bufsiz;
326 int flags;
327{
328 unsigned int ifindex;
329 const struct in6_addr *a6;
330 int n;
331
332 ifindex = (unsigned int)sa6->sin6_scope_id;
333 a6 = &sa6->sin6_addr;
334
335#ifdef notdef
336 if ((flags & NI_NUMERICSCOPE) != 0) {
337 n = snprintf(buf, bufsiz, "%u", sa6->sin6_scope_id);
338 if (n < 0 || n >= bufsiz)
339 return -1;
340 else
341 return n;
342 }
343#endif
344
345 /* if_indextoname() does not take buffer size. not a good api... */
346 if ((IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6)) &&
347 bufsiz >= IF_NAMESIZE) {
348 char *p = if_indextoname(ifindex, buf);
349 if (p) {
350 return(strlen(p));
351 }
352 }
353
354 /* last resort */
355 n = snprintf(buf, bufsiz, "%u", sa6->sin6_scope_id);
356 if (n < 0 || n >= bufsiz)
357 return -1;
358 else
359 return n;
360}
361#endif /* INET6 */
diff --git a/src/lib/libc/net/getnetbyaddr.c b/src/lib/libc/net/getnetbyaddr.c
new file mode 100644
index 0000000000..925d1d5895
--- /dev/null
+++ b/src/lib/libc/net/getnetbyaddr.c
@@ -0,0 +1,56 @@
1/*
2 * Copyright (c) 1983, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#if defined(LIBC_SCCS) && !defined(lint)
35static char rcsid[] = "$OpenBSD: getnetbyaddr.c,v 1.5 1997/07/09 01:08:28 millert Exp $";
36#endif /* LIBC_SCCS and not lint */
37
38#include <netdb.h>
39
40extern int _net_stayopen;
41
42struct netent *
43_getnetbyaddr(net, type)
44 register in_addr_t net;
45 register int type;
46{
47 register struct netent *p;
48
49 setnetent(_net_stayopen);
50 while ((p = getnetent()))
51 if (p->n_addrtype == type && p->n_net == net)
52 break;
53 if (!_net_stayopen)
54 endnetent();
55 return (p);
56}
diff --git a/src/lib/libc/net/getnetbyname.c b/src/lib/libc/net/getnetbyname.c
new file mode 100644
index 0000000000..4e39cf6860
--- /dev/null
+++ b/src/lib/libc/net/getnetbyname.c
@@ -0,0 +1,62 @@
1/*
2 * Copyright (c) 1983, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#if defined(LIBC_SCCS) && !defined(lint)
35static char rcsid[] = "$OpenBSD: getnetbyname.c,v 1.5 1997/07/09 01:08:29 millert Exp $";
36#endif /* LIBC_SCCS and not lint */
37
38#include <netdb.h>
39#include <string.h>
40
41extern int _net_stayopen;
42
43struct netent *
44_getnetbyname(name)
45 register const char *name;
46{
47 register struct netent *p;
48 register char **cp;
49
50 setnetent(_net_stayopen);
51 while ((p = getnetent())) {
52 if (strcasecmp(p->n_name, name) == 0)
53 break;
54 for (cp = p->n_aliases; *cp != 0; cp++)
55 if (strcasecmp(*cp, name) == 0)
56 goto found;
57 }
58found:
59 if (!_net_stayopen)
60 endnetent();
61 return (p);
62}
diff --git a/src/lib/libc/net/getnetent.3 b/src/lib/libc/net/getnetent.3
new file mode 100644
index 0000000000..0c401c74ff
--- /dev/null
+++ b/src/lib/libc/net/getnetent.3
@@ -0,0 +1,144 @@
1.\" $OpenBSD: getnetent.3,v 1.11 2000/12/24 00:30:56 aaron Exp $
2.\"
3.\" Copyright (c) 1983, 1991, 1993
4.\" The Regents of the University of California. All rights reserved.
5.\"
6.\" Redistribution and use in source and binary forms, with or without
7.\" modification, are permitted provided that the following conditions
8.\" are met:
9.\" 1. Redistributions of source code must retain the above copyright
10.\" notice, this list of conditions and the following disclaimer.
11.\" 2. Redistributions in binary form must reproduce the above copyright
12.\" notice, this list of conditions and the following disclaimer in the
13.\" documentation and/or other materials provided with the distribution.
14.\" 3. All advertising materials mentioning features or use of this software
15.\" must display the following acknowledgement:
16.\" This product includes software developed by the University of
17.\" California, Berkeley and its contributors.
18.\" 4. Neither the name of the University nor the names of its contributors
19.\" may be used to endorse or promote products derived from this software
20.\" without specific prior written permission.
21.\"
22.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32.\" SUCH DAMAGE.
33.\"
34.Dd March 13, 1997
35.Dt GETNETENT 3
36.Os
37.Sh NAME
38.Nm getnetent ,
39.Nm getnetbyaddr ,
40.Nm getnetbyname ,
41.Nm setnetent ,
42.Nm endnetent
43.Nd get network entry
44.Sh SYNOPSIS
45.Fd #include <netdb.h>
46.Ft struct netent *
47.Fn getnetent "void"
48.Ft struct netent *
49.Fn getnetbyname "char *name"
50.Ft struct netent *
51.Fn getnetbyaddr "in_addr_t net" "int type"
52.Ft void
53.Fn setnetent "int stayopen"
54.Ft void
55.Fn endnetent "void"
56.Sh DESCRIPTION
57The
58.Fn getnetent ,
59.Fn getnetbyname ,
60and
61.Fn getnetbyaddr
62functions each return a pointer to an object with the following structure
63containing the broken-out fields of a line in the network database,
64.Pa /etc/networks .
65.Bd -literal -offset indent
66struct netent {
67 char *n_name; /* official name of net */
68 char **n_aliases; /* alias list */
69 int n_addrtype; /* net number type */
70 in_addr_t n_net; /* net number */
71};
72.Ed
73.Pp
74The members of this structure are:
75.Bl -tag -width n_addrtype
76.It Fa n_name
77The official name of the network.
78.It Fa n_aliases
79A zero-terminated list of alternate names for the network.
80.It Fa n_addrtype
81The type of the network number returned; currently only
82.Dv AF_INET .
83.It Fa n_net
84The network number.
85Network numbers are returned in machine byte order.
86.El
87.Pp
88The
89.Fn getnetent
90function reads the next line of the file, opening the file if necessary.
91.Pp
92The
93.Fn setnetent
94function opens and rewinds the file.
95If the
96.Fa stayopen
97flag is non-zero,
98the net database will not be closed after each call to
99.Fn getnetbyname
100or
101.Fn getnetbyaddr .
102.Pp
103The
104.Fn endnetent
105function closes the file.
106.Pp
107The
108.Fn getnetbyname
109and
110.Fn getnetbyaddr
111functions search the domain name server if the system is configured to use one.
112If the search fails, or no name server is configured, they sequentially
113search from the beginning of the file until a matching net name or
114net address and type is found, or until
115.Dv EOF
116is encountered.
117Network numbers are supplied in host order.
118.Sh FILES
119.Bl -tag -width /etc/networks -compact
120.It Pa /etc/networks
121.El
122.Sh DIAGNOSTICS
123Null pointer (0) returned on
124.Dv EOF
125or error.
126.Sh SEE ALSO
127.Xr resolver 3 ,
128.Xr networks 5
129.Sh HISTORY
130The
131.Fn getnetent ,
132.Fn getnetbyaddr ,
133.Fn getnetbyname ,
134.Fn setnetent ,
135and
136.Fn endnetent
137functions appeared in
138.Bx 4.2 .
139.Sh BUGS
140The data space used by these functions is static; if future use
141requires the data, it should be copied before any subsequent calls
142to these functions overwrite it.
143Only Internet network numbers are currently understood.
144Expecting network numbers to fit in no more than 32 bits is naive.
diff --git a/src/lib/libc/net/getnetent.c b/src/lib/libc/net/getnetent.c
new file mode 100644
index 0000000000..8f618a1d5e
--- /dev/null
+++ b/src/lib/libc/net/getnetent.c
@@ -0,0 +1,129 @@
1/*
2 * Copyright (c) 1983, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#if defined(LIBC_SCCS) && !defined(lint)
35static char rcsid[] = "$OpenBSD: getnetent.c,v 1.8 1998/03/16 05:06:57 millert Exp $";
36#endif /* LIBC_SCCS and not lint */
37
38#include <sys/types.h>
39#include <sys/socket.h>
40#include <netinet/in.h>
41#include <arpa/inet.h>
42#include <netdb.h>
43#include <stdio.h>
44#include <string.h>
45
46#define MAXALIASES 35
47
48static FILE *netf;
49static char line[BUFSIZ+1];
50static struct netent net;
51static char *net_aliases[MAXALIASES];
52int _net_stayopen;
53
54void
55setnetent(f)
56 int f;
57{
58 if (netf == NULL)
59 netf = fopen(_PATH_NETWORKS, "r" );
60 else
61 rewind(netf);
62 _net_stayopen |= f;
63}
64
65void
66endnetent()
67{
68 if (netf) {
69 fclose(netf);
70 netf = NULL;
71 }
72 _net_stayopen = 0;
73}
74
75struct netent *
76getnetent()
77{
78 char *p, *cp, **q;
79 size_t len;
80
81 if (netf == NULL && (netf = fopen(_PATH_NETWORKS, "r" )) == NULL)
82 return (NULL);
83again:
84 if ((p = fgetln(netf, &len)) == NULL)
85 return (NULL);
86 if (p[len-1] == '\n')
87 len--;
88 if (len >= sizeof(line) || len == 0)
89 goto again;
90 p = memcpy(line, p, len);
91 line[len] = '\0';
92 if (*p == '#')
93 goto again;
94 if ((cp = strchr(p, '#')) != NULL)
95 *cp = '\0';
96 net.n_name = p;
97 if (strlen(net.n_name) >= MAXHOSTNAMELEN-1)
98 net.n_name[MAXHOSTNAMELEN-1] = '\0';
99 cp = strpbrk(p, " \t");
100 if (cp == NULL)
101 goto again;
102 *cp++ = '\0';
103 while (*cp == ' ' || *cp == '\t')
104 cp++;
105 p = strpbrk(cp, " \t");
106 if (p != NULL)
107 *p++ = '\0';
108 net.n_net = inet_network(cp);
109 net.n_addrtype = AF_INET;
110 q = net.n_aliases = net_aliases;
111 if (p != NULL)
112 cp = p;
113 while (cp && *cp) {
114 if (*cp == ' ' || *cp == '\t') {
115 cp++;
116 continue;
117 }
118 if (q < &net_aliases[MAXALIASES - 1]) {
119 *q++ = cp;
120 if (strlen(cp) >= MAXHOSTNAMELEN-1)
121 cp[MAXHOSTNAMELEN-1] = '\0';
122 }
123 cp = strpbrk(cp, " \t");
124 if (cp != NULL)
125 *cp++ = '\0';
126 }
127 *q = NULL;
128 return (&net);
129}
diff --git a/src/lib/libc/net/getnetnamadr.c b/src/lib/libc/net/getnetnamadr.c
new file mode 100644
index 0000000000..abbfdbd64c
--- /dev/null
+++ b/src/lib/libc/net/getnetnamadr.c
@@ -0,0 +1,391 @@
1/* $OpenBSD: getnetnamadr.c,v 1.18 2002/08/27 08:53:13 itojun Exp $ */
2
3/*
4 * Copyright (c) 1997, Jason Downs. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed by Jason Downs for the
17 * OpenBSD system.
18 * 4. Neither the name(s) of the author(s) nor the name OpenBSD
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS
23 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT,
26 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
27 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34/* Copyright (c) 1993 Carlos Leandro and Rui Salgueiro
35 * Dep. Matematica Universidade de Coimbra, Portugal, Europe
36 *
37 * Permission to use, copy, modify, and distribute this software for any
38 * purpose with or without fee is hereby granted, provided that the above
39 * copyright notice and this permission notice appear in all copies.
40 */
41/*
42 * Copyright (c) 1983, 1993
43 * The Regents of the University of California. All rights reserved.
44 *
45 * Redistribution and use in source and binary forms, with or without
46 * modification, are permitted provided that the following conditions
47 * are met:
48 * 1. Redistributions of source code must retain the above copyright
49 * notice, this list of conditions and the following disclaimer.
50 * 2. Redistributions in binary form must reproduce the above copyright
51 * notice, this list of conditions and the following disclaimer in the
52 * documentation and/or other materials provided with the distribution.
53 * 3. All advertising materials mentioning features or use of this software
54 * must display the following acknowledgement:
55 * This product includes software developed by the University of
56 * California, Berkeley and its contributors.
57 * 4. Neither the name of the University nor the names of its contributors
58 * may be used to endorse or promote products derived from this software
59 * without specific prior written permission.
60 *
61 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
62 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
63 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
64 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
65 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
66 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
67 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
68 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
69 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
70 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
71 * SUCH DAMAGE.
72 */
73
74#if defined(LIBC_SCCS) && !defined(lint)
75#if 0
76static char sccsid[] = "@(#)getnetbyaddr.c 8.1 (Berkeley) 6/4/93";
77static char sccsid_[] = "from getnetnamadr.c 1.4 (Coimbra) 93/06/03";
78static char rcsid[] = "$From: getnetnamadr.c,v 8.7 1996/08/05 08:31:35 vixie Exp $";
79#else
80static char rcsid[] = "$OpenBSD: getnetnamadr.c,v 1.18 2002/08/27 08:53:13 itojun Exp $";
81#endif
82#endif /* LIBC_SCCS and not lint */
83
84#include <sys/types.h>
85#include <sys/param.h>
86#include <sys/socket.h>
87#include <netinet/in.h>
88#include <arpa/inet.h>
89#include <arpa/nameser.h>
90
91#include <stdio.h>
92#include <netdb.h>
93#include <resolv.h>
94#include <ctype.h>
95#include <errno.h>
96#include <string.h>
97#include <stdlib.h>
98
99extern int h_errno;
100
101struct netent *_getnetbyaddr(in_addr_t net, int type);
102struct netent *_getnetbyname(const char *name);
103
104int _hokchar(const char *);
105
106#define BYADDR 0
107#define BYNAME 1
108#define MAXALIASES 35
109
110#define MAXPACKET (64*1024)
111
112typedef union {
113 HEADER hdr;
114 u_char buf[MAXPACKET];
115} querybuf;
116
117typedef union {
118 long al;
119 char ac;
120} align;
121
122static struct netent *
123getnetanswer(answer, anslen, net_i)
124 querybuf *answer;
125 int anslen;
126 int net_i;
127{
128
129 register HEADER *hp;
130 register u_char *cp;
131 register int n;
132 u_char *eom;
133 int type, class, ancount, qdcount, haveanswer, i, nchar;
134 char aux1[MAXHOSTNAMELEN], aux2[MAXHOSTNAMELEN], ans[MAXHOSTNAMELEN];
135 char *in, *st, *pauxt, *bp, **ap, *ep;
136 char *paux1 = &aux1[0], *paux2 = &aux2[0], flag = 0;
137 static struct netent net_entry;
138 static char *net_aliases[MAXALIASES], netbuf[BUFSIZ+1];
139
140 /*
141 * find first satisfactory answer
142 *
143 * answer --> +------------+ ( MESSAGE )
144 * | Header |
145 * +------------+
146 * | Question | the question for the name server
147 * +------------+
148 * | Answer | RRs answering the question
149 * +------------+
150 * | Authority | RRs pointing toward an authority
151 * | Additional | RRs holding additional information
152 * +------------+
153 */
154 eom = answer->buf + anslen;
155 hp = &answer->hdr;
156 ancount = ntohs(hp->ancount); /* #/records in the answer section */
157 qdcount = ntohs(hp->qdcount); /* #/entries in the question section */
158 bp = netbuf;
159 ep = netbuf + sizeof(netbuf);
160 cp = answer->buf + HFIXEDSZ;
161 if (!qdcount) {
162 if (hp->aa)
163 h_errno = HOST_NOT_FOUND;
164 else
165 h_errno = TRY_AGAIN;
166 return (NULL);
167 }
168 while (qdcount-- > 0)
169 cp += __dn_skipname(cp, eom) + QFIXEDSZ;
170 ap = net_aliases;
171 *ap = NULL;
172 net_entry.n_aliases = net_aliases;
173 haveanswer = 0;
174 while (--ancount >= 0 && cp < eom) {
175 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
176#ifdef USE_RESOLV_NAME_OK
177 if ((n < 0) || !res_dnok(bp))
178#else
179 if ((n < 0) || !_hokchar(bp))
180#endif
181 break;
182 cp += n;
183 ans[0] = '\0';
184 strlcpy(&ans[0], bp, sizeof ans);
185 GETSHORT(type, cp);
186 GETSHORT(class, cp);
187 cp += INT32SZ; /* TTL */
188 GETSHORT(n, cp);
189 if (class == C_IN && type == T_PTR) {
190 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
191#ifdef USE_RESOLV_NAME_OK
192 if ((n < 0) || !res_hnok(bp))
193#else
194 if ((n < 0) || !_hokchar(bp))
195#endif
196 {
197 cp += n;
198 return (NULL);
199 }
200 cp += n;
201 *ap++ = bp;
202 bp += strlen(bp) + 1;
203 net_entry.n_addrtype =
204 (class == C_IN) ? AF_INET : AF_UNSPEC;
205 haveanswer++;
206 }
207 }
208 if (haveanswer) {
209 *ap = NULL;
210 switch (net_i) {
211 case BYADDR:
212 net_entry.n_name = *net_entry.n_aliases;
213 net_entry.n_net = 0L;
214 break;
215 case BYNAME:
216 in = *net_entry.n_aliases;
217 net_entry.n_name = &ans[0];
218 aux2[0] = '\0';
219 for (i = 0; i < 4; i++) {
220 for (st = in, nchar = 0;
221 *st != '.';
222 st++, nchar++)
223 ;
224 if (nchar != 1 || *in != '0' || flag) {
225 flag = 1;
226 strlcpy(paux1,
227 (i==0) ? in : in-1,
228 (i==0) ? nchar+1 : nchar+2);
229 pauxt = paux2;
230 paux2 = strcat(paux1, paux2);
231 paux1 = pauxt;
232 }
233 in = ++st;
234 }
235 net_entry.n_net = inet_network(paux2);
236 break;
237 }
238 net_entry.n_aliases++;
239 return (&net_entry);
240 }
241 h_errno = TRY_AGAIN;
242 return (NULL);
243}
244
245struct netent *
246getnetbyaddr(net, net_type)
247 register in_addr_t net;
248 register int net_type;
249{
250 unsigned int netbr[4];
251 int nn, anslen;
252 querybuf *buf;
253 char qbuf[MAXDNAME];
254 in_addr_t net2;
255 struct netent *net_entry = NULL;
256 char lookups[MAXDNSLUS];
257 int i;
258
259 if ((_res.options & RES_INIT) == 0 && res_init() == -1)
260 return(_getnetbyaddr(net, net_type));
261
262 bcopy(_res.lookups, lookups, sizeof lookups);
263 if (lookups[0] == '\0')
264 strlcpy(lookups, "bf", sizeof lookups);
265
266 for (i = 0; i < MAXDNSLUS && lookups[i]; i++) {
267 switch (lookups[i]) {
268#ifdef YP
269 case 'y':
270 /* There is no YP support. */
271 break;
272#endif /* YP */
273 case 'b':
274 if (net_type != AF_INET)
275 break; /* DNS only supports AF_INET? */
276
277 for (nn = 4, net2 = net; net2; net2 >>= 8)
278 netbr[--nn] = net2 & 0xff;
279 switch (nn) {
280 case 3: /* Class A */
281 snprintf(qbuf, sizeof(qbuf),
282 "0.0.0.%u.in-addr.arpa", netbr[3]);
283 break;
284 case 2: /* Class B */
285 snprintf(qbuf, sizeof(qbuf),
286 "0.0.%u.%u.in-addr.arpa",
287 netbr[3], netbr[2]);
288 break;
289 case 1: /* Class C */
290 snprintf(qbuf, sizeof(qbuf),
291 "0.%u.%u.%u.in-addr.arpa",
292 netbr[3], netbr[2], netbr[1]);
293 break;
294 case 0: /* Class D - E */
295 snprintf(qbuf, sizeof(qbuf),
296 "%u.%u.%u.%u.in-addr.arpa",
297 netbr[3], netbr[2], netbr[1], netbr[0]);
298 break;
299 }
300 buf = malloc(sizeof(*buf));
301 if (buf == NULL)
302 break;
303 anslen = res_query(qbuf, C_IN, T_PTR, buf->buf,
304 sizeof(buf->buf));
305 if (anslen < 0) {
306 free(buf);
307#ifdef DEBUG
308 if (_res.options & RES_DEBUG)
309 printf("res_query failed\n");
310#endif
311 break;
312 }
313 net_entry = getnetanswer(buf, anslen, BYADDR);
314 free(buf);
315 if (net_entry != NULL) {
316 unsigned u_net = net; /* maybe net should be unsigned ? */
317
318 /* Strip trailing zeros */
319 while ((u_net & 0xff) == 0 && u_net != 0)
320 u_net >>= 8;
321 net_entry->n_net = u_net;
322 return (net_entry);
323 }
324 break;
325 case 'f':
326 net_entry = _getnetbyaddr(net, net_type);
327 if (net_entry != NULL)
328 return (net_entry);
329 }
330 }
331
332 /* Nothing matched. */
333 return (NULL);
334}
335
336struct netent *
337getnetbyname(net)
338 register const char *net;
339{
340 int anslen;
341 querybuf *buf;
342 char qbuf[MAXDNAME];
343 struct netent *net_entry = NULL;
344 char lookups[MAXDNSLUS];
345 int i;
346
347 if ((_res.options & RES_INIT) == 0 && res_init() == -1)
348 return (_getnetbyname(net));
349
350 bcopy(_res.lookups, lookups, sizeof lookups);
351 if (lookups[0] == '\0')
352 strlcpy(lookups, "bf", sizeof lookups);
353
354 for (i = 0; i < MAXDNSLUS && lookups[i]; i++) {
355 switch (lookups[i]) {
356#ifdef YP
357 case 'y':
358 /* There is no YP support. */
359 break;
360#endif /* YP */
361 case 'b':
362 strlcpy(qbuf, net, sizeof qbuf);
363 buf = malloc(sizeof(*buf));
364 if (buf == NULL)
365 break;
366 anslen = res_search(qbuf, C_IN, T_PTR, buf->buf,
367 sizeof(buf->buf));
368 if (anslen < 0) {
369 free(buf);
370#ifdef DEBUG
371 if (_res.options & RES_DEBUG)
372 printf("res_query failed\n");
373#endif
374 break;
375 }
376 net_entry = getnetanswer(buf, anslen, BYNAME);
377 free(buf);
378 if (net_entry != NULL)
379 return (net_entry);
380 break;
381 case 'f':
382 net_entry = _getnetbyname(net);
383 if (net_entry != NULL)
384 return (net_entry);
385 break;
386 }
387 }
388
389 /* Nothing matched. */
390 return (NULL);
391}
diff --git a/src/lib/libc/net/getproto.c b/src/lib/libc/net/getproto.c
new file mode 100644
index 0000000000..474d8d9427
--- /dev/null
+++ b/src/lib/libc/net/getproto.c
@@ -0,0 +1,55 @@
1/*
2 * Copyright (c) 1983, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#if defined(LIBC_SCCS) && !defined(lint)
35static char rcsid[] = "$OpenBSD: getproto.c,v 1.3 1997/07/09 01:08:31 millert Exp $";
36#endif /* LIBC_SCCS and not lint */
37
38#include <netdb.h>
39
40extern int _proto_stayopen;
41
42struct protoent *
43getprotobynumber(proto)
44 register int proto;
45{
46 register struct protoent *p;
47
48 setprotoent(_proto_stayopen);
49 while ((p = getprotoent()))
50 if (p->p_proto == proto)
51 break;
52 if (!_proto_stayopen)
53 endprotoent();
54 return (p);
55}
diff --git a/src/lib/libc/net/getprotoent.3 b/src/lib/libc/net/getprotoent.3
new file mode 100644
index 0000000000..1f95529532
--- /dev/null
+++ b/src/lib/libc/net/getprotoent.3
@@ -0,0 +1,134 @@
1.\" $OpenBSD: getprotoent.3,v 1.8 2000/12/24 00:30:56 aaron Exp $
2.\"
3.\" Copyright (c) 1983, 1991, 1993
4.\" The Regents of the University of California. All rights reserved.
5.\"
6.\" Redistribution and use in source and binary forms, with or without
7.\" modification, are permitted provided that the following conditions
8.\" are met:
9.\" 1. Redistributions of source code must retain the above copyright
10.\" notice, this list of conditions and the following disclaimer.
11.\" 2. Redistributions in binary form must reproduce the above copyright
12.\" notice, this list of conditions and the following disclaimer in the
13.\" documentation and/or other materials provided with the distribution.
14.\" 3. All advertising materials mentioning features or use of this software
15.\" must display the following acknowledgement:
16.\" This product includes software developed by the University of
17.\" California, Berkeley and its contributors.
18.\" 4. Neither the name of the University nor the names of its contributors
19.\" may be used to endorse or promote products derived from this software
20.\" without specific prior written permission.
21.\"
22.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32.\" SUCH DAMAGE.
33.\"
34.Dd June 4, 1993
35.Dt GETPROTOENT 3
36.Os
37.Sh NAME
38.Nm getprotoent ,
39.Nm getprotobynumber ,
40.Nm getprotobyname ,
41.Nm setprotoent ,
42.Nm endprotoent
43.Nd get protocol entry
44.Sh SYNOPSIS
45.Fd #include <netdb.h>
46.Ft struct protoent *
47.Fn getprotoent "void"
48.Ft struct protoent *
49.Fn getprotobyname "char *name"
50.Ft struct protoent *
51.Fn getprotobynumber "int proto"
52.Ft void
53.Fn setprotoent "int stayopen"
54.Ft void
55.Fn endprotoent "void"
56.Sh DESCRIPTION
57The
58.Fn getprotoent ,
59.Fn getprotobyname ,
60and
61.Fn getprotobynumber
62functions each return a pointer to an object with the following structure
63containing the broken-out fields of a line in the network protocol database,
64.Pa /etc/protocols .
65.Bd -literal -offset indent
66.Pp
67struct protoent {
68 char *p_name; /* official name of protocol */
69 char **p_aliases; /* alias list */
70 int p_proto; /* protocol number */
71};
72.Ed
73.Pp
74The members of this structure are:
75.Bl -tag -width p_aliases
76.It Fa p_name
77The official name of the protocol.
78.It Fa p_aliases
79A zero-terminated list of alternate names for the protocol.
80.It Fa p_proto
81The protocol number.
82.El
83.Pp
84The
85.Fn getprotoent
86function reads the next line of the file, opening the file if necessary.
87.Pp
88The
89.Fn setprotoent
90function opens and rewinds the file.
91If the
92.Fa stayopen
93flag is non-zero,
94the net database will not be closed after each call to
95.Fn getprotobyname
96or
97.Fn getprotobynumber .
98.Pp
99The
100.Fn endprotoent
101function closes the file.
102.Pp
103The
104.Fn getprotobyname
105and
106.Fn getprotobynumber
107functions sequentially search from the beginning of the file until a
108matching protocol name or protocol number is found, or until
109.Dv EOF
110is encountered.
111.Sh RETURN VALUES
112Null pointer (0) returned on
113.Dv EOF
114or error.
115.Sh FILES
116.Bl -tag -width /etc/protocols -compact
117.It Pa /etc/protocols
118.El
119.Sh SEE ALSO
120.Xr protocols 5
121.Sh HISTORY
122The
123.Fn getprotoent ,
124.Fn getprotobynumber ,
125.Fn getprotobyname ,
126.Fn setprotoent ,
127and
128.Fn endprotoent
129functions appeared in
130.Bx 4.2 .
131.Sh BUGS
132These functions use a static data space; if the data is needed for future use,
133it should be copied before any subsequent calls overwrite it.
134Only the Internet protocols are currently understood.
diff --git a/src/lib/libc/net/getprotoent.c b/src/lib/libc/net/getprotoent.c
new file mode 100644
index 0000000000..2f8b267611
--- /dev/null
+++ b/src/lib/libc/net/getprotoent.c
@@ -0,0 +1,127 @@
1/*
2 * Copyright (c) 1983, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#if defined(LIBC_SCCS) && !defined(lint)
35static char rcsid[] = "$OpenBSD: getprotoent.c,v 1.4 1999/09/03 16:23:18 millert Exp $";
36#endif /* LIBC_SCCS and not lint */
37
38#include <sys/types.h>
39#include <sys/socket.h>
40#include <netdb.h>
41#include <stdio.h>
42#include <stdlib.h>
43#include <string.h>
44
45#define MAXALIASES 35
46
47static FILE *protof = NULL;
48static char line[BUFSIZ+1];
49static struct protoent proto;
50static char *proto_aliases[MAXALIASES];
51int _proto_stayopen;
52
53void
54setprotoent(f)
55 int f;
56{
57 if (protof == NULL)
58 protof = fopen(_PATH_PROTOCOLS, "r" );
59 else
60 rewind(protof);
61 _proto_stayopen |= f;
62}
63
64void
65endprotoent()
66{
67 if (protof) {
68 fclose(protof);
69 protof = NULL;
70 }
71 _proto_stayopen = 0;
72}
73
74struct protoent *
75getprotoent()
76{
77 char *p, *cp, **q, *endp;
78 long l;
79 size_t len;
80
81 if (protof == NULL && (protof = fopen(_PATH_PROTOCOLS, "r" )) == NULL)
82 return (NULL);
83again:
84 if ((p = fgetln(protof, &len)) == NULL)
85 return (NULL);
86 if (p[len-1] == '\n')
87 len--;
88 if (len >= sizeof(line) || len == 0)
89 goto again;
90 p = memcpy(line, p, len);
91 line[len] = '\0';
92 if (*p == '#')
93 goto again;
94 if ((cp = strchr(p, '#')) != NULL)
95 *cp = '\0';
96 proto.p_name = p;
97 cp = strpbrk(p, " \t");
98 if (cp == NULL)
99 goto again;
100 *cp++ = '\0';
101 while (*cp == ' ' || *cp == '\t')
102 cp++;
103 p = strpbrk(cp, " \t");
104 if (p != NULL)
105 *p++ = '\0';
106 l = strtol(cp, &endp, 10);
107 if (endp == cp || *endp != '\0' || l < 0 || l >= INT_MAX)
108 goto again;
109 proto.p_proto = l;
110 q = proto.p_aliases = proto_aliases;
111 if (p != NULL) {
112 cp = p;
113 while (cp && *cp) {
114 if (*cp == ' ' || *cp == '\t') {
115 cp++;
116 continue;
117 }
118 if (q < &proto_aliases[MAXALIASES - 1])
119 *q++ = cp;
120 cp = strpbrk(cp, " \t");
121 if (cp != NULL)
122 *cp++ = '\0';
123 }
124 }
125 *q = NULL;
126 return (&proto);
127}
diff --git a/src/lib/libc/net/getprotoname.c b/src/lib/libc/net/getprotoname.c
new file mode 100644
index 0000000000..7a4e5fede5
--- /dev/null
+++ b/src/lib/libc/net/getprotoname.c
@@ -0,0 +1,62 @@
1/*
2 * Copyright (c) 1983, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#if defined(LIBC_SCCS) && !defined(lint)
35static char rcsid[] = "$OpenBSD: getprotoname.c,v 1.3 1997/07/09 01:08:32 millert Exp $";
36#endif /* LIBC_SCCS and not lint */
37
38#include <netdb.h>
39#include <string.h>
40
41extern int _proto_stayopen;
42
43struct protoent *
44getprotobyname(name)
45 register const char *name;
46{
47 register struct protoent *p;
48 register char **cp;
49
50 setprotoent(_proto_stayopen);
51 while ((p = getprotoent())) {
52 if (strcmp(p->p_name, name) == 0)
53 break;
54 for (cp = p->p_aliases; *cp != 0; cp++)
55 if (strcmp(*cp, name) == 0)
56 goto found;
57 }
58found:
59 if (!_proto_stayopen)
60 endprotoent();
61 return (p);
62}
diff --git a/src/lib/libc/net/getrrsetbyname.3 b/src/lib/libc/net/getrrsetbyname.3
new file mode 100644
index 0000000000..50cadfd372
--- /dev/null
+++ b/src/lib/libc/net/getrrsetbyname.3
@@ -0,0 +1,166 @@
1.\" $OpenBSD: getrrsetbyname.3,v 1.7 2002/06/09 05:03:59 deraadt Exp $
2.\"
3.\" Copyright (C) 2000, 2001 Internet Software Consortium.
4.\"
5.\" Permission to use, copy, modify, and distribute this software for any
6.\" purpose with or without fee is hereby granted, provided that the above
7.\" copyright notice and this permission notice appear in all copies.
8.\"
9.\" THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
10.\" DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
11.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
12.\" INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
13.\" INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
14.\" FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
15.\" NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
16.\" WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17.\"
18.Dd Oct 18, 2000
19.Dt GETRRSETBYNAME 3
20.Os
21.Sh NAME
22.Nm getrrsetbyname
23.Nd retrieve DNS records
24.Sh SYNOPSIS
25.Fd #include <netdb.h>
26.Ft int
27.Fn getrrsetbyname "const char *hostname" "unsigned int rdclass" \
28"unsigned int rdtype" "unsigned int flags" "struct rrsetinfo **res"
29.Ft int
30.Fn freerrset "struct rrsetinfo **rrset"
31.Sh DESCRIPTION
32.Fn getrrsetbyname
33gets a set of resource records associated with a
34.Fa hostname ,
35.Fa class
36and
37.Fa type .
38.Fa hostname
39is a pointer a to null-terminated string.
40The
41.Fa flags
42field is currently unused and must be zero.
43.Pp
44After a successful call to
45.Fn getrrsetbyname ,
46.Fa *res
47is a pointer to an
48.Li rrsetinfo
49structure, containing a list of one or more
50.Li rdatainfo
51structures containing resource records and potentially another list of
52.Li rdatainfo
53structures containing SIG resource records associated with those records.
54The members
55.Li rri_rdclass
56and
57.Li rri_rdtype
58are copied from the parameters.
59.Li rri_ttl
60and
61.Li rri_name
62are properties of the obtained rrset.
63The resource records contained in
64.Li rri_rdatas
65and
66.Li rri_sigs
67are in uncompressed DNS wire format.
68Properties of the rdataset are represented in the
69.Li rri_flags
70bitfield.
71If the
72.Dv RRSET_VALIDATED
73bit is set, the data has been DNSSEC
74validated and the signatures verified.
75.Pp
76The following structures are used:
77.Bd -literal -offset
78struct rdatainfo {
79 unsigned int rdi_length; /* length of data */
80 unsigned char *rdi_data; /* record data */
81};
82
83struct rrsetinfo {
84 unsigned int rri_flags; /* RRSET_VALIDATED ... */
85 unsigned int rri_rdclass; /* class number */
86 unsigned int rri_rdtype; /* RR type number */
87 unsigned int rri_ttl; /* time to live */
88 unsigned int rri_nrdatas; /* size of rdatas array */
89 unsigned int rri_nsigs; /* size of sigs array */
90 char *rri_name; /* canonical name */
91 struct rdatainfo *rri_rdatas; /* individual records */
92 struct rdatainfo *rri_sigs; /* individual signatures */
93};
94.Ed
95.Pp
96All of the information returned by
97.Fn getrrsetbyname
98is dynamically allocated: the
99.Li rrsetinfo
100and
101.Li rdatainfo
102structures,
103and the canonical host name strings pointed to by the
104.Li rrsetinfo
105u lib/libc/sys/lseek.2
106structure.
107Memory allocated for the dynamically allocated structures created by
108a successful call to
109.Fn getrrsetbyname
110is released by
111.Fn freerrset .
112.Li rrset
113is a pointer to a
114.Li struct rrset
115created by a call to
116.Fn getrrsetbyname .
117.Pp
118If the EDNS0 option is activated in
119.Xr resolv.conf 3 ,
120.Fn getrrsetbyname
121will request DNSSEC authentication using the EDNS0 DNSSEC OK (DO) bit.
122.Sh "RETURN VALUES"
123.Fn getrrsetbyname
124returns zero on success, and one of the following error
125codes if an error occurred:
126.Pp
127.Bl -tag -width ERRSET_NOMEMORY -compact
128.It Dv ERRSET_NONAME
129the name does not exist
130.It Dv ERRSET_NODATA
131the name exists, but does not have data of the desired type
132.It Dv ERRSET_NOMEMORY
133memory could not be allocated
134.It Dv ERRSET_INVAL
135a parameter is invalid
136.It Dv ERRSET_FAIL
137other failure
138.El
139.Sh SEE ALSO
140.Xr resolver 3 ,
141.Xr resolv.conf 5 ,
142.Xr named 8
143.Sh AUTHORS
144Jakob Schlyter
145.Aq jakob@openbsd.org
146.Sh HISTORY
147.Fn getrrsetbyname
148first appeared in
149.Ox 3.0 .
150The API first appeared in ISC BIND version 9.
151.Sh BUGS
152The data in
153.Li *rdi_data
154should be returned in uncompressed wire format.
155Currently, the data is in compressed format and the caller can't
156uncompress since it doesn't have the full message.
157.Sh CAVEATS
158The
159.Dv RRSET_VALIDATED
160flag in
161.Li rri_flags
162is set if the AD (autenticated data) bit in the DNS answer is
163set. This flag
164.Em should not
165be trusted unless the transport between the nameserver and the resolver
166is secure (e.g. IPsec, trusted network, loopback communication).
diff --git a/src/lib/libc/net/getrrsetbyname.c b/src/lib/libc/net/getrrsetbyname.c
new file mode 100644
index 0000000000..1ec60486b3
--- /dev/null
+++ b/src/lib/libc/net/getrrsetbyname.c
@@ -0,0 +1,508 @@
1/* $OpenBSD: getrrsetbyname.c,v 1.5 2002/09/07 20:54:04 jakob Exp $ */
2
3/*
4 * Copyright (c) 2001 Jakob Schlyter. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/*
30 * Portions Copyright (c) 1999-2001 Internet Software Consortium.
31 *
32 * Permission to use, copy, modify, and distribute this software for any
33 * purpose with or without fee is hereby granted, provided that the above
34 * copyright notice and this permission notice appear in all copies.
35 *
36 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
37 * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
38 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
39 * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
40 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
41 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
42 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
43 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
44 */
45
46#include <sys/types.h>
47#include <netinet/in.h>
48#include <arpa/nameser.h>
49#include <netdb.h>
50#include <resolv.h>
51#include <stdlib.h>
52#include <string.h>
53
54#define ANSWER_BUFFER_SIZE 1024*64
55
56struct dns_query {
57 char *name;
58 u_int16_t type;
59 u_int16_t class;
60 struct dns_query *next;
61};
62
63struct dns_rr {
64 char *name;
65 u_int16_t type;
66 u_int16_t class;
67 u_int16_t ttl;
68 u_int16_t size;
69 void *rdata;
70 struct dns_rr *next;
71};
72
73struct dns_response {
74 HEADER header;
75 struct dns_query *query;
76 struct dns_rr *answer;
77 struct dns_rr *authority;
78 struct dns_rr *additional;
79};
80
81static struct dns_response *parse_dns_response(const u_char *, int);
82static struct dns_query *parse_dns_qsection(const u_char *, int,
83 const u_char **, int);
84static struct dns_rr *parse_dns_rrsection(const u_char *, int, const u_char **,
85 int);
86
87static void free_dns_query(struct dns_query *);
88static void free_dns_rr(struct dns_rr *);
89static void free_dns_response(struct dns_response *);
90
91static int count_dns_rr(struct dns_rr *, u_int16_t, u_int16_t);
92
93int
94getrrsetbyname(const char *hostname, unsigned int rdclass,
95 unsigned int rdtype, unsigned int flags,
96 struct rrsetinfo **res)
97{
98 int result;
99 struct rrsetinfo *rrset = NULL;
100 struct dns_response *response;
101 struct dns_rr *rr;
102 struct rdatainfo *rdata;
103 unsigned int length, index_ans, index_sig;
104 u_char answer[ANSWER_BUFFER_SIZE];
105
106 /* check for invalid class and type */
107 if (rdclass > 0xffff || rdtype > 0xffff) {
108 result = ERRSET_INVAL;
109 goto fail;
110 }
111
112 /* don't allow queries of class or type ANY */
113 if (rdclass == 0xff || rdtype == 0xff) {
114 result = ERRSET_INVAL;
115 goto fail;
116 }
117
118 /* don't allow flags yet, unimplemented */
119 if (flags) {
120 result = ERRSET_INVAL;
121 goto fail;
122 }
123
124 /* initialize resolver */
125 if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
126 result = ERRSET_FAIL;
127 goto fail;
128 }
129
130#ifdef DEBUG
131 _res.options |= RES_DEBUG;
132#endif /* DEBUG */
133
134#ifdef RES_USE_DNSSEC
135 /* turn on DNSSEC if EDNS0 is configured */
136 if (_res.options & RES_USE_EDNS0)
137 _res.options |= RES_USE_DNSSEC;
138#endif /* RES_USE_DNSEC */
139
140 /* make query */
141 length = res_query(hostname, (signed int) rdclass, (signed int) rdtype,
142 answer, sizeof(answer));
143 if (length < 0) {
144 switch(h_errno) {
145 case HOST_NOT_FOUND:
146 result = ERRSET_NONAME;
147 goto fail;
148 case NO_DATA:
149 result = ERRSET_NODATA;
150 goto fail;
151 default:
152 result = ERRSET_FAIL;
153 goto fail;
154 }
155 }
156
157 /* parse result */
158 response = parse_dns_response(answer, length);
159 if (response == NULL) {
160 result = ERRSET_FAIL;
161 goto fail;
162 }
163
164 if (response->header.qdcount != 1) {
165 result = ERRSET_FAIL;
166 goto fail;
167 }
168
169 /* initialize rrset */
170 rrset = calloc(1, sizeof(struct rrsetinfo));
171 if (rrset == NULL) {
172 result = ERRSET_NOMEMORY;
173 goto fail;
174 }
175 rrset->rri_rdclass = response->query->class;
176 rrset->rri_rdtype = response->query->type;
177 rrset->rri_ttl = response->answer->ttl;
178 rrset->rri_nrdatas = response->header.ancount;
179
180 /* check for authenticated data */
181 if (response->header.ad == 1)
182 rrset->rri_flags |= RRSET_VALIDATED;
183
184 /* copy name from answer section */
185 length = strlen(response->answer->name);
186 rrset->rri_name = malloc(length + 1);
187 if (rrset->rri_name == NULL) {
188 result = ERRSET_NOMEMORY;
189 goto fail;
190 }
191 strlcpy(rrset->rri_name, response->answer->name, length + 1);
192
193 /* count answers */
194 rrset->rri_nrdatas = count_dns_rr(response->answer, rrset->rri_rdclass,
195 rrset->rri_rdtype);
196 rrset->rri_nsigs = count_dns_rr(response->answer, rrset->rri_rdclass,
197 T_SIG);
198
199 /* allocate memory for answers */
200 rrset->rri_rdatas = calloc(rrset->rri_nrdatas,
201 sizeof(struct rdatainfo));
202 if (rrset->rri_rdatas == NULL) {
203 result = ERRSET_NOMEMORY;
204 goto fail;
205 }
206
207 /* allocate memory for signatures */
208 rrset->rri_sigs = calloc(rrset->rri_nsigs, sizeof(struct rdatainfo));
209 if (rrset->rri_sigs == NULL) {
210 result = ERRSET_NOMEMORY;
211 goto fail;
212 }
213
214 /* copy answers & signatures */
215 for (rr = response->answer, index_ans = 0, index_sig = 0;
216 rr; rr = rr->next) {
217
218 rdata = NULL;
219
220 if (rr->class == rrset->rri_rdclass &&
221 rr->type == rrset->rri_rdtype)
222 rdata = &rrset->rri_rdatas[index_ans++];
223
224 if (rr->class == rrset->rri_rdclass &&
225 rr->type == T_SIG)
226 rdata = &rrset->rri_sigs[index_sig++];
227
228 if (rdata) {
229 rdata->rdi_length = rr->size;
230 rdata->rdi_data = malloc(rr->size);
231
232 if (rdata->rdi_data == NULL) {
233 result = ERRSET_NOMEMORY;
234 goto fail;
235 }
236 memcpy(rdata->rdi_data, rr->rdata, rr->size);
237 }
238 }
239
240 *res = rrset;
241 return (ERRSET_SUCCESS);
242
243fail:
244 if (rrset != NULL)
245 freerrset(rrset);
246 return (result);
247}
248
249void
250freerrset(struct rrsetinfo *rrset)
251{
252 u_int16_t i;
253
254 if (rrset == NULL)
255 return;
256
257 if (rrset->rri_rdatas) {
258 for (i = 0; i < rrset->rri_nrdatas; i++) {
259 if (rrset->rri_rdatas[i].rdi_data == NULL)
260 break;
261 free(rrset->rri_rdatas[i].rdi_data);
262 }
263 free(rrset->rri_rdatas);
264 }
265
266 if (rrset->rri_sigs) {
267 for (i = 0; i < rrset->rri_nsigs; i++) {
268 if (rrset->rri_sigs[i].rdi_data == NULL)
269 break;
270 free(rrset->rri_sigs[i].rdi_data);
271 }
272 free(rrset->rri_sigs);
273 }
274
275 if (rrset->rri_name)
276 free(rrset->rri_name);
277 free(rrset);
278}
279
280/*
281 * DNS response parsing routines
282 */
283static struct dns_response *
284parse_dns_response(const u_char *answer, int size)
285{
286 struct dns_response *resp;
287 const u_char *cp;
288
289 /* allocate memory for the response */
290 resp = calloc(1, sizeof(*resp));
291 if (resp == NULL)
292 return (NULL);
293
294 /* initialize current pointer */
295 cp = answer;
296
297 /* copy header */
298 memcpy(&resp->header, cp, HFIXEDSZ);
299 cp += HFIXEDSZ;
300
301 /* fix header byte order */
302 resp->header.qdcount = ntohs(resp->header.qdcount);
303 resp->header.ancount = ntohs(resp->header.ancount);
304 resp->header.nscount = ntohs(resp->header.nscount);
305 resp->header.arcount = ntohs(resp->header.arcount);
306
307 /* there must be at least one query */
308 if (resp->header.qdcount < 1) {
309 free_dns_response(resp);
310 return (NULL);
311 }
312
313 /* parse query section */
314 resp->query = parse_dns_qsection(answer, size, &cp,
315 resp->header.qdcount);
316 if (resp->header.qdcount && resp->query == NULL) {
317 free_dns_response(resp);
318 return (NULL);
319 }
320
321 /* parse answer section */
322 resp->answer = parse_dns_rrsection(answer, size, &cp,
323 resp->header.ancount);
324 if (resp->header.ancount && resp->answer == NULL) {
325 free_dns_response(resp);
326 return (NULL);
327 }
328
329 /* parse authority section */
330 resp->authority = parse_dns_rrsection(answer, size, &cp,
331 resp->header.nscount);
332 if (resp->header.nscount && resp->authority == NULL) {
333 free_dns_response(resp);
334 return (NULL);
335 }
336
337 /* parse additional section */
338 resp->additional = parse_dns_rrsection(answer, size, &cp,
339 resp->header.arcount);
340 if (resp->header.arcount && resp->additional == NULL) {
341 free_dns_response(resp);
342 return (NULL);
343 }
344
345 return (resp);
346}
347
348static struct dns_query *
349parse_dns_qsection(const u_char *answer, int size, const u_char **cp, int count)
350{
351 struct dns_query *head, *curr, *prev;
352 int i, length;
353 char name[MAXDNAME];
354
355 for (i = 1, head = NULL, prev = NULL; i <= count; i++, prev = curr) {
356
357 /* allocate and initialize struct */
358 curr = calloc(1, sizeof(struct dns_query));
359 if (curr == NULL) {
360 free_dns_query(head);
361 return (NULL);
362 }
363 if (head == NULL)
364 head = curr;
365 if (prev != NULL)
366 prev->next = curr;
367
368 /* name */
369 length = dn_expand(answer, answer + size, *cp, name,
370 sizeof(name));
371 if (length < 0) {
372 free_dns_query(head);
373 return (NULL);
374 }
375 curr->name = strdup(name);
376 if (curr->name == NULL) {
377 free_dns_query(head);
378 return (NULL);
379 }
380 *cp += length;
381
382 /* type */
383 curr->type = _getshort(*cp);
384 *cp += INT16SZ;
385
386 /* class */
387 curr->class = _getshort(*cp);
388 *cp += INT16SZ;
389 }
390
391 return (head);
392}
393
394static struct dns_rr *
395parse_dns_rrsection(const u_char *answer, int size, const u_char **cp, int count)
396{
397 struct dns_rr *head, *curr, *prev;
398 int i, length;
399 char name[MAXDNAME];
400
401 for (i = 1, head = NULL, prev = NULL; i <= count; i++, prev = curr) {
402
403 /* allocate and initialize struct */
404 curr = calloc(1, sizeof(struct dns_rr));
405 if (curr == NULL) {
406 free_dns_rr(head);
407 return (NULL);
408 }
409 if (head == NULL)
410 head = curr;
411 if (prev != NULL)
412 prev->next = curr;
413
414 /* name */
415 length = dn_expand(answer, answer + size, *cp, name,
416 sizeof(name));
417 if (length < 0) {
418 free_dns_rr(head);
419 return (NULL);
420 }
421 curr->name = strdup(name);
422 if (curr->name == NULL) {
423 free_dns_rr(head);
424 return (NULL);
425 }
426 *cp += length;
427
428 /* type */
429 curr->type = _getshort(*cp);
430 *cp += INT16SZ;
431
432 /* class */
433 curr->class = _getshort(*cp);
434 *cp += INT16SZ;
435
436 /* ttl */
437 curr->ttl = _getlong(*cp);
438 *cp += INT32SZ;
439
440 /* rdata size */
441 curr->size = _getshort(*cp);
442 *cp += INT16SZ;
443
444 /* rdata itself */
445 curr->rdata = malloc(curr->size);
446 if (curr->rdata == NULL) {
447 free_dns_rr(head);
448 return (NULL);
449 }
450 memcpy(curr->rdata, *cp, curr->size);
451 *cp += curr->size;
452 }
453
454 return (head);
455}
456
457static void
458free_dns_query(struct dns_query *p)
459{
460 if (p == NULL)
461 return;
462
463 if (p->name)
464 free(p->name);
465 free_dns_query(p->next);
466 free(p);
467}
468
469static void
470free_dns_rr(struct dns_rr *p)
471{
472 if (p == NULL)
473 return;
474
475 if (p->name)
476 free(p->name);
477 if (p->rdata)
478 free(p->rdata);
479 free_dns_rr(p->next);
480 free(p);
481}
482
483static void
484free_dns_response(struct dns_response *p)
485{
486 if (p == NULL)
487 return;
488
489 free_dns_query(p->query);
490 free_dns_rr(p->answer);
491 free_dns_rr(p->authority);
492 free_dns_rr(p->additional);
493 free(p);
494}
495
496static int
497count_dns_rr(struct dns_rr *p, u_int16_t class, u_int16_t type)
498{
499 int n = 0;
500
501 while(p) {
502 if (p->class == class && p->type == type)
503 n++;
504 p = p->next;
505 }
506
507 return (n);
508}
diff --git a/src/lib/libc/net/getservbyname.c b/src/lib/libc/net/getservbyname.c
new file mode 100644
index 0000000000..16602cc3a6
--- /dev/null
+++ b/src/lib/libc/net/getservbyname.c
@@ -0,0 +1,87 @@
1/*
2 * Copyright (c) 1983, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#if defined(LIBC_SCCS) && !defined(lint)
35static char rcsid[] = "$OpenBSD: getservbyname.c,v 1.5 2000/01/06 08:24:17 d Exp $";
36#endif /* LIBC_SCCS and not lint */
37
38#include <netdb.h>
39#include <string.h>
40#include "thread_private.h"
41
42extern int _serv_stayopen;
43
44_THREAD_PRIVATE_MUTEX(getservbyname_r);
45
46struct servent *
47getservbyname_r(name, proto, se, buf, buflen)
48 const char *name, *proto;
49 struct servent *se;
50 char *buf;
51 int buflen;
52{
53 register struct servent *p;
54 register char **cp;
55
56 _THREAD_PRIVATE_MUTEX_LOCK(getservbyname_r);
57 setservent(_serv_stayopen);
58 while ((p = getservent())) {
59 if (strcmp(name, p->s_name) == 0)
60 goto gotname;
61 for (cp = p->s_aliases; *cp; cp++)
62 if (strcmp(name, *cp) == 0)
63 goto gotname;
64 continue;
65gotname:
66 if (proto == 0 || strcmp(p->s_proto, proto) == 0)
67 break;
68 }
69 if (!_serv_stayopen)
70 endservent();
71 _THREAD_PRIVATE_MUTEX_UNLOCK(getservbyname_r);
72 return (p);
73}
74
75struct servent *getservbyname(name, proto)
76 const char *name, *proto;
77{
78 _THREAD_PRIVATE_KEY(getservbyname);
79 static char buf[4096];
80 char *bufp = (char*)_THREAD_PRIVATE(getservbyname, buf, NULL);
81
82 if (bufp == NULL)
83 return (NULL);
84 return getservbyname_r(name, proto, (struct servent*) bufp,
85 bufp + sizeof(struct servent),
86 sizeof buf - sizeof(struct servent) );
87}
diff --git a/src/lib/libc/net/getservbyport.c b/src/lib/libc/net/getservbyport.c
new file mode 100644
index 0000000000..4b063760d2
--- /dev/null
+++ b/src/lib/libc/net/getservbyport.c
@@ -0,0 +1,60 @@
1/*
2 * Copyright (c) 1983, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#if defined(LIBC_SCCS) && !defined(lint)
35static char rcsid[] = "$OpenBSD: getservbyport.c,v 1.3 1997/07/09 01:08:35 millert Exp $";
36#endif /* LIBC_SCCS and not lint */
37
38#include <netdb.h>
39#include <string.h>
40
41extern int _serv_stayopen;
42
43struct servent *
44getservbyport(port, proto)
45 int port;
46 const char *proto;
47{
48 register struct servent *p;
49
50 setservent(_serv_stayopen);
51 while ((p = getservent())) {
52 if (p->s_port != port)
53 continue;
54 if (proto == 0 || strcmp(p->s_proto, proto) == 0)
55 break;
56 }
57 if (!_serv_stayopen)
58 endservent();
59 return (p);
60}
diff --git a/src/lib/libc/net/getservent.3 b/src/lib/libc/net/getservent.3
new file mode 100644
index 0000000000..85e0d65352
--- /dev/null
+++ b/src/lib/libc/net/getservent.3
@@ -0,0 +1,141 @@
1.\" $OpenBSD: getservent.3,v 1.11 2000/12/24 00:30:56 aaron Exp $
2.\"
3.\" Copyright (c) 1983, 1991, 1993
4.\" The Regents of the University of California. All rights reserved.
5.\"
6.\" Redistribution and use in source and binary forms, with or without
7.\" modification, are permitted provided that the following conditions
8.\" are met:
9.\" 1. Redistributions of source code must retain the above copyright
10.\" notice, this list of conditions and the following disclaimer.
11.\" 2. Redistributions in binary form must reproduce the above copyright
12.\" notice, this list of conditions and the following disclaimer in the
13.\" documentation and/or other materials provided with the distribution.
14.\" 3. All advertising materials mentioning features or use of this software
15.\" must display the following acknowledgement:
16.\" This product includes software developed by the University of
17.\" California, Berkeley and its contributors.
18.\" 4. Neither the name of the University nor the names of its contributors
19.\" may be used to endorse or promote products derived from this software
20.\" without specific prior written permission.
21.\"
22.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32.\" SUCH DAMAGE.
33.\"
34.Dd January 12, 1994
35.Dt GETSERVENT 3
36.Os
37.Sh NAME
38.Nm getservent ,
39.Nm getservbyport ,
40.Nm getservbyname ,
41.Nm setservent ,
42.Nm endservent
43.Nd get service entry
44.Sh SYNOPSIS
45.Fd #include <netdb.h>
46.Ft struct servent *
47.Fn getservent "void"
48.Ft struct servent *
49.Fn getservbyname "char *name" "char *proto"
50.Ft struct servent *
51.Fn getservbyport "int port" "char *proto"
52.Ft void
53.Fn setservent "int stayopen"
54.Ft void
55.Fn endservent "void"
56.Sh DESCRIPTION
57The
58.Fn getservent ,
59.Fn getservbyname ,
60and
61.Fn getservbyport
62functions each return a pointer to an object with the following structure
63containing the broken-out fields of a line in the network services database,
64.Pa /etc/services .
65.Bd -literal -offset indent
66struct servent {
67 char *s_name; /* official name of service */
68 char **s_aliases; /* alias list */
69 int s_port; /* port service resides at */
70 char *s_proto; /* protocol to use */
71};
72.Ed
73.Pp
74The members of this structure are:
75.Bl -tag -width s_aliases
76.It Fa s_name
77The official name of the service.
78.It Fa s_aliases
79A zero-terminated list of alternate names for the service.
80.It Fa s_port
81The port number at which the service resides.
82Port numbers are returned in network byte order.
83.It Fa s_proto
84The name of the protocol to use when contacting the service.
85.El
86.Pp
87The
88.Fn getservent
89function reads the next line of the file, opening the file if necessary.
90.Pp
91The
92.Fn setservent
93function opens and rewinds the file.
94If the
95.Fa stayopen
96flag is non-zero,
97the net database will not be closed after each call to
98.Fn getservbyname
99or
100.Fn getservbyport .
101.Pp
102The
103.Fn endservent
104function closes the file.
105.Pp
106The
107.Fn getservbyname
108and
109.Fn getservbyport
110functions sequentially search from the beginning of the file until a
111matching protocol name or port number (specified in network byte order)
112is found, or until
113.Dv EOF
114is encountered.
115If a protocol name is also supplied (non-null),
116searches must also match the protocol.
117.Sh FILES
118.Bl -tag -width /etc/services -compact
119.It Pa /etc/services
120.El
121.Sh DIAGNOSTICS
122Null pointer (0) returned on
123.Dv EOF
124or error.
125.Sh SEE ALSO
126.Xr getprotoent 3 ,
127.Xr services 5
128.Sh HISTORY
129The
130.Fn getservent ,
131.Fn getservbyport ,
132.Fn getservbyname ,
133.Fn setservent ,
134and
135.Fn endservent
136functions appeared in
137.Bx 4.2 .
138.Sh BUGS
139These functions use static data storage; if the data is needed for future use,
140it should be copied before any subsequent calls overwrite it.
141Expecting port numbers to fit in a 32-bit quantity is probably naive.
diff --git a/src/lib/libc/net/getservent.c b/src/lib/libc/net/getservent.c
new file mode 100644
index 0000000000..ff6bf1e57f
--- /dev/null
+++ b/src/lib/libc/net/getservent.c
@@ -0,0 +1,129 @@
1/*
2 * Copyright (c) 1983, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#if defined(LIBC_SCCS) && !defined(lint)
35static char rcsid[] = "$OpenBSD: getservent.c,v 1.5 1999/09/03 16:23:19 millert Exp $";
36#endif /* LIBC_SCCS and not lint */
37
38#include <sys/types.h>
39#include <sys/socket.h>
40#include <netdb.h>
41#include <stdio.h>
42#include <string.h>
43#include <stdlib.h>
44
45#define MAXALIASES 35
46
47static FILE *servf = NULL;
48static char line[BUFSIZ+1];
49static struct servent serv;
50static char *serv_aliases[MAXALIASES];
51int _serv_stayopen;
52
53void
54setservent(f)
55 int f;
56{
57 if (servf == NULL)
58 servf = fopen(_PATH_SERVICES, "r" );
59 else
60 rewind(servf);
61 _serv_stayopen |= f;
62}
63
64void
65endservent()
66{
67 if (servf) {
68 fclose(servf);
69 servf = NULL;
70 }
71 _serv_stayopen = 0;
72}
73
74struct servent *
75getservent()
76{
77 char *p, *cp, **q, *endp;
78 long l;
79 size_t len;
80
81 if (servf == NULL && (servf = fopen(_PATH_SERVICES, "r" )) == NULL)
82 return (NULL);
83again:
84 if ((p = fgetln(servf, &len)) == NULL)
85 return (NULL);
86 if (p[len-1] == '\n')
87 len--;
88 if (len >= sizeof(line) || len == 0)
89 goto again;
90 p = memcpy(line, p, len);
91 line[len] = '\0';
92 if (*p == '#')
93 goto again;
94 if ((cp = strchr(p, '#')) != NULL)
95 *cp = '\0';
96 serv.s_name = p;
97 p = strpbrk(p, " \t");
98 if (p == NULL)
99 goto again;
100 *p++ = '\0';
101 while (*p == ' ' || *p == '\t')
102 p++;
103 cp = strpbrk(p, ",/");
104 if (cp == NULL)
105 goto again;
106 *cp++ = '\0';
107 l = strtol(p, &endp, 10);
108 if (endp == p || *endp != '\0' || l < 0 || l > USHRT_MAX)
109 goto again;
110 serv.s_port = htons((in_port_t)l);
111 serv.s_proto = cp;
112 q = serv.s_aliases = serv_aliases;
113 cp = strpbrk(cp, " \t");
114 if (cp != NULL)
115 *cp++ = '\0';
116 while (cp && *cp) {
117 if (*cp == ' ' || *cp == '\t') {
118 cp++;
119 continue;
120 }
121 if (q < &serv_aliases[MAXALIASES - 1])
122 *q++ = cp;
123 cp = strpbrk(cp, " \t");
124 if (cp != NULL)
125 *cp++ = '\0';
126 }
127 *q = NULL;
128 return (&serv);
129}
diff --git a/src/lib/libc/net/herror.c b/src/lib/libc/net/herror.c
new file mode 100644
index 0000000000..737bb115a7
--- /dev/null
+++ b/src/lib/libc/net/herror.c
@@ -0,0 +1,121 @@
1/* $OpenBSD: herror.c,v 1.4 1997/03/13 19:07:28 downsj Exp $ */
2
3/*
4 * ++Copyright++ 1987, 1993
5 * -
6 * Copyright (c) 1987, 1993
7 * The Regents of the University of California. All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by the University of
20 * California, Berkeley and its contributors.
21 * 4. Neither the name of the University nor the names of its contributors
22 * may be used to endorse or promote products derived from this software
23 * without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
36 * -
37 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
38 *
39 * Permission to use, copy, modify, and distribute this software for any
40 * purpose with or without fee is hereby granted, provided that the above
41 * copyright notice and this permission notice appear in all copies, and that
42 * the name of Digital Equipment Corporation not be used in advertising or
43 * publicity pertaining to distribution of the document or software without
44 * specific, written prior permission.
45 *
46 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
47 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
48 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
49 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
50 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
51 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
52 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
53 * SOFTWARE.
54 * -
55 * --Copyright--
56 */
57
58#if defined(LIBC_SCCS) && !defined(lint)
59#if 0
60static char sccsid[] = "@(#)herror.c 8.1 (Berkeley) 6/4/93";
61static char rcsid[] = "$From: herror.c,v 8.3 1996/08/05 08:31:35 vixie Exp $";
62#else
63static char rcsid[] = "$OpenBSD: herror.c,v 1.4 1997/03/13 19:07:28 downsj Exp $";
64#endif
65#endif /* LIBC_SCCS and not lint */
66
67#include <sys/types.h>
68#include <sys/param.h>
69#include <sys/uio.h>
70#include <netdb.h>
71#include <unistd.h>
72#include <string.h>
73
74const char *h_errlist[] = {
75 "Resolver Error 0 (no error)",
76 "Unknown host", /* 1 HOST_NOT_FOUND */
77 "Host name lookup failure", /* 2 TRY_AGAIN */
78 "Unknown server error", /* 3 NO_RECOVERY */
79 "No address associated with name", /* 4 NO_ADDRESS */
80};
81int h_nerr = { sizeof h_errlist / sizeof h_errlist[0] };
82
83extern int h_errno;
84
85/*
86 * herror --
87 * print the error indicated by the h_errno value.
88 */
89void
90herror(s)
91 const char *s;
92{
93 struct iovec iov[4];
94 register struct iovec *v = iov;
95
96 if (s && *s) {
97 v->iov_base = (char *)s;
98 v->iov_len = strlen(s);
99 v++;
100 v->iov_base = ": ";
101 v->iov_len = 2;
102 v++;
103 }
104 v->iov_base = (char *)hstrerror(h_errno);
105 v->iov_len = strlen(v->iov_base);
106 v++;
107 v->iov_base = "\n";
108 v->iov_len = 1;
109 writev(STDERR_FILENO, iov, (v - iov) + 1);
110}
111
112const char *
113hstrerror(err)
114 int err;
115{
116 if (err < 0)
117 return ("Resolver internal error");
118 else if (err < h_nerr)
119 return (h_errlist[err]);
120 return ("Unknown resolver error");
121}
diff --git a/src/lib/libc/net/htonl.c b/src/lib/libc/net/htonl.c
new file mode 100644
index 0000000000..73b7432731
--- /dev/null
+++ b/src/lib/libc/net/htonl.c
@@ -0,0 +1,25 @@
1/*
2 * Written by J.T. Conklin <jtc@netbsd.org>.
3 * Public domain.
4 */
5
6#if defined(LIBC_SCCS) && !defined(lint)
7static char *rcsid = "$OpenBSD: htonl.c,v 1.4 1996/12/12 03:19:55 tholo Exp $";
8#endif /* LIBC_SCCS and not lint */
9
10#include <sys/types.h>
11#include <machine/endian.h>
12
13#undef htonl
14
15u_int32_t
16htonl(x)
17 u_int32_t x;
18{
19#if BYTE_ORDER == LITTLE_ENDIAN
20 u_char *s = (u_char *)&x;
21 return (u_int32_t)(s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3]);
22#else
23 return x;
24#endif
25}
diff --git a/src/lib/libc/net/htons.c b/src/lib/libc/net/htons.c
new file mode 100644
index 0000000000..ded70712ea
--- /dev/null
+++ b/src/lib/libc/net/htons.c
@@ -0,0 +1,24 @@
1/*
2 * Written by J.T. Conklin <jtc@netbsd.org>.
3 * Public domain.
4 */
5
6#if defined(LIBC_SCCS) && !defined(lint)
7static char *rcsid = "$OpenBSD: htons.c,v 1.7 2002/02/19 19:39:36 millert Exp $";
8#endif /* LIBC_SCCS and not lint */
9
10#include <sys/types.h>
11#include <machine/endian.h>
12
13#undef htons
14
15u_int16_t
16htons(u_int16_t x)
17{
18#if BYTE_ORDER == LITTLE_ENDIAN
19 u_char *s = (u_char *) &x;
20 return (u_int16_t)(s[0] << 8 | s[1]);
21#else
22 return x;
23#endif
24}
diff --git a/src/lib/libc/net/if_indextoname.3 b/src/lib/libc/net/if_indextoname.3
new file mode 100644
index 0000000000..85269c3769
--- /dev/null
+++ b/src/lib/libc/net/if_indextoname.3
@@ -0,0 +1,140 @@
1.\" $OpenBSD: if_indextoname.3,v 1.5 2002/03/07 22:41:12 millert Exp $
2.\" Copyright (c) 1983, 1991, 1993
3.\" The Regents of the University of California. All rights reserved.
4.\"
5.\" Redistribution and use in source and binary forms, with or without
6.\" modification, are permitted provided that the following conditions
7.\" are met:
8.\" 1. Redistributions of source code must retain the above copyright
9.\" notice, this list of conditions and the following disclaimer.
10.\" 2. Redistributions in binary form must reproduce the above copyright
11.\" notice, this list of conditions and the following disclaimer in the
12.\" documentation and/or other materials provided with the distribution.
13.\" 3. All advertising materials mentioning features or use of this software
14.\" must display the following acknowledgement:
15.\" This product includes software developed by the University of
16.\" California, Berkeley and its contributors.
17.\" 4. Neither the name of the University nor the names of its contributors
18.\" may be used to endorse or promote products derived from this software
19.\" without specific prior written permission.
20.\"
21.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31.\" SUCH DAMAGE.
32.\"
33.\" From: @(#)rcmd.3 8.1 (Berkeley) 6/4/93
34.\"
35.Dd May 21, 1998
36.Dt IF_NAMETOINDEX 3
37.Os
38.Sh NAME
39.Nm if_nametoindex ,
40.Nm if_indextoname ,
41.Nm if_nameindex ,
42.Nm if_freenameindex
43.Nd convert interface index to name, and vice versa
44.Sh SYNOPSIS
45.Fd #include <net/if.h>
46.Ft "unsigned int"
47.Fn if_nametoindex "const char *ifname"
48.Ft "char *"
49.Fn if_indextoname "unsigned int ifindex" "char *ifname"
50.Ft "struct if_nameindex *"
51.Fn if_nameindex "void"
52.Ft "void"
53.Fn if_freenameindex "struct if_nameindex *ptr"
54.Sh DESCRIPTION
55These functions map interface indexes to interface names (such as
56.Dq lo0 ) ,
57and vice versa.
58.Pp
59The
60.Fn if_nametoindex
61function converts an interface name specified by the
62.Fa ifname
63argument to an interface index (positive integer value).
64If the specified interface does not exist, 0 will be returned.
65.Pp
66.Fn if_indextoname
67converts an interface index specified by the
68.Fa ifindex
69argument to an interface name.
70The
71.Fa ifname
72argument must point to a buffer of at least
73.Dv IF_NAMESIZE
74bytes into which the interface name corresponding to the specified index is
75returned.
76.Pf ( Dv IF_NAMESIZE
77is also defined in
78.Aq Pa net/if.h
79and its value includes a terminating null byte at the end of the
80interface name.)
81This pointer is also the return value of the function.
82If there is no interface corresponding to the specified index,
83.Dv NULL
84is returned.
85.Pp
86.Fn if_nameindex
87returns an array of
88.Fa if_nameindex
89structures.
90.Fa if_nametoindex
91is also defined in
92.Aq Pa net/if.h ,
93and is as follows:
94.Bd -literal -offset
95struct if_nameindex {
96 unsigned int if_index; /* 1, 2, ... */
97 char *if_name; /* null terminated name: "le0", ... */
98};
99.Ed
100.Pp
101The end of the array of structures is indicated by a structure with
102an
103.Fa if_index
104of 0 and an
105.Fa if_name
106of
107.Dv NULL .
108The function returns a null pointer on error.
109The memory used for this array of structures along with the interface
110names pointed to by the
111.Fa if_name
112members is obtained dynamically.
113This memory is freed by the
114.Fn if_freenameindex
115function.
116.Pp
117.Fn if_freenameindex
118takes a pointer that was returned by
119.Fn if_nameindex
120as argument
121.Pq Fa ptr ,
122and it reclaims the region allocated.
123.Sh DIAGNOSTICS
124.Fn if_nametoindex
125returns 0 on error, positive integer on success.
126.Fn if_indextoname
127and
128.Fn if_nameindex
129return
130.Dv NULL
131on errors.
132.Sh SEE ALSO
133.Xr getifaddrs 3 ,
134.Xr networking 4
135.Pp
136R. Gilligan, S. Thomson, J. Bound, and W. Stevens,
137``Basic Socket Interface Extensions for IPv6,'' RFC2553, March 1999.
138.Sh STANDARDS
139These functions are defined in ``Basic Socket Interface Extensions for IPv6''
140.Pq RFC2533 .
diff --git a/src/lib/libc/net/if_indextoname.c b/src/lib/libc/net/if_indextoname.c
new file mode 100644
index 0000000000..f99e52e387
--- /dev/null
+++ b/src/lib/libc/net/if_indextoname.c
@@ -0,0 +1,86 @@
1/* $OpenBSD: if_indextoname.c,v 1.9 2002/03/07 22:40:23 millert Exp $ */
2/* $KAME: if_indextoname.c,v 1.6 2000/11/07 22:33:25 jinmei Exp $ */
3
4/*-
5 * Copyright (c) 1997, 2000
6 * Berkeley Software Design, Inc. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 *
14 * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * BSDI Id: if_indextoname.c,v 2.3 2000/04/17 22:38:05 dab Exp
27 */
28
29#include <sys/types.h>
30#include <sys/socket.h>
31#include <net/if_dl.h>
32#include <net/if.h>
33#include <ifaddrs.h>
34#include <stdlib.h>
35#include <string.h>
36#include <errno.h>
37
38/*
39 * From RFC 2533:
40 *
41 * The second function maps an interface index into its corresponding
42 * name.
43 *
44 * #include <net/if.h>
45 *
46 * char *if_indextoname(unsigned int ifindex, char *ifname);
47 *
48 * The ifname argument must point to a buffer of at least IF_NAMESIZE
49 * bytes into which the interface name corresponding to the specified
50 * index is returned. (IF_NAMESIZE is also defined in <net/if.h> and
51 * its value includes a terminating null byte at the end of the
52 * interface name.) This pointer is also the return value of the
53 * function. If there is no interface corresponding to the specified
54 * index, NULL is returned, and errno is set to ENXIO, if there was a
55 * system error (such as running out of memory), if_indextoname returns
56 * NULL and errno would be set to the proper value (e.g., ENOMEM).
57 */
58
59char *
60if_indextoname(unsigned int ifindex, char *ifname)
61{
62 struct ifaddrs *ifaddrs, *ifa;
63 int error = 0;
64
65 if (getifaddrs(&ifaddrs) < 0)
66 return(NULL); /* getifaddrs properly set errno */
67
68 for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
69 if (ifa->ifa_addr &&
70 ifa->ifa_addr->sa_family == AF_LINK &&
71 ifindex == ((struct sockaddr_dl*)ifa->ifa_addr)->sdl_index)
72 break;
73 }
74
75 if (ifa == NULL) {
76 error = ENXIO;
77 ifname = NULL;
78 }
79 else
80 strlcpy(ifname, ifa->ifa_name, IFNAMSIZ);
81
82 freeifaddrs(ifaddrs);
83
84 errno = error;
85 return(ifname);
86}
diff --git a/src/lib/libc/net/if_nameindex.c b/src/lib/libc/net/if_nameindex.c
new file mode 100644
index 0000000000..3675a2a450
--- /dev/null
+++ b/src/lib/libc/net/if_nameindex.c
@@ -0,0 +1,140 @@
1/* $OpenBSD: if_nameindex.c,v 1.9 2002/03/07 22:40:23 millert Exp $ */
2/* $KAME: if_nameindex.c,v 1.7 2000/11/24 08:17:20 itojun Exp $ */
3
4/*-
5 * Copyright (c) 1997, 2000
6 * Berkeley Software Design, Inc. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 *
14 * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * BSDI Id: if_nameindex.c,v 2.3 2000/04/17 22:38:05 dab Exp
27 */
28
29#include <sys/types.h>
30#include <sys/socket.h>
31#include <net/if_dl.h>
32#include <net/if.h>
33#include <ifaddrs.h>
34#include <stdlib.h>
35#include <string.h>
36
37/*
38 * From RFC 2553:
39 *
40 * 4.3 Return All Interface Names and Indexes
41 *
42 * The if_nameindex structure holds the information about a single
43 * interface and is defined as a result of including the <net/if.h>
44 * header.
45 *
46 * struct if_nameindex {
47 * unsigned int if_index;
48 * char *if_name;
49 * };
50 *
51 * The final function returns an array of if_nameindex structures, one
52 * structure per interface.
53 *
54 * struct if_nameindex *if_nameindex(void);
55 *
56 * The end of the array of structures is indicated by a structure with
57 * an if_index of 0 and an if_name of NULL. The function returns a NULL
58 * pointer upon an error, and would set errno to the appropriate value.
59 *
60 * The memory used for this array of structures along with the interface
61 * names pointed to by the if_name members is obtained dynamically.
62 * This memory is freed by the next function.
63 *
64 * 4.4. Free Memory
65 *
66 * The following function frees the dynamic memory that was allocated by
67 * if_nameindex().
68 *
69 * #include <net/if.h>
70 *
71 * void if_freenameindex(struct if_nameindex *ptr);
72 *
73 * The argument to this function must be a pointer that was returned by
74 * if_nameindex().
75 */
76
77struct if_nameindex *
78if_nameindex(void)
79{
80 struct ifaddrs *ifaddrs, *ifa;
81 unsigned int ni;
82 size_t nbytes;
83 struct if_nameindex *ifni, *ifni2;
84 char *cp;
85
86 if (getifaddrs(&ifaddrs) < 0)
87 return(NULL);
88
89 /*
90 * First, find out how many interfaces there are, and how
91 * much space we need for the string names.
92 */
93 ni = 0;
94 nbytes = 0;
95 for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
96 if (ifa->ifa_addr &&
97 ifa->ifa_addr->sa_family == AF_LINK) {
98 nbytes += strlen(ifa->ifa_name) + 1;
99 ni++;
100 }
101 }
102
103 /*
104 * Next, allocate a chunk of memory, use the first part
105 * for the array of structures, and the last part for
106 * the strings.
107 */
108 cp = malloc((ni + 1) * sizeof(struct if_nameindex) + nbytes);
109 ifni = (struct if_nameindex *)cp;
110 if (ifni == NULL)
111 goto out;
112 cp += (ni + 1) * sizeof(struct if_nameindex);
113
114 /*
115 * Now just loop through the list of interfaces again,
116 * filling in the if_nameindex array and making copies
117 * of all the strings.
118 */
119 ifni2 = ifni;
120 for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
121 if (ifa->ifa_addr &&
122 ifa->ifa_addr->sa_family == AF_LINK) {
123 ifni2->if_index =
124 ((struct sockaddr_dl*)ifa->ifa_addr)->sdl_index;
125 ifni2->if_name = cp;
126 nbytes = strlen(ifa->ifa_name) + 1;
127 memcpy(cp, ifa->ifa_name, nbytes);
128 ifni2++;
129 cp += nbytes;
130 }
131 }
132 /*
133 * Finally, don't forget to terminate the array.
134 */
135 ifni2->if_index = 0;
136 ifni2->if_name = NULL;
137out:
138 freeifaddrs(ifaddrs);
139 return(ifni);
140}
diff --git a/src/lib/libc/net/if_nametoindex.c b/src/lib/libc/net/if_nametoindex.c
new file mode 100644
index 0000000000..8bd792b949
--- /dev/null
+++ b/src/lib/libc/net/if_nametoindex.c
@@ -0,0 +1,81 @@
1/* $OpenBSD: if_nametoindex.c,v 1.8 2002/03/07 22:40:23 millert Exp $ */
2/* $KAME: if_nametoindex.c,v 1.5 2000/11/24 08:04:40 itojun Exp $ */
3
4/*-
5 * Copyright (c) 1997, 2000
6 * Berkeley Software Design, Inc. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 *
14 * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * BSDI Id: if_nametoindex.c,v 2.3 2000/04/17 22:38:05 dab Exp
27 */
28
29#include <sys/types.h>
30#include <sys/socket.h>
31#include <net/if.h>
32#include <net/if_dl.h>
33#include <ifaddrs.h>
34#include <stdlib.h>
35#include <string.h>
36#include <errno.h>
37
38/*
39 * From RFC 2553:
40 *
41 * 4.1 Name-to-Index
42 *
43 *
44 * The first function maps an interface name into its corresponding
45 * index.
46 *
47 * #include <net/if.h>
48 *
49 * unsigned int if_nametoindex(const char *ifname);
50 *
51 * If the specified interface name does not exist, the return value is
52 * 0, and errno is set to ENXIO. If there was a system error (such as
53 * running out of memory), the return value is 0 and errno is set to the
54 * proper value (e.g., ENOMEM).
55 */
56
57unsigned int
58if_nametoindex(const char *ifname)
59{
60 struct ifaddrs *ifaddrs, *ifa;
61 unsigned int ni;
62
63 if (getifaddrs(&ifaddrs) < 0)
64 return(0);
65
66 ni = 0;
67
68 for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
69 if (ifa->ifa_addr &&
70 ifa->ifa_addr->sa_family == AF_LINK &&
71 strcmp(ifa->ifa_name, ifname) == 0) {
72 ni = ((struct sockaddr_dl*)ifa->ifa_addr)->sdl_index;
73 break;
74 }
75 }
76
77 freeifaddrs(ifaddrs);
78 if (!ni)
79 errno = ENXIO;
80 return(ni);
81}
diff --git a/src/lib/libc/net/inet.3 b/src/lib/libc/net/inet.3
new file mode 100644
index 0000000000..62f526c09d
--- /dev/null
+++ b/src/lib/libc/net/inet.3
@@ -0,0 +1,349 @@
1.\" $OpenBSD: inet.3,v 1.13 2001/02/17 23:13:26 pjanzen Exp $
2.\" $NetBSD: inet.3,v 1.7 1997/06/18 02:25:24 lukem Exp $
3.\"
4.\" Copyright (c) 1983, 1990, 1991, 1993
5.\" The Regents of the University of California. All rights reserved.
6.\"
7.\" Redistribution and use in source and binary forms, with or without
8.\" modification, are permitted provided that the following conditions
9.\" are met:
10.\" 1. Redistributions of source code must retain the above copyright
11.\" notice, this list of conditions and the following disclaimer.
12.\" 2. Redistributions in binary form must reproduce the above copyright
13.\" notice, this list of conditions and the following disclaimer in the
14.\" documentation and/or other materials provided with the distribution.
15.\" 3. All advertising materials mentioning features or use of this software
16.\" must display the following acknowledgement:
17.\" This product includes software developed by the University of
18.\" California, Berkeley and its contributors.
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.\" @(#)inet.3 8.1 (Berkeley) 6/4/93
36.\"
37.Dd June 18, 1997
38.Dt INET 3
39.Os
40.Sh NAME
41.Nm inet_addr ,
42.Nm inet_aton ,
43.Nm inet_lnaof ,
44.Nm inet_makeaddr ,
45.Nm inet_netof ,
46.Nm inet_network ,
47.Nm inet_ntoa ,
48.Nm inet_ntop ,
49.Nm inet_pton
50.Nd Internet address manipulation routines
51.Sh SYNOPSIS
52.Fd #include <sys/socket.h>
53.Fd #include <netinet/in.h>
54.Fd #include <arpa/inet.h>
55.Ft in_addr_t
56.Fn inet_addr "const char *cp"
57.Ft int
58.Fn inet_aton "const char *cp" "struct in_addr *addr"
59.Ft in_addr_t
60.Fn inet_lnaof "struct in_addr in"
61.Ft struct in_addr
62.Fn inet_makeaddr "unsigned long net" "unsigned long lna"
63.Ft in_addr_t
64.Fn inet_netof "struct in_addr in"
65.Ft in_addr_t
66.Fn inet_network "const char *cp"
67.Ft char *
68.Fn inet_ntoa "struct in_addr in"
69.Ft const char *
70.Fn inet_ntop "int af" "const void *src" "char *dst" "size_t size"
71.Ft int
72.Fn inet_pton "int af" "const char *src" "void *dst"
73.Sh DESCRIPTION
74The routines
75.Fn inet_aton ,
76.Fn inet_addr
77and
78.Fn inet_network
79interpret character strings representing
80numbers expressed in the Internet standard
81.Ql \&.
82notation.
83The
84.Fn inet_pton
85function converts a presentation format address (that is, printable form
86as held in a character string) to network format (usually a
87.Li struct in_addr
88or some other internal binary representation, in network byte order).
89It returns 1 if the address was valid for the specified address family, or
900 if the address wasn't parseable in the specified address family, or \-1
91if some system error occurred (in which case
92.Va errno
93will have been set).
94This function is presently valid for
95.Dv AF_INET
96and
97.Dv AF_INET6 .
98The
99.Fn inet_aton
100routine interprets the specified character string as an Internet address,
101placing the address into the structure provided.
102It returns 1 if the string was successfully interpreted,
103or 0 if the string was invalid.
104The
105.Fn inet_addr
106and
107.Fn inet_network
108functions return numbers suitable for use
109as Internet addresses and Internet network
110numbers, respectively.
111.Pp
112The function
113.Fn inet_ntop
114converts an address from network format (usually a
115.Li struct in_addr
116or some other binary form, in network byte order) to presentation format
117(suitable for external display purposes).
118It returns
119.Dv NULL
120if a system
121error occurs (in which case,
122.Va errno
123will have been set), or it returns a pointer to the destination string.
124The routine
125.Fn inet_ntoa
126takes an Internet address and returns an
127.Tn ASCII
128string representing the address in
129.Ql \&.
130notation.
131The routine
132.Fn inet_makeaddr
133takes an Internet network number and a local
134network address and constructs an Internet address
135from it.
136The routines
137.Fn inet_netof
138and
139.Fn inet_lnaof
140break apart Internet host addresses, returning
141the network number and local network address part,
142respectively.
143.Pp
144All Internet addresses are returned in network
145order (bytes ordered from left to right).
146All network numbers and local address parts are
147returned as machine format integer values.
148.Sh INTERNET ADDRESSES (IP VERSION 4)
149Values specified using the
150.Ql \&.
151notation take one
152of the following forms:
153.Bd -literal -offset indent
154a.b.c.d
155a.b.c
156a.b
157a
158.Ed
159.Pp
160When four parts are specified, each is interpreted
161as a byte of data and assigned, from left to right,
162to the four bytes of an Internet address.
163Note that when an Internet address is viewed as a 32-bit
164integer quantity on a system that uses little-endian
165byte order (such as the
166.Tn Intel 386, 486
167and
168.Tn Pentium
169processors) the bytes referred to above appear as
170.Dq Li d.c.b.a .
171That is, little-endian bytes are ordered from right to left.
172.Pp
173When a three part address is specified, the last
174part is interpreted as a 16-bit quantity and placed
175in the rightmost two bytes of the network address.
176This makes the three part address format convenient
177for specifying Class B network addresses as
178.Dq Li 128.net.host .
179.Pp
180When a two part address is supplied, the last part
181is interpreted as a 24-bit quantity and placed in
182the rightmost three bytes of the network address.
183This makes the two part address format convenient
184for specifying Class A network addresses as
185.Dq Li net.host .
186.Pp
187When only one part is given, the value is stored
188directly in the network address without any byte
189rearrangement.
190.Pp
191All numbers supplied as
192.Dq parts
193in a
194.Ql \&.
195notation
196may be decimal, octal, or hexadecimal, as specified
197in the C language (i.e., a leading 0x or 0X implies
198hexadecimal; otherwise, a leading 0 implies octal;
199otherwise, the number is interpreted as decimal).
200.Sh INTERNET ADDRESSES (IP VERSION 6)
201In order to support scoped IPv6 addresses,
202.Xr getaddrinfo 3
203and
204.Xr getnameinfo 3
205are recommended rather than the functions presented here.
206.Pp
207The presentation format of an IPv6 address is given in [RFC1884 2.2]:
208.Pp
209There are three conventional forms for representing IPv6 addresses as
210text strings:
211.Bl -enum
212.It
213The preferred form is x:x:x:x:x:x:x:x, where the 'x's are the
214hexadecimal values of the eight 16-bit pieces of the address.
215Examples:
216.Bd -literal -offset indent
217FEDC:BA98:7654:3210:FEDC:BA98:7654:3210
2181080:0:0:0:8:800:200C:417A
219.Ed
220.Pp
221Note that it is not necessary to write the leading zeros in an
222individual field, but there must be at least one numeral in
223every field (except for the case described in 2.).
224.It
225Due to the method of allocating certain styles of IPv6
226addresses, it will be common for addresses to contain long
227strings of zero bits.
228In order to make writing addresses
229.Pp
230containing zero bits easier a special syntax is available to
231compress the zeros.
232The use of
233.Dq \&:\&:
234indicates multiple groups
235of 16 bits of zeros.
236The
237.Dq \&:\&:
238can only appear once in an
239address.
240The
241.Dq \&:\&:
242can also be used to compress the leading and/or trailing zeros in an address.
243.Pp
244For example the following addresses:
245.Bd -literal -offset indent
2461080:0:0:0:8:800:200C:417A a unicast address
247FF01:0:0:0:0:0:0:43 a multicast address
2480:0:0:0:0:0:0:1 the loopback address
2490:0:0:0:0:0:0:0 the unspecified addresses
250.Ed
251.Pp
252may be represented as:
253.Bd -literal -offset indent
2541080::8:800:200C:417A a unicast address
255FF01::43 a multicast address
256::1 the loopback address
257:: the unspecified addresses
258.Ed
259.It
260An alternative form that is sometimes more convenient when
261dealing with a mixed environment of IPv4 and IPv6 nodes is
262x:x:x:x:x:x:d.d.d.d, where the 'x's are the hexadecimal values
263of the six high-order 16-bit pieces of the address, and the 'd's
264are the decimal values of the four low-order 8-bit pieces of the
265address (standard IPv4 representation).
266Examples:
267.Bd -literal -offset indent
2680:0:0:0:0:0:13.1.68.3
2690:0:0:0:0:FFFF:129.144.52.38
270.Ed
271.Pp
272or in compressed form:
273.Bd -literal -offset indent
274::13.1.68.3
275::FFFF:129.144.52.38
276.Ed
277.El
278.Sh DIAGNOSTICS
279The constant
280.Dv INADDR_NONE
281is returned by
282.Fn inet_addr
283and
284.Fn inet_network
285for malformed requests.
286.Sh SEE ALSO
287.Xr byteorder 3 ,
288.Xr gethostbyname 3 ,
289.Xr getnetent 3 ,
290.Xr inet_net 3 ,
291.Xr hosts 5 ,
292.Xr networks 5
293.Sh STANDARDS
294The
295.Nm inet_ntop
296and
297.Nm inet_pton
298functions conforms to the IETF IPv6 BSD API and address formatting
299specifications.
300Note that
301.Nm inet_pton
302does not accept 1-, 2-, or 3-part dotted addresses; all four parts
303must be specified.
304This is a narrower input set than that accepted by
305.Nm inet_aton .
306.Sh HISTORY
307The
308.Nm inet_addr ,
309.Nm inet_network ,
310.Nm inet_makeaddr ,
311.Nm inet_lnaof
312and
313.Nm inet_netof
314functions appeared in
315.Bx 4.2 .
316The
317.Nm inet_aton
318and
319.Nm inet_ntoa
320functions appeared in
321.Bx 4.3 .
322The
323.Nm inet_pton
324and
325.Nm inet_ntop
326functions appeared in BIND 4.9.4.
327.Sh BUGS
328The value
329.Dv INADDR_NONE
330(0xffffffff) is a valid broadcast address, but
331.Fn inet_addr
332cannot return that value without indicating failure.
333Also,
334.Fn inet_addr
335should have been designed to return a
336.Li struct in_addr .
337The newer
338.Fn inet_aton
339function does not share these problems, and almost all existing code
340should be modified to use
341.Fn inet_aton
342instead.
343.Pp
344The problem of host byte ordering versus network byte ordering is
345confusing.
346.Pp
347The string returned by
348.Fn inet_ntoa
349resides in a static memory area.
diff --git a/src/lib/libc/net/inet6_option_space.3 b/src/lib/libc/net/inet6_option_space.3
new file mode 100644
index 0000000000..73419d5239
--- /dev/null
+++ b/src/lib/libc/net/inet6_option_space.3
@@ -0,0 +1,452 @@
1.\" $OpenBSD: inet6_option_space.3,v 1.8 2001/06/23 05:57:04 deraadt Exp $
2.\" $KAME: inet6_option_space.3,v 1.7 2000/05/17 14:32:13 itojun Exp $
3.\"
4.\" Copyright (c) 1983, 1987, 1991, 1993
5.\" The Regents of the University of California. All rights reserved.
6.\"
7.\" Redistribution and use in source and binary forms, with or without
8.\" modification, are permitted provided that the following conditions
9.\" are met:
10.\" 1. Redistributions of source code must retain the above copyright
11.\" notice, this list of conditions and the following disclaimer.
12.\" 2. Redistributions in binary form must reproduce the above copyright
13.\" notice, this list of conditions and the following disclaimer in the
14.\" documentation and/or other materials provided with the distribution.
15.\" 3. All advertising materials mentioning features or use of this software
16.\" must display the following acknowledgement:
17.\" This product includes software developed by the University of
18.\" California, Berkeley and its contributors.
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.Dd December 10, 1999
36.Dt INET6_OPTION_SPACE 3
37.Os
38.\"
39.Sh NAME
40.Nm inet6_option_space ,
41.Nm inet6_option_init ,
42.Nm inet6_option_append ,
43.Nm inet6_option_alloc ,
44.Nm inet6_option_next ,
45.Nm inet6_option_find
46.Nd IPv6 Hop-by-Hop and Destination Options manipulation
47.\"
48.Sh SYNOPSIS
49.Fd #include <netinet/in.h>
50.Ft "int"
51.Fn inet6_option_space "int nbytes"
52.Ft "int"
53.Fn inet6_option_init "void *bp" "struct cmsghdr **cmsgp" "int type"
54.Ft "int"
55.Fn inet6_option_append "struct cmsghdr *cmsg" "const u_int8_t *typep" "int multx" "int plusy"
56.Ft "u_int8_t *"
57.Fn inet6_option_alloc "struct cmsghdr *cmsg" "int datalen" "int multx" "int plusy";
58.Ft "int"
59.Fn inet6_option_next "const struct cmsghdr *cmsg" "u_int8_t **tptrp"
60.Ft "int"
61.Fn inet6_option_find "const struct cmsghdr *cmsg" "u_int8_t **tptrp" "int type"
62.\"
63.Sh DESCRIPTION
64.\"
65Building and parsing the Hop-by-Hop and Destination options is
66complicated due to alignment constranints, padding and
67ancillary data manipulation.
68RFC2292 defines a set of functions to help the application.
69The function prototypes for
70these functions are all in the
71.Aq Li netinet/in.h
72header.
73.\"
74.Ss inet6_option_space
75.Fn inet6_option_space
76returns the number of bytes required to hold an option when it is stored as
77ancillary data, including the
78.Li cmsghdr
79structure at the beginning,
80and any padding at the end
81.Po
82to make its size a multiple of 8 bytes
83.Pc .
84The argument is the size of the structure defining the option,
85which must include any pad bytes at the beginning
86.Po
87the value
88.Li y
89in the alignment term
90.Dq Li xn + y
91.Pc ,
92the type byte, the length byte, and the option data.
93.Pp
94Note: If multiple options are stored in a single ancillary data
95object, which is the recommended technique, this function
96overestimates the amount of space required by the size of
97.Li N-1
98.Li cmsghdr
99structures,
100where
101.Li N
102is the number of options to be stored in the object.
103This is of little consequence, since it is assumed that most
104Hop-by-Hop option headers and Destination option headers carry only
105one option
106.Pq appendix B of [RFC-2460] .
107.\"
108.Ss inet6_option_init
109.Fn inet6_option_init
110is called once per ancillary data object that will
111contain either Hop-by-Hop or Destination options.
112It returns
113.Li 0
114on success or
115.Li -1
116on an error.
117.Pp
118.Fa bp
119is a pointer to previously allocated space that will contain the
120ancillary data object.
121It must be large enough to contain all the
122individual options to be added by later calls to
123.Fn inet6_option_append
124and
125.Fn inet6_option_alloc .
126.Pp
127.Fa cmsgp
128is a pointer to a pointer to a
129.Li cmsghdr
130structure.
131.Fa *cmsgp
132is initialized by this function to point to the
133.Li cmsghdr
134structure constructed by this function in the buffer pointed to by
135.Fa bp .
136.Pp
137.Fa type
138is either
139.Dv IPV6_HOPOPTS
140or
141.Dv IPV6_DSTOPTS .
142This
143.Fa type
144is stored in the
145.Li cmsg_type
146member of the
147.Li cmsghdr
148structure pointed to by
149.Fa *cmsgp .
150.\"
151.Ss inet6_option_append
152This function appends a Hop-by-Hop option or a Destination option
153into an ancillary data object that has been initialized by
154.Fn inet6_option_init .
155This function returns
156.Li 0
157if it succeeds or
158.Li -1
159on an error.
160.Pp
161.Fa cmsg
162is a pointer to the
163.Li cmsghdr
164structure that must have been
165initialized by
166.Fn inet6_option_init .
167.Pp
168.Fa typep
169is a pointer to the 8-bit option type.
170It is assumed that this
171field is immediately followed by the 8-bit option data length field,
172which is then followed immediately by the option data.
173The caller
174initializes these three fields
175.Pq the type-length-value, or TLV
176before calling this function.
177.Pp
178The option type must have a value from
179.Li 2
180to
181.Li 255 ,
182inclusive.
183.Po
184.Li 0
185and
186.Li 1
187are reserved for the
188.Li Pad1
189and
190.Li PadN
191options, respectively.
192.Pc
193.Pp
194The option data length must have a value between
195.Li 0
196and
197.Li 255 ,
198inclusive, and is the length of the option data that follows.
199.Pp
200.Fa multx
201is the value
202.Li x
203in the alignment term
204.Dq Li xn + y .
205It must have a value of
206.Li 1 ,
207.Li 2 ,
208.Li 4 ,
209or
210.Li 8 .
211.Pp
212.Fa plusy
213is the value
214.Li y
215in the alignment term
216.Dq Li xn + y .
217It must have a value between
218.Li 0
219and
220.Li 7 ,
221inclusive.
222.\"
223.Ss inet6_option_alloc
224This function appends a Hop-by-Hop option or a Destination option
225into an ancillary data object that has been initialized by
226.Fn inet6_option_init .
227This function returns a pointer to the 8-bit
228option type field that starts the option on success, or
229.Dv NULL
230on an error.
231.Pp
232The difference between this function and
233.Fn inet6_option_append
234is that the latter copies the contents of a previously built option into
235the ancillary data object while the current function returns a
236pointer to the space in the data object where the option's TLV must
237then be built by the caller.
238.Pp
239.Fa cmsg
240is a pointer to the
241.Li cmsghdr
242structure that must have been
243initialized by
244.Fn inet6_option_init .
245.Pp
246.Fa datalen
247is the value of the option data length byte for this option.
248This value is required as an argument to allow the function to
249determine if padding must be appended at the end of the option.
250.Po
251The
252.Fn inet6_option_append
253function does not need a data length argument
254since the option data length must already be stored by the caller.
255.Pc
256.Pp
257.Fa multx
258is the value
259.Li x
260in the alignment term
261.Dq Li xn + y .
262It must have a value of
263.Li 1 ,
264.Li 2 ,
265.Li 4 ,
266or
267.Li 8 .
268.Pp
269.Fa plusy
270is the value
271.Li y
272in the alignment term
273.Dq Li xn + y .
274It must have a value between
275.Li 0
276and
277.Li 7 ,
278inclusive.
279.\"
280.Ss inet6_option_next
281This function processes the next Hop-by-Hop option or Destination
282option in an ancillary data object.
283If another option remains to be
284processed, the return value of the function is
285.Li 0
286and
287.Fa *tptrp
288points to
289the 8-bit option type field
290.Po
291which is followed by the 8-bit option
292data length, followed by the option data
293.Pc .
294If no more options remain
295to be processed, the return value is
296.Li -1
297and
298.Fa *tptrp
299is
300.Dv NULL .
301If an error occurs, the return value is
302.Li -1
303and
304.Fa *tptrp
305is not
306.Dv NULL .
307.Pp
308.Fa cmsg
309is a pointer to
310.Li cmsghdr
311structure of which
312.Li cmsg_level
313equals
314.Dv IPPROTO_IPV6
315and
316.Li cmsg_type
317equals either
318.Dv IPV6_HOPOPTS
319or
320.Dv IPV6_DSTOPTS .
321.Pp
322.Fa tptrp
323is a pointer to a pointer to an 8-bit byte and
324.Fa *tptrp
325is used
326by the function to remember its place in the ancillary data object
327each time the function is called.
328The first time this function is
329called for a given ancillary data object,
330.Fa *tptrp
331must be set to
332.Dv NULL .
333.Pp
334Each time this function returns success,
335.Fa *tptrp
336points to the 8-bit
337option type field for the next option to be processed.
338.\"
339.Ss inet6_option_find
340This function is similar to the previously described
341.Fn inet6_option_next
342function, except this function lets the caller
343specify the option type to be searched for, instead of always
344returning the next option in the ancillary data object.
345.Fa cmsg
346is a
347pointer to
348.Li cmsghdr
349structure of which
350.Li cmsg_level
351equals
352.Dv IPPROTO_IPV6
353and
354.Li cmsg_type
355equals either
356.Dv IPV6_HOPOPTS
357or
358.Dv IPV6_DSTOPTS .
359.Pp
360.Fa tptrp
361is a pointer to a pointer to an 8-bit byte and
362.Fa *tptrp
363is used
364by the function to remember its place in the ancillary data object
365each time the function is called.
366The first time this function is
367called for a given ancillary data object,
368.Fa *tptrp
369must be set to
370.Dv NULL .
371.Pa
372This function starts searching for an option of the specified type
373beginning after the value of
374.Fa *tptrp .
375If an option of the specified
376type is located, this function returns
377.Li 0
378and
379.Fa *tptrp
380points to the 8-
381bit option type field for the option of the specified type.
382If an
383option of the specified type is not located, the return value is
384.Li -1
385and
386.Fa *tptrp
387is
388.Dv NULL .
389If an error occurs, the return value is
390.Li -1
391and
392.Fa *tptrp
393is not
394.Dv NULL .
395.\"
396.Sh DIAGNOSTICS
397.Fn inet6_option_init
398and
399.Fn inet6_option_append
400return
401.Li 0
402on success or
403.Li -1
404on an error.
405.Pp
406.Fn inet6_option_alloc
407returns
408.Dv NULL
409on an error.
410.Pp
411On errors,
412.Fn inet6_option_next
413and
414.Fn inet6_option_find
415return
416.Li -1
417setting
418.Fa *tptrp
419to non
420.Dv NULL
421value.
422.\"
423.Sh EXAMPLES
424RFC2292 gives comprehensive examples in chapter 6.
425.\"
426.Sh SEE ALSO
427.Rs
428.%A W. Stevens
429.%A M. Thomas
430.%T "Advanced Sockets API for IPv6"
431.%N RFC2292
432.%D February 1998
433.Re
434.Rs
435.%A S. Deering
436.%A R. Hinden
437.%T "Internet Protocol, Version 6 (IPv6) Specification"
438.%N RFC2460
439.%D December 1998
440.Re
441.\"
442.Sh HISTORY
443The implementation first appeared in KAME advanced networking kit.
444.\"
445.Sh STANDARDS
446The functions
447are documented in
448.Dq Advanced Sockets API for IPv6
449.Pq RFC2292 .
450.\"
451.Sh BUGS
452The text was shamelessly copied from RFC2292.
diff --git a/src/lib/libc/net/inet6_rthdr_space.3 b/src/lib/libc/net/inet6_rthdr_space.3
new file mode 100644
index 0000000000..cafe0d2645
--- /dev/null
+++ b/src/lib/libc/net/inet6_rthdr_space.3
@@ -0,0 +1,325 @@
1.\" $OpenBSD: inet6_rthdr_space.3,v 1.8 2001/06/23 05:57:04 deraadt Exp $
2.\" $KAME: inet6_rthdr_space.3,v 1.8 2000/05/17 14:30:15 itojun Exp $
3.\"
4.\" Copyright (c) 1983, 1987, 1991, 1993
5.\" The Regents of the University of California. All rights reserved.
6.\"
7.\" Redistribution and use in source and binary forms, with or without
8.\" modification, are permitted provided that the following conditions
9.\" are met:
10.\" 1. Redistributions of source code must retain the above copyright
11.\" notice, this list of conditions and the following disclaimer.
12.\" 2. Redistributions in binary form must reproduce the above copyright
13.\" notice, this list of conditions and the following disclaimer in the
14.\" documentation and/or other materials provided with the distribution.
15.\" 3. All advertising materials mentioning features or use of this software
16.\" must display the following acknowledgement:
17.\" This product includes software developed by the University of
18.\" California, Berkeley and its contributors.
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.Dd December 10, 1999
36.Dt INET6_RTHDR_SPACE 3
37.Os
38.\"
39.Sh NAME
40.Nm inet6_rthdr_space ,
41.Nm inet6_rthdr_init ,
42.Nm inet6_rthdr_add ,
43.Nm inet6_rthdr_lasthop ,
44.Nm inet6_rthdr_reverse ,
45.Nm inet6_rthdr_segments ,
46.Nm inet6_rthdr_getaddr ,
47.Nm inet6_rthdr_getflags
48.Nd IPv6 Routing Header Options manipulation
49.\"
50.Sh SYNOPSIS
51.Fd #include <netinet/in.h>
52.Ft size_t
53.Fn inet6_rthdr_space "int type" "int segments"
54.Ft "struct cmsghdr *"
55.Fn inet6_rthdr_init "void *bp" "int type"
56.Ft int
57.Fn inet6_rthdr_add "struct cmsghdr *cmsg" "const struct in6_addr *addr" "unsigned int flags"
58.Ft int
59.Fn inet6_rthdr_lasthop "struct cmsghdr *cmsg" "unsigned int flags"
60.Ft int
61.Fn inet6_rthdr_reverse "const struct cmsghdr *in" "struct cmsghdr *out"
62.Ft int
63.Fn inet6_rthdr_segments "const struct cmsghdr *cmsg"
64.Ft "struct in6_addr *"
65.Fn inet6_rthdr_getaddr "struct cmsghdr *cmsg" "int index"
66.Ft int
67.Fn inet6_rthdr_getflags "const struct cmsghdr *cmsg" "int index"
68.\"
69.Sh DESCRIPTION
70RFC2292 IPv6 advanced API defines eight
71functions that the application calls to build and examine a Routing
72header.
73Four functions build a Routing header:
74.Bl -hang
75.It Fn inet6_rthdr_space
76return #bytes required for ancillary data
77.It Fn inet6_rthdr_init
78initialize ancillary data for Routing header
79.It Fn inet6_rthdr_add
80add IPv6 address & flags to Routing header
81.It Fn inet6_rthdr_lasthop
82specify the flags for the final hop
83.El
84.Pp
85Four functions deal with a returned Routing header:
86.Bl -hang
87.It Fn inet6_rthdr_reverse
88reverse a Routing header
89.It Fn inet6_rthdr_segments
90return #segments in a Routing header
91.It Fn inet6_rthdr_getaddr
92fetch one address from a Routing header
93.It Fn inet6_rthdr_getflags
94fetch one flag from a Routing header
95.El
96.Pp
97The function prototypes for these functions are all in the
98.Aq Li netinet/in.h
99header.
100.\"
101.Ss inet6_rthdr_space
102This function returns the number of bytes required to hold a Routing
103header of the specified
104.Fa type
105containing the specified number of
106.Fa segments
107.Pq addresses .
108For an IPv6 Type 0 Routing header, the number
109of segments must be between 1 and 23, inclusive.
110The return value
111includes the size of the cmsghdr structure that precedes the Routing
112header, and any required padding.
113.Pp
114If the return value is 0, then either the type of the Routing header
115is not supported by this implementation or the number of segments is
116invalid for this type of Routing header.
117.Pp
118Note: This function returns the size but does not allocate the space
119required for the ancillary data.
120This allows an application to
121allocate a larger buffer, if other ancillary data objects are
122desired, since all the ancillary data objects must be specified to
123.Xr sendmsg 2
124as a single
125.Li msg_control
126buffer.
127.\"
128.Ss inet6_rthdr_init
129This function initializes the buffer pointed to by
130.Fa bp
131to contain a
132.Li cmsghdr
133structure followed by a Routing header of the specified
134.Fa type .
135The
136.Li cmsg_len
137member of the
138.Li cmsghdr
139structure is initialized to the
140size of the structure plus the amount of space required by the
141Routing header.
142The
143.Li cmsg_level
144and
145.Li cmsg_type
146members are also initialized as required.
147.Pp
148The caller must allocate the buffer and its size can be determined by
149calling
150.Fn inet6_rthdr_space .
151.Pp
152Upon success the return value is the pointer to the
153.Li cmsghdr
154structure, and this is then used as the first argument to the next
155two functions.
156Upon an error the return value is
157.Dv NULL .
158.\"
159.Ss inet6_rthdr_add
160This function adds the address pointed to by
161.Fa addr
162to the end of the
163Routing header being constructed and sets the type of this hop to the
164value of
165.Fa flags .
166For an IPv6 Type 0 Routing header,
167.Fa flags
168must be
169either
170.Dv IPV6_RTHDR_LOOSE
171or
172.Dv IPV6_RTHDR_STRICT .
173.Pp
174If successful, the
175.Li cmsg_len
176member of the
177.Li cmsghdr
178structure is
179updated to account for the new address in the Routing header and the
180return value of the function is 0.
181Upon an error the return value of
182the function is -1.
183.\"
184.Ss inet6_rthdr_lasthop
185This function specifies the Strict/Loose flag for the final hop of a
186Routing header.
187For an IPv6 Type 0 Routing header,
188.Fa flags
189must be either
190.Dv IPV6_RTHDR_LOOSE
191or
192.Dv IPV6_RTHDR_STRICT .
193.Pp
194The return value of the function is 0 upon success, or -1 upon an error.
195.Pp
196Notice that a Routing header specifying
197.Li N
198intermediate nodes requires
199.Li N+1
200Strict/Loose flags.
201This requires
202.Li N
203calls to
204.Fn inet6_rthdr_add
205followed by one call to
206.Fn inet6_rthdr_lasthop .
207.\"
208.Ss inet6_rthdr_reverse
209This function takes a Routing header that was received as ancillary
210data
211.Po
212pointed to by the first argument,
213.Fa in
214.Pc
215and writes a new Routing
216header that sends datagrams along the reverse of that route.
217Both
218arguments are allowed to point to the same buffer
219.Pq that is, the reversal can occur in place .
220.Pp
221The return value of the function is 0 on success, or -1 upon an
222error.
223.\"
224.Ss inet6_rthdr_segments
225This function returns the number of segments
226.Pq addresses
227contained in
228the Routing header described by
229.Fa cmsg .
230On success the return value is
231between 1 and 23, inclusive.
232The return value of the function is -1 upon an error.
233.\"
234.Ss inet6_rthdr_getaddr
235This function returns a pointer to the IPv6 address specified by
236.Fa index
237.Po
238which must have a value between 1 and the value returned by
239.Fn inet6_rthdr_segments
240.Pc
241in the Routing header described by
242.Fa cmsg .
243An
244application should first call
245.Fn inet6_rthdr_segments
246to obtain the number of segments in the Routing header.
247.Pp
248Upon an error the return value of the function is
249.Dv NULL .
250.\"
251.Ss inet6_rthdr_getflags
252This function returns the flags value specified by
253.Fa index
254.Po
255which must
256have a value between 0 and the value returned by
257.Fn inet6_rthdr_segments
258.Pc
259in the Routing header described by
260.Fa cmsg .
261For an IPv6 Type 0 Routing header the return value will be either
262.Dv IPV6_RTHDR_LOOSE
263or
264.Dv IPV6_RTHDR_STRICT .
265.Pp
266Upon an error the return value of the function is -1.
267.Pp
268Note: Addresses are indexed starting at 1, and flags starting at 0,
269to maintain consistency with the terminology and figures in RFC2460.
270.\"
271.Sh DIAGNOSTICS
272.Fn inet6_rthdr_space
273returns 0 on errors.
274.Pp
275.Fn inet6_rthdr_add ,
276.Fn inet6_rthdr_lasthop
277and
278.Fn inet6_rthdr_reverse
279return 0 on success, and returns -1 on error.
280.Pp
281.Fn inet6_rthdr_init
282and
283.Fn inet6_rthdr_getaddr
284return
285.Dv NULL
286on error.
287.Pp
288.Fn inet6_rthdr_segments
289and
290.Fn inet6_rthdr_getflags
291return -1 on error.
292.\"
293.Sh EXAMPLES
294RFC2292 gives comprehensive examples in chapter 8.
295.\"
296.Sh SEE ALSO
297.Rs
298.%A W. Stevens
299.%A M. Thomas
300.%T "Advanced Sockets API for IPv6"
301.%N RFC2292
302.%D February 1998
303.Re
304.Rs
305.%A S. Deering
306.%A R. Hinden
307.%T "Internet Protocol, Version 6 (IPv6) Specification"
308.%N RFC2460
309.%D December 1998
310.Re
311.\"
312.Sh HISTORY
313The implementation first appeared in KAME advanced networking kit.
314.\"
315.Sh STANDARDS
316The functions
317are documented in
318.Dq Advanced Sockets API for IPv6
319.Pq RFC2292 .
320.\"
321.Sh BUGS
322The text was shamelessly copied from RFC2292.
323.Pp
324.Fn inet6_rthdr_reverse
325is not implemented yet.
diff --git a/src/lib/libc/net/inet_addr.c b/src/lib/libc/net/inet_addr.c
new file mode 100644
index 0000000000..6203ccdaac
--- /dev/null
+++ b/src/lib/libc/net/inet_addr.c
@@ -0,0 +1,187 @@
1/* $OpenBSD: inet_addr.c,v 1.6 1999/05/03 22:31:14 yanick Exp $ */
2
3/*
4 * ++Copyright++ 1983, 1990, 1993
5 * -
6 * Copyright (c) 1983, 1990, 1993
7 * The Regents of the University of California. All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by the University of
20 * California, Berkeley and its contributors.
21 * 4. Neither the name of the University nor the names of its contributors
22 * may be used to endorse or promote products derived from this software
23 * without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
36 * -
37 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
38 *
39 * Permission to use, copy, modify, and distribute this software for any
40 * purpose with or without fee is hereby granted, provided that the above
41 * copyright notice and this permission notice appear in all copies, and that
42 * the name of Digital Equipment Corporation not be used in advertising or
43 * publicity pertaining to distribution of the document or software without
44 * specific, written prior permission.
45 *
46 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
47 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
48 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
49 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
50 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
51 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
52 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
53 * SOFTWARE.
54 * -
55 * --Copyright--
56 */
57
58#if defined(LIBC_SCCS) && !defined(lint)
59#if 0
60static char sccsid[] = "@(#)inet_addr.c 8.1 (Berkeley) 6/17/93";
61static char rcsid[] = "$From: inet_addr.c,v 8.5 1996/08/05 08:31:35 vixie Exp $";
62#else
63static char rcsid[] = "$OpenBSD: inet_addr.c,v 1.6 1999/05/03 22:31:14 yanick Exp $";
64#endif
65#endif /* LIBC_SCCS and not lint */
66
67#include <sys/types.h>
68#include <sys/param.h>
69#include <netinet/in.h>
70#include <arpa/inet.h>
71#include <ctype.h>
72
73/*
74 * Ascii internet address interpretation routine.
75 * The value returned is in network order.
76 */
77in_addr_t
78inet_addr(cp)
79 register const char *cp;
80{
81 struct in_addr val;
82
83 if (inet_aton(cp, &val))
84 return (val.s_addr);
85 return (INADDR_NONE);
86}
87
88/*
89 * Check whether "cp" is a valid ascii representation
90 * of an Internet address and convert to a binary address.
91 * Returns 1 if the address is valid, 0 if not.
92 * This replaces inet_addr, the return value from which
93 * cannot distinguish between failure and a local broadcast address.
94 */
95int
96inet_aton(cp, addr)
97 register const char *cp;
98 struct in_addr *addr;
99{
100 register in_addr_t val;
101 register int base, n;
102 register char c;
103 u_int parts[4];
104 register u_int *pp = parts;
105
106 c = *cp;
107 for (;;) {
108 /*
109 * Collect number up to ``.''.
110 * Values are specified as for C:
111 * 0x=hex, 0=octal, isdigit=decimal.
112 */
113 if (!isdigit(c))
114 return (0);
115 val = 0; base = 10;
116 if (c == '0') {
117 c = *++cp;
118 if (c == 'x' || c == 'X')
119 base = 16, c = *++cp;
120 else
121 base = 8;
122 }
123 for (;;) {
124 if (isascii(c) && isdigit(c)) {
125 val = (val * base) + (c - '0');
126 c = *++cp;
127 } else if (base == 16 && isascii(c) && isxdigit(c)) {
128 val = (val << 4) |
129 (c + 10 - (islower(c) ? 'a' : 'A'));
130 c = *++cp;
131 } else
132 break;
133 }
134 if (c == '.') {
135 /*
136 * Internet format:
137 * a.b.c.d
138 * a.b.c (with c treated as 16 bits)
139 * a.b (with b treated as 24 bits)
140 */
141 if (pp >= parts + 3)
142 return (0);
143 *pp++ = val;
144 c = *++cp;
145 } else
146 break;
147 }
148 /*
149 * Check for trailing characters.
150 */
151 if (c != '\0' && (!isascii(c) || !isspace(c)))
152 return (0);
153 /*
154 * Concoct the address according to
155 * the number of parts specified.
156 */
157 n = pp - parts + 1;
158 switch (n) {
159
160 case 0:
161 return (0); /* initial nondigit */
162
163 case 1: /* a -- 32 bits */
164 break;
165
166 case 2: /* a.b -- 8.24 bits */
167 if ((val > 0xffffff) || (parts[0] > 0xff))
168 return (0);
169 val |= parts[0] << 24;
170 break;
171
172 case 3: /* a.b.c -- 8.8.16 bits */
173 if ((val > 0xffff) || (parts[0] > 0xff) || (parts[1] > 0xff))
174 return (0);
175 val |= (parts[0] << 24) | (parts[1] << 16);
176 break;
177
178 case 4: /* a.b.c.d -- 8.8.8.8 bits */
179 if ((val > 0xff) || (parts[0] > 0xff) || (parts[1] > 0xff) || (parts[2] > 0xff))
180 return (0);
181 val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
182 break;
183 }
184 if (addr)
185 addr->s_addr = htonl(val);
186 return (1);
187}
diff --git a/src/lib/libc/net/inet_lnaof.c b/src/lib/libc/net/inet_lnaof.c
new file mode 100644
index 0000000000..6aed18699b
--- /dev/null
+++ b/src/lib/libc/net/inet_lnaof.c
@@ -0,0 +1,59 @@
1/*
2 * Copyright (c) 1983, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#if defined(LIBC_SCCS) && !defined(lint)
35static char rcsid[] = "$OpenBSD: inet_lnaof.c,v 1.3 1997/04/05 21:13:11 millert Exp $";
36#endif /* LIBC_SCCS and not lint */
37
38#include <sys/param.h>
39#include <netinet/in.h>
40#include <arpa/inet.h>
41
42/*
43 * Return the local network address portion of an
44 * internet address; handles class a/b/c network
45 * number formats.
46 */
47in_addr_t
48inet_lnaof(in)
49 struct in_addr in;
50{
51 register in_addr_t i = ntohl(in.s_addr);
52
53 if (IN_CLASSA(i))
54 return ((i)&IN_CLASSA_HOST);
55 else if (IN_CLASSB(i))
56 return ((i)&IN_CLASSB_HOST);
57 else
58 return ((i)&IN_CLASSC_HOST);
59}
diff --git a/src/lib/libc/net/inet_makeaddr.c b/src/lib/libc/net/inet_makeaddr.c
new file mode 100644
index 0000000000..196a589e4c
--- /dev/null
+++ b/src/lib/libc/net/inet_makeaddr.c
@@ -0,0 +1,62 @@
1/*
2 * Copyright (c) 1983, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#if defined(LIBC_SCCS) && !defined(lint)
35static char rcsid[] = "$OpenBSD: inet_makeaddr.c,v 1.3 1997/04/05 21:13:12 millert Exp $";
36#endif /* LIBC_SCCS and not lint */
37
38#include <sys/param.h>
39#include <netinet/in.h>
40#include <arpa/inet.h>
41
42/*
43 * Formulate an Internet address from network + host. Used in
44 * building addresses stored in the ifnet structure.
45 */
46struct in_addr
47inet_makeaddr(net, host)
48 in_addr_t net, host;
49{
50 in_addr_t addr;
51
52 if (net < 128)
53 addr = (net << IN_CLASSA_NSHIFT) | (host & IN_CLASSA_HOST);
54 else if (net < 65536)
55 addr = (net << IN_CLASSB_NSHIFT) | (host & IN_CLASSB_HOST);
56 else if (net < 16777216L)
57 addr = (net << IN_CLASSC_NSHIFT) | (host & IN_CLASSC_HOST);
58 else
59 addr = net | host;
60 addr = htonl(addr);
61 return (*(struct in_addr *)&addr);
62}
diff --git a/src/lib/libc/net/inet_net.3 b/src/lib/libc/net/inet_net.3
new file mode 100644
index 0000000000..5c32aecd86
--- /dev/null
+++ b/src/lib/libc/net/inet_net.3
@@ -0,0 +1,148 @@
1.\" $OpenBSD: inet_net.3,v 1.6 2000/04/21 15:38:17 aaron Exp $
2.\" $NetBSD: inet_net.3,v 1.1 1997/06/18 02:25:27 lukem Exp $
3.\"
4.\" Copyright (c) 1997 The NetBSD Foundation, Inc.
5.\" All rights reserved.
6.\"
7.\" This code is derived from software contributed to The NetBSD Foundation
8.\" by Luke Mewburn.
9.\"
10.\" Redistribution and use in source and binary forms, with or without
11.\" modification, are permitted provided that the following conditions
12.\" are met:
13.\" 1. Redistributions of source code must retain the above copyright
14.\" notice, this list of conditions and the following disclaimer.
15.\" 2. Redistributions in binary form must reproduce the above copyright
16.\" notice, this list of conditions and the following disclaimer in the
17.\" documentation and/or other materials provided with the distribution.
18.\" 3. All advertising materials mentioning features or use of this software
19.\" must display the following acknowledgement:
20.\" This product includes software developed by the NetBSD
21.\" Foundation, Inc. and its contributors.
22.\" 4. Neither the name of The NetBSD Foundation nor the names of its
23.\" contributors may be used to endorse or promote products derived
24.\" from this software without specific prior written permission.
25.\"
26.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
30.\" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36.\" POSSIBILITY OF SUCH DAMAGE.
37.\"
38.Dd June 18, 1997
39.Dt INET_NET 3
40.Os
41.Sh NAME
42.Nm inet_net_ntop ,
43.Nm inet_net_pton
44.Nd Internet network number manipulation routines
45.Sh SYNOPSIS
46.Fd #include <sys/socket.h>
47.Fd #include <netinet/in.h>
48.Fd #include <arpa/inet.h>
49.Ft char *
50.Fn inet_net_ntop "int af" "const void *src" "int bits" "char *dst" "size_t size"
51.Ft int
52.Fn inet_net_pton "int af" "const char *src" "void *dst" "size_t size"
53.Sh DESCRIPTION
54The
55.Fn inet_net_ntop
56function converts an Internet network number from network format (usually a
57.Li struct in_addr
58or some other binary form, in network byte order) to CIDR presentation format
59(suitable for external display purposes).
60.Fa bits
61is the number of bits in
62.Fa src
63that are the network number.
64It returns
65.Dv NULL
66if a system error occurs (in which case,
67.Va errno
68will have been set), or it returns a pointer to the destination string.
69.Pp
70The
71.Fn inet_net_pton
72function converts a presentation format Internet network number (that is,
73printable form as held in a character string) to network format (usually a
74.Li struct in_addr
75or some other internal binary representation, in network byte order).
76It returns the number of bits (either computed based on the class, or
77specified with /CIDR), or \-1 if a failure occurred
78(in which case
79.Va errno
80will have been set.
81It will be set to
82.Er ENOENT
83if the Internet network number was not valid).
84.Pp
85The only value for
86.Fa af
87currently supported is
88.Dv AF_INET .
89.Fa size
90is the size of the result buffer
91.Fa dst .
92.Sh NETWORK NUMBERS (IP VERSION 4)
93Internet network numbers may be specified in one of the following forms:
94.Bd -literal -offset indent
95a.b.c.d/bits
96a.b.c.d
97a.b.c
98a.b
99a
100.Ed
101.Pp
102When four parts are specified, each is interpreted
103as a byte of data and assigned, from left to right,
104to the four bytes of an Internet network number.
105Note that when an Internet network number is viewed as a 32-bit
106integer quantity on a system that uses little-endian
107byte order (such as the Intel 386, 486, and Pentium processors)
108the bytes referred to above appear as
109.Dq Li d.c.b.a .
110That is, little-endian bytes are ordered from right to left.
111.Pp
112When a three part number is specified, the last
113part is interpreted as a 16-bit quantity and placed
114in the rightmost two bytes of the Internet network number.
115This makes the three part number format convenient
116for specifying Class B network numbers as
117.Dq Li 128.net.host .
118.Pp
119When a two part number is supplied, the last part
120is interpreted as a 24-bit quantity and placed in
121the rightmost three bytes of the Internet network number.
122This makes the two part number format convenient
123for specifying Class A network numbers as
124.Dq Li net.host .
125.Pp
126When only one part is given, the value is stored
127directly in the Internet network number without any byte
128rearrangement.
129.Pp
130All numbers supplied as
131.Dq parts
132in a
133.Ql \&.
134notation
135may be decimal, octal, or hexadecimal, as specified
136in the C language (i.e., a leading 0x or 0X implies
137hexadecimal; otherwise, a leading 0 implies octal;
138otherwise, the number is interpreted as decimal).
139.Sh SEE ALSO
140.Xr byteorder 3 ,
141.Xr inet 3 ,
142.Xr networks 5
143.Sh HISTORY
144The
145.Nm inet_net_ntop
146and
147.Nm inet_net_pton
148functions first appeared in BIND 4.9.4.
diff --git a/src/lib/libc/net/inet_net_ntop.c b/src/lib/libc/net/inet_net_ntop.c
new file mode 100644
index 0000000000..18eea6bb6d
--- /dev/null
+++ b/src/lib/libc/net/inet_net_ntop.c
@@ -0,0 +1,153 @@
1/* $OpenBSD: inet_net_ntop.c,v 1.3 2002/08/19 03:01:54 itojun Exp $ */
2
3/*
4 * Copyright (c) 1996 by Internet Software Consortium.
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
11 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
12 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
13 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
16 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
17 * SOFTWARE.
18 */
19
20#if defined(LIBC_SCCS) && !defined(lint)
21#if 0
22static const char rcsid[] = "$From: inet_net_ntop.c,v 8.2 1996/08/08 06:54:44 vixie Exp $";
23#else
24static const char rcsid[] = "$OpenBSD: inet_net_ntop.c,v 1.3 2002/08/19 03:01:54 itojun Exp $";
25#endif
26#endif
27
28#include <sys/types.h>
29#include <sys/socket.h>
30#include <netinet/in.h>
31#include <arpa/inet.h>
32
33#include <errno.h>
34#include <stdio.h>
35#include <string.h>
36#include <stdlib.h>
37
38static char *inet_net_ntop_ipv4(const u_char *, int, char *, size_t);
39
40/*
41 * char *
42 * inet_net_ntop(af, src, bits, dst, size)
43 * convert network number from network to presentation format.
44 * generates CIDR style result always.
45 * return:
46 * pointer to dst, or NULL if an error occurred (check errno).
47 * author:
48 * Paul Vixie (ISC), July 1996
49 */
50char *
51inet_net_ntop(af, src, bits, dst, size)
52 int af;
53 const void *src;
54 int bits;
55 char *dst;
56 size_t size;
57{
58 switch (af) {
59 case AF_INET:
60 return (inet_net_ntop_ipv4(src, bits, dst, size));
61 default:
62 errno = EAFNOSUPPORT;
63 return (NULL);
64 }
65}
66
67/*
68 * static char *
69 * inet_net_ntop_ipv4(src, bits, dst, size)
70 * convert IPv4 network number from network to presentation format.
71 * generates CIDR style result always.
72 * return:
73 * pointer to dst, or NULL if an error occurred (check errno).
74 * note:
75 * network byte order assumed. this means 192.5.5.240/28 has
76 * 0x11110000 in its fourth octet.
77 * author:
78 * Paul Vixie (ISC), July 1996
79 */
80static char *
81inet_net_ntop_ipv4(src, bits, dst, size)
82 const u_char *src;
83 int bits;
84 char *dst;
85 size_t size;
86{
87 char *odst = dst;
88 char *t;
89 u_int m;
90 int b;
91 char *ep;
92 int advance;
93
94 ep = dst + size;
95 if (ep <= dst)
96 goto emsgsize;
97
98 if (bits < 0 || bits > 32) {
99 errno = EINVAL;
100 return (NULL);
101 }
102 if (bits == 0) {
103 if (ep - dst < sizeof "0")
104 goto emsgsize;
105 *dst++ = '0';
106 *dst = '\0';
107 }
108
109 /* Format whole octets. */
110 for (b = bits / 8; b > 0; b--) {
111 if (ep - dst < sizeof "255.")
112 goto emsgsize;
113 advance = snprintf(dst, ep - dst, "%u", *src++);
114 if (advance <= 0 || advance >= ep - dst)
115 goto emsgsize;
116 dst += advance;
117 if (b > 1) {
118 if (dst + 1 >= ep)
119 goto emsgsize;
120 *dst++ = '.';
121 *dst = '\0';
122 }
123 }
124
125 /* Format partial octet. */
126 b = bits % 8;
127 if (b > 0) {
128 if (ep - dst < sizeof ".255")
129 goto emsgsize;
130 if (dst != odst)
131 if (dst + 1 >= ep)
132 goto emsgsize;
133 *dst++ = '.';
134 m = ((1 << b) - 1) << (8 - b);
135 advance = snprintf(dst, ep - dst, "%u", *src & m);
136 if (advance <= 0 || advance >= ep - dst)
137 goto emsgsize;
138 dst += advance;
139 }
140
141 /* Format CIDR /width. */
142 if (ep - dst < sizeof "/32")
143 goto emsgsize;
144 advance = snprintf(dst, ep - dst, "/%u", bits);
145 if (advance <= 0 || advance >= ep - dst)
146 goto emsgsize;
147 dst += advance;
148 return (odst);
149
150 emsgsize:
151 errno = EMSGSIZE;
152 return (NULL);
153}
diff --git a/src/lib/libc/net/inet_net_pton.c b/src/lib/libc/net/inet_net_pton.c
new file mode 100644
index 0000000000..932531eb5d
--- /dev/null
+++ b/src/lib/libc/net/inet_net_pton.c
@@ -0,0 +1,206 @@
1/* $OpenBSD: inet_net_pton.c,v 1.2 2002/02/17 19:42:23 millert Exp $ */
2
3/*
4 * Copyright (c) 1996 by Internet Software Consortium.
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
11 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
12 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
13 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
16 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
17 * SOFTWARE.
18 */
19
20#if defined(LIBC_SCCS) && !defined(lint)
21#if 0
22static const char rcsid[] = "$From: inet_net_pton.c,v 8.3 1996/11/11 06:36:52 vixie Exp $";
23#else
24static const char rcsid[] = "$OpenBSD: inet_net_pton.c,v 1.2 2002/02/17 19:42:23 millert Exp $";
25#endif
26#endif
27
28#include <sys/types.h>
29#include <sys/socket.h>
30#include <netinet/in.h>
31#include <arpa/inet.h>
32
33#include <assert.h>
34#include <ctype.h>
35#include <errno.h>
36#include <stdio.h>
37#include <string.h>
38#include <stdlib.h>
39
40static int inet_net_pton_ipv4(const char *, u_char *, size_t);
41
42/*
43 * static int
44 * inet_net_pton(af, src, dst, size)
45 * convert network number from presentation to network format.
46 * accepts hex octets, hex strings, decimal octets, and /CIDR.
47 * "size" is in bytes and describes "dst".
48 * return:
49 * number of bits, either imputed classfully or specified with /CIDR,
50 * or -1 if some failure occurred (check errno). ENOENT means it was
51 * not a valid network specification.
52 * author:
53 * Paul Vixie (ISC), June 1996
54 */
55int
56inet_net_pton(af, src, dst, size)
57 int af;
58 const char *src;
59 void *dst;
60 size_t size;
61{
62 switch (af) {
63 case AF_INET:
64 return (inet_net_pton_ipv4(src, dst, size));
65 default:
66 errno = EAFNOSUPPORT;
67 return (-1);
68 }
69}
70
71/*
72 * static int
73 * inet_net_pton_ipv4(src, dst, size)
74 * convert IPv4 network number from presentation to network format.
75 * accepts hex octets, hex strings, decimal octets, and /CIDR.
76 * "size" is in bytes and describes "dst".
77 * return:
78 * number of bits, either imputed classfully or specified with /CIDR,
79 * or -1 if some failure occurred (check errno). ENOENT means it was
80 * not an IPv4 network specification.
81 * note:
82 * network byte order assumed. this means 192.5.5.240/28 has
83 * 0x11110000 in its fourth octet.
84 * author:
85 * Paul Vixie (ISC), June 1996
86 */
87static int
88inet_net_pton_ipv4(src, dst, size)
89 const char *src;
90 u_char *dst;
91 size_t size;
92{
93 static const char
94 xdigits[] = "0123456789abcdef",
95 digits[] = "0123456789";
96 int n, ch, tmp, dirty, bits;
97 const u_char *odst = dst;
98
99 ch = *src++;
100 if (ch == '0' && (src[0] == 'x' || src[0] == 'X')
101 && isascii(src[1]) && isxdigit(src[1])) {
102 /* Hexadecimal: Eat nybble string. */
103 if (size <= 0)
104 goto emsgsize;
105 *dst = 0, dirty = 0;
106 src++; /* skip x or X. */
107 while ((ch = *src++) != '\0' &&
108 isascii(ch) && isxdigit(ch)) {
109 if (isupper(ch))
110 ch = tolower(ch);
111 n = strchr(xdigits, ch) - xdigits;
112 assert(n >= 0 && n <= 15);
113 *dst |= n;
114 if (!dirty++)
115 *dst <<= 4;
116 else if (size-- > 0)
117 *++dst = 0, dirty = 0;
118 else
119 goto emsgsize;
120 }
121 if (dirty)
122 size--;
123 } else if (isascii(ch) && isdigit(ch)) {
124 /* Decimal: eat dotted digit string. */
125 for (;;) {
126 tmp = 0;
127 do {
128 n = strchr(digits, ch) - digits;
129 assert(n >= 0 && n <= 9);
130 tmp *= 10;
131 tmp += n;
132 if (tmp > 255)
133 goto enoent;
134 } while ((ch = *src++) != '\0' &&
135 isascii(ch) && isdigit(ch));
136 if (size-- <= 0)
137 goto emsgsize;
138 *dst++ = (u_char) tmp;
139 if (ch == '\0' || ch == '/')
140 break;
141 if (ch != '.')
142 goto enoent;
143 ch = *src++;
144 if (!isascii(ch) || !isdigit(ch))
145 goto enoent;
146 }
147 } else
148 goto enoent;
149
150 bits = -1;
151 if (ch == '/' && isascii(src[0]) && isdigit(src[0]) && dst > odst) {
152 /* CIDR width specifier. Nothing can follow it. */
153 ch = *src++; /* Skip over the /. */
154 bits = 0;
155 do {
156 n = strchr(digits, ch) - digits;
157 assert(n >= 0 && n <= 9);
158 bits *= 10;
159 bits += n;
160 } while ((ch = *src++) != '\0' &&
161 isascii(ch) && isdigit(ch));
162 if (ch != '\0')
163 goto enoent;
164 if (bits > 32)
165 goto emsgsize;
166 }
167
168 /* Firey death and destruction unless we prefetched EOS. */
169 if (ch != '\0')
170 goto enoent;
171
172 /* If nothing was written to the destination, we found no address. */
173 if (dst == odst)
174 goto enoent;
175 /* If no CIDR spec was given, infer width from net class. */
176 if (bits == -1) {
177 if (*odst >= 240) /* Class E */
178 bits = 32;
179 else if (*odst >= 224) /* Class D */
180 bits = 4;
181 else if (*odst >= 192) /* Class C */
182 bits = 24;
183 else if (*odst >= 128) /* Class B */
184 bits = 16;
185 else /* Class A */
186 bits = 8;
187 /* If imputed mask is narrower than specified octets, widen. */
188 if (bits >= 8 && bits < ((dst - odst) * 8))
189 bits = (dst - odst) * 8;
190 }
191 /* Extend network to cover the actual mask. */
192 while (bits > ((dst - odst) * 8)) {
193 if (size-- <= 0)
194 goto emsgsize;
195 *dst++ = '\0';
196 }
197 return (bits);
198
199 enoent:
200 errno = ENOENT;
201 return (-1);
202
203 emsgsize:
204 errno = EMSGSIZE;
205 return (-1);
206}
diff --git a/src/lib/libc/net/inet_neta.c b/src/lib/libc/net/inet_neta.c
new file mode 100644
index 0000000000..6960bcd0b5
--- /dev/null
+++ b/src/lib/libc/net/inet_neta.c
@@ -0,0 +1,91 @@
1/* $OpenBSD: inet_neta.c,v 1.4 2002/08/19 03:01:54 itojun Exp $ */
2
3/*
4 * Copyright (c) 1996 by Internet Software Consortium.
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
11 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
12 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
13 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
16 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
17 * SOFTWARE.
18 */
19
20#if defined(LIBC_SCCS) && !defined(lint)
21#if 0
22static const char rcsid[] = "$Id: inet_neta.c,v 1.4 2002/08/19 03:01:54 itojun Exp $";
23#else
24static const char rcsid[] = "$OpenBSD: inet_neta.c,v 1.4 2002/08/19 03:01:54 itojun Exp $";
25#endif
26#endif
27
28#include <sys/types.h>
29#include <sys/socket.h>
30#include <netinet/in.h>
31#include <arpa/inet.h>
32
33#include <errno.h>
34#include <stdio.h>
35#include <string.h>
36
37/*
38 * char *
39 * inet_neta(src, dst, size)
40 * format an in_addr_t network number into presentation format.
41 * return:
42 * pointer to dst, or NULL if an error occurred (check errno).
43 * note:
44 * format of ``src'' is as for inet_network().
45 * author:
46 * Paul Vixie (ISC), July 1996
47 */
48char *
49inet_neta(src, dst, size)
50 in_addr_t src;
51 char *dst;
52 size_t size;
53{
54 char *odst = dst;
55 char *ep;
56 int advance;
57
58 if (src == 0x00000000) {
59 if (size < sizeof "0.0.0.0")
60 goto emsgsize;
61 strlcpy(dst, "0.0.0.0", size);
62 return dst;
63 }
64 ep = dst + size;
65 if (ep <= dst)
66 goto emsgsize;
67 while (src & 0xffffffff) {
68 u_char b = (src & 0xff000000) >> 24;
69
70 src <<= 8;
71 if (b || src) {
72 if (ep - dst < sizeof "255.")
73 goto emsgsize;
74 advance = snprintf(dst, ep - dst, "%u", b);
75 if (advance <= 0 || advance >= ep - dst)
76 goto emsgsize;
77 dst += advance;
78 if (src != 0L) {
79 if (dst + 1 >= ep)
80 goto emsgsize;
81 *dst++ = '.';
82 *dst = '\0';
83 }
84 }
85 }
86 return (odst);
87
88 emsgsize:
89 errno = EMSGSIZE;
90 return (NULL);
91}
diff --git a/src/lib/libc/net/inet_netof.c b/src/lib/libc/net/inet_netof.c
new file mode 100644
index 0000000000..f3b9c01697
--- /dev/null
+++ b/src/lib/libc/net/inet_netof.c
@@ -0,0 +1,58 @@
1/*
2 * Copyright (c) 1983, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#if defined(LIBC_SCCS) && !defined(lint)
35static char rcsid[] = "$OpenBSD: inet_netof.c,v 1.3 1997/04/05 21:13:13 millert Exp $";
36#endif /* LIBC_SCCS and not lint */
37
38#include <sys/param.h>
39#include <netinet/in.h>
40#include <arpa/inet.h>
41
42/*
43 * Return the network number from an internet
44 * address; handles class a/b/c network #'s.
45 */
46in_addr_t
47inet_netof(in)
48 struct in_addr in;
49{
50 register in_addr_t i = ntohl(in.s_addr);
51
52 if (IN_CLASSA(i))
53 return (((i)&IN_CLASSA_NET) >> IN_CLASSA_NSHIFT);
54 else if (IN_CLASSB(i))
55 return (((i)&IN_CLASSB_NET) >> IN_CLASSB_NSHIFT);
56 else
57 return (((i)&IN_CLASSC_NET) >> IN_CLASSC_NSHIFT);
58}
diff --git a/src/lib/libc/net/inet_network.c b/src/lib/libc/net/inet_network.c
new file mode 100644
index 0000000000..8a9a555d62
--- /dev/null
+++ b/src/lib/libc/net/inet_network.c
@@ -0,0 +1,92 @@
1/*
2 * Copyright (c) 1983, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#if defined(LIBC_SCCS) && !defined(lint)
35static char rcsid[] = "$OpenBSD: inet_network.c,v 1.7 1997/07/09 01:08:37 millert Exp $";
36#endif /* LIBC_SCCS and not lint */
37
38#include <sys/types.h>
39#include <netinet/in.h>
40#include <arpa/inet.h>
41#include <ctype.h>
42
43/*
44 * Internet network address interpretation routine.
45 * The library routines call this routine to interpret
46 * network numbers.
47 */
48in_addr_t
49inet_network(cp)
50 register const char *cp;
51{
52 register in_addr_t val, base, n;
53 register char c;
54 in_addr_t parts[4], *pp = parts;
55 register int i;
56
57again:
58 val = 0; base = 10;
59 if (*cp == '0')
60 base = 8, cp++;
61 if (*cp == 'x' || *cp == 'X')
62 base = 16, cp++;
63 while ((c = *cp)) {
64 if (isdigit(c)) {
65 val = (val * base) + (c - '0');
66 cp++;
67 continue;
68 }
69 if (base == 16 && isxdigit(c)) {
70 val = (val << 4) + (c + 10 - (islower(c) ? 'a' : 'A'));
71 cp++;
72 continue;
73 }
74 break;
75 }
76 if (*cp == '.') {
77 if (pp >= parts + 3)
78 return (INADDR_NONE);
79 *pp++ = val, cp++;
80 goto again;
81 }
82 if (*cp && !isspace(*cp))
83 return (INADDR_NONE);
84 *pp++ = val;
85 n = pp - parts;
86 for (val = 0, i = 0; i < 4; i++) {
87 val <<= 8;
88 if (i < n)
89 val |= parts[i] & 0xff;
90 }
91 return (val);
92}
diff --git a/src/lib/libc/net/inet_ntoa.c b/src/lib/libc/net/inet_ntoa.c
new file mode 100644
index 0000000000..377184f366
--- /dev/null
+++ b/src/lib/libc/net/inet_ntoa.c
@@ -0,0 +1,59 @@
1/*
2 * Copyright (c) 1983, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#if defined(LIBC_SCCS) && !defined(lint)
35static char rcsid[] = "$OpenBSD: inet_ntoa.c,v 1.3 2002/06/27 10:14:01 itojun Exp $";
36#endif /* LIBC_SCCS and not lint */
37
38/*
39 * Convert network-format internet address
40 * to base 256 d.d.d.d representation.
41 */
42#include <sys/types.h>
43#include <netinet/in.h>
44#include <arpa/inet.h>
45#include <stdio.h>
46
47char *
48inet_ntoa(in)
49 struct in_addr in;
50{
51 static char b[18];
52 register char *p;
53
54 p = (char *)&in;
55#define UC(b) (((int)b)&0xff)
56 (void)snprintf(b, sizeof(b),
57 "%u.%u.%u.%u", UC(p[0]), UC(p[1]), UC(p[2]), UC(p[3]));
58 return (b);
59}
diff --git a/src/lib/libc/net/inet_ntop.c b/src/lib/libc/net/inet_ntop.c
new file mode 100644
index 0000000000..adce61c1d4
--- /dev/null
+++ b/src/lib/libc/net/inet_ntop.c
@@ -0,0 +1,213 @@
1/* $OpenBSD: inet_ntop.c,v 1.5 2002/08/23 16:27:31 itojun Exp $ */
2
3/* Copyright (c) 1996 by Internet Software Consortium.
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
10 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
11 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
12 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
15 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
16 * SOFTWARE.
17 */
18
19#if defined(LIBC_SCCS) && !defined(lint)
20#if 0
21static char rcsid[] = "$From: inet_ntop.c,v 8.7 1996/08/05 08:41:18 vixie Exp $";
22#else
23static char rcsid[] = "$OpenBSD: inet_ntop.c,v 1.5 2002/08/23 16:27:31 itojun Exp $";
24#endif
25#endif /* LIBC_SCCS and not lint */
26
27#include <sys/param.h>
28#include <sys/types.h>
29#include <sys/socket.h>
30#include <netinet/in.h>
31#include <arpa/inet.h>
32#include <arpa/nameser.h>
33#include <string.h>
34#include <errno.h>
35#include <stdio.h>
36
37/*
38 * WARNING: Don't even consider trying to compile this on a system where
39 * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
40 */
41
42static const char *inet_ntop4(const u_char *src, char *dst, size_t size);
43static const char *inet_ntop6(const u_char *src, char *dst, size_t size);
44
45/* char *
46 * inet_ntop(af, src, dst, size)
47 * convert a network format address to presentation format.
48 * return:
49 * pointer to presentation format address (`dst'), or NULL (see errno).
50 * author:
51 * Paul Vixie, 1996.
52 */
53const char *
54inet_ntop(af, src, dst, size)
55 int af;
56 const void *src;
57 char *dst;
58 size_t size;
59{
60 switch (af) {
61 case AF_INET:
62 return (inet_ntop4(src, dst, size));
63 case AF_INET6:
64 return (inet_ntop6(src, dst, size));
65 default:
66 errno = EAFNOSUPPORT;
67 return (NULL);
68 }
69 /* NOTREACHED */
70}
71
72/* const char *
73 * inet_ntop4(src, dst, size)
74 * format an IPv4 address, more or less like inet_ntoa()
75 * return:
76 * `dst' (as a const)
77 * notes:
78 * (1) uses no statics
79 * (2) takes a u_char* not an in_addr as input
80 * author:
81 * Paul Vixie, 1996.
82 */
83static const char *
84inet_ntop4(src, dst, size)
85 const u_char *src;
86 char *dst;
87 size_t size;
88{
89 static const char fmt[] = "%u.%u.%u.%u";
90 char tmp[sizeof "255.255.255.255"];
91 int l;
92
93 l = snprintf(tmp, size, fmt, src[0], src[1], src[2], src[3]);
94 if (l <= 0 || l >= size) {
95 errno = ENOSPC;
96 return (NULL);
97 }
98 strlcpy(dst, tmp, size);
99 return (dst);
100}
101
102/* const char *
103 * inet_ntop6(src, dst, size)
104 * convert IPv6 binary address into presentation (printable) format
105 * author:
106 * Paul Vixie, 1996.
107 */
108static const char *
109inet_ntop6(src, dst, size)
110 const u_char *src;
111 char *dst;
112 size_t size;
113{
114 /*
115 * Note that int32_t and int16_t need only be "at least" large enough
116 * to contain a value of the specified size. On some systems, like
117 * Crays, there is no such thing as an integer variable with 16 bits.
118 * Keep this in mind if you think this function should have been coded
119 * to use pointer overlays. All the world's not a VAX.
120 */
121 char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"];
122 char *tp, *ep;
123 struct { int base, len; } best, cur;
124 u_int words[IN6ADDRSZ / INT16SZ];
125 int i;
126 int advance;
127
128 /*
129 * Preprocess:
130 * Copy the input (bytewise) array into a wordwise array.
131 * Find the longest run of 0x00's in src[] for :: shorthanding.
132 */
133 memset(words, '\0', sizeof words);
134 for (i = 0; i < IN6ADDRSZ; i++)
135 words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
136 best.base = -1;
137 cur.base = -1;
138 for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) {
139 if (words[i] == 0) {
140 if (cur.base == -1)
141 cur.base = i, cur.len = 1;
142 else
143 cur.len++;
144 } else {
145 if (cur.base != -1) {
146 if (best.base == -1 || cur.len > best.len)
147 best = cur;
148 cur.base = -1;
149 }
150 }
151 }
152 if (cur.base != -1) {
153 if (best.base == -1 || cur.len > best.len)
154 best = cur;
155 }
156 if (best.base != -1 && best.len < 2)
157 best.base = -1;
158
159 /*
160 * Format the result.
161 */
162 tp = tmp;
163 ep = tmp + sizeof(tmp);
164 for (i = 0; i < (IN6ADDRSZ / INT16SZ) && tp < ep; i++) {
165 /* Are we inside the best run of 0x00's? */
166 if (best.base != -1 && i >= best.base &&
167 i < (best.base + best.len)) {
168 if (i == best.base) {
169 if (tp + 1 >= ep)
170 return (NULL);
171 *tp++ = ':';
172 }
173 continue;
174 }
175 /* Are we following an initial run of 0x00s or any real hex? */
176 if (i != 0) {
177 if (tp + 1 >= ep)
178 return (NULL);
179 *tp++ = ':';
180 }
181 /* Is this address an encapsulated IPv4? */
182 if (i == 6 && best.base == 0 &&
183 (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
184 if (!inet_ntop4(src+12, tp, (size_t)(ep - tp)))
185 return (NULL);
186 tp += strlen(tp);
187 break;
188 }
189 advance = snprintf(tp, ep - tp, "%x", words[i]);
190 if (advance <= 0 || advance >= ep - tp)
191 return (NULL);
192 tp += advance;
193 }
194 /* Was it a trailing run of 0x00's? */
195 if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ)) {
196 if (tp + 1 >= ep)
197 return (NULL);
198 *tp++ = ':';
199 }
200 if (tp + 1 >= ep)
201 return (NULL);
202 *tp++ = '\0';
203
204 /*
205 * Check for overflow, copy, and we're done.
206 */
207 if ((size_t)(tp - tmp) > size) {
208 errno = ENOSPC;
209 return (NULL);
210 }
211 strlcpy(dst, tmp, size);
212 return (dst);
213}
diff --git a/src/lib/libc/net/inet_pton.c b/src/lib/libc/net/inet_pton.c
new file mode 100644
index 0000000000..b04ef05c31
--- /dev/null
+++ b/src/lib/libc/net/inet_pton.c
@@ -0,0 +1,222 @@
1/* $OpenBSD: inet_pton.c,v 1.4 2002/02/16 21:27:23 millert Exp $ */
2
3/* Copyright (c) 1996 by Internet Software Consortium.
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
10 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
11 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
12 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
15 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
16 * SOFTWARE.
17 */
18
19#if defined(LIBC_SCCS) && !defined(lint)
20#if 0
21static char rcsid[] = "$From: inet_pton.c,v 8.7 1996/08/05 08:31:35 vixie Exp $";
22#else
23static char rcsid[] = "$OpenBSD: inet_pton.c,v 1.4 2002/02/16 21:27:23 millert Exp $";
24#endif
25#endif /* LIBC_SCCS and not lint */
26
27#include <sys/param.h>
28#include <sys/types.h>
29#include <sys/socket.h>
30#include <netinet/in.h>
31#include <arpa/inet.h>
32#include <arpa/nameser.h>
33#include <string.h>
34#include <errno.h>
35
36/*
37 * WARNING: Don't even consider trying to compile this on a system where
38 * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
39 */
40
41static int inet_pton4(const char *src, u_char *dst);
42static int inet_pton6(const char *src, u_char *dst);
43
44/* int
45 * inet_pton(af, src, dst)
46 * convert from presentation format (which usually means ASCII printable)
47 * to network format (which is usually some kind of binary format).
48 * return:
49 * 1 if the address was valid for the specified address family
50 * 0 if the address wasn't valid (`dst' is untouched in this case)
51 * -1 if some other error occurred (`dst' is untouched in this case, too)
52 * author:
53 * Paul Vixie, 1996.
54 */
55int
56inet_pton(af, src, dst)
57 int af;
58 const char *src;
59 void *dst;
60{
61 switch (af) {
62 case AF_INET:
63 return (inet_pton4(src, dst));
64 case AF_INET6:
65 return (inet_pton6(src, dst));
66 default:
67 errno = EAFNOSUPPORT;
68 return (-1);
69 }
70 /* NOTREACHED */
71}
72
73/* int
74 * inet_pton4(src, dst)
75 * like inet_aton() but without all the hexadecimal and shorthand.
76 * return:
77 * 1 if `src' is a valid dotted quad, else 0.
78 * notice:
79 * does not touch `dst' unless it's returning 1.
80 * author:
81 * Paul Vixie, 1996.
82 */
83static int
84inet_pton4(src, dst)
85 const char *src;
86 u_char *dst;
87{
88 static const char digits[] = "0123456789";
89 int saw_digit, octets, ch;
90 u_char tmp[INADDRSZ], *tp;
91
92 saw_digit = 0;
93 octets = 0;
94 *(tp = tmp) = 0;
95 while ((ch = *src++) != '\0') {
96 const char *pch;
97
98 if ((pch = strchr(digits, ch)) != NULL) {
99 u_int new = *tp * 10 + (pch - digits);
100
101 if (new > 255)
102 return (0);
103 if (! saw_digit) {
104 if (++octets > 4)
105 return (0);
106 saw_digit = 1;
107 }
108 *tp = new;
109 } else if (ch == '.' && saw_digit) {
110 if (octets == 4)
111 return (0);
112 *++tp = 0;
113 saw_digit = 0;
114 } else
115 return (0);
116 }
117 if (octets < 4)
118 return (0);
119
120 memcpy(dst, tmp, INADDRSZ);
121 return (1);
122}
123
124/* int
125 * inet_pton6(src, dst)
126 * convert presentation level address to network order binary form.
127 * return:
128 * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
129 * notice:
130 * (1) does not touch `dst' unless it's returning 1.
131 * (2) :: in a full address is silently ignored.
132 * credit:
133 * inspired by Mark Andrews.
134 * author:
135 * Paul Vixie, 1996.
136 */
137static int
138inet_pton6(src, dst)
139 const char *src;
140 u_char *dst;
141{
142 static const char xdigits_l[] = "0123456789abcdef",
143 xdigits_u[] = "0123456789ABCDEF";
144 u_char tmp[IN6ADDRSZ], *tp, *endp, *colonp;
145 const char *xdigits, *curtok;
146 int ch, saw_xdigit;
147 u_int val;
148
149 memset((tp = tmp), '\0', IN6ADDRSZ);
150 endp = tp + IN6ADDRSZ;
151 colonp = NULL;
152 /* Leading :: requires some special handling. */
153 if (*src == ':')
154 if (*++src != ':')
155 return (0);
156 curtok = src;
157 saw_xdigit = 0;
158 val = 0;
159 while ((ch = *src++) != '\0') {
160 const char *pch;
161
162 if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
163 pch = strchr((xdigits = xdigits_u), ch);
164 if (pch != NULL) {
165 val <<= 4;
166 val |= (pch - xdigits);
167 if (val > 0xffff)
168 return (0);
169 saw_xdigit = 1;
170 continue;
171 }
172 if (ch == ':') {
173 curtok = src;
174 if (!saw_xdigit) {
175 if (colonp)
176 return (0);
177 colonp = tp;
178 continue;
179 } else if (*src == '\0') {
180 return (0);
181 }
182 if (tp + INT16SZ > endp)
183 return (0);
184 *tp++ = (u_char) (val >> 8) & 0xff;
185 *tp++ = (u_char) val & 0xff;
186 saw_xdigit = 0;
187 val = 0;
188 continue;
189 }
190 if (ch == '.' && ((tp + INADDRSZ) <= endp) &&
191 inet_pton4(curtok, tp) > 0) {
192 tp += INADDRSZ;
193 saw_xdigit = 0;
194 break; /* '\0' was seen by inet_pton4(). */
195 }
196 return (0);
197 }
198 if (saw_xdigit) {
199 if (tp + INT16SZ > endp)
200 return (0);
201 *tp++ = (u_char) (val >> 8) & 0xff;
202 *tp++ = (u_char) val & 0xff;
203 }
204 if (colonp != NULL) {
205 /*
206 * Since some memmove()'s erroneously fail to handle
207 * overlapping regions, we'll do the shift by hand.
208 */
209 const int n = tp - colonp;
210 int i;
211
212 for (i = 1; i <= n; i++) {
213 endp[- i] = colonp[n - i];
214 colonp[n - i] = 0;
215 }
216 tp = endp;
217 }
218 if (tp != endp)
219 return (0);
220 memcpy(dst, tmp, IN6ADDRSZ);
221 return (1);
222}
diff --git a/src/lib/libc/net/ip6opt.c b/src/lib/libc/net/ip6opt.c
new file mode 100644
index 0000000000..cbd49f0c22
--- /dev/null
+++ b/src/lib/libc/net/ip6opt.c
@@ -0,0 +1,388 @@
1/* $OpenBSD: ip6opt.c,v 1.1 1999/12/11 08:09:11 itojun Exp $ */
2
3/*
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32#include <sys/param.h>
33#include <sys/types.h>
34#include <sys/socket.h>
35
36#include <netinet/in.h>
37#include <netinet/ip6.h>
38
39#include <string.h>
40#include <stdio.h>
41
42static int ip6optlen(u_int8_t *opt, u_int8_t *lim);
43static void inet6_insert_padopt(u_char *p, int len);
44
45/*
46 * This function returns the number of bytes required to hold an option
47 * when it is stored as ancillary data, including the cmsghdr structure
48 * at the beginning, and any padding at the end (to make its size a
49 * multiple of 8 bytes). The argument is the size of the structure
50 * defining the option, which must include any pad bytes at the
51 * beginning (the value y in the alignment term "xn + y"), the type
52 * byte, the length byte, and the option data.
53 */
54int
55inet6_option_space(nbytes)
56 int nbytes;
57{
58 nbytes += 2; /* we need space for nxt-hdr and length fields */
59 return(CMSG_SPACE((nbytes + 7) & ~7));
60}
61
62/*
63 * This function is called once per ancillary data object that will
64 * contain either Hop-by-Hop or Destination options. It returns 0 on
65 * success or -1 on an error.
66 */
67int
68inet6_option_init(bp, cmsgp, type)
69 void *bp;
70 struct cmsghdr **cmsgp;
71 int type;
72{
73 register struct cmsghdr *ch = (struct cmsghdr *)bp;
74
75 /* argument validation */
76 if (type != IPV6_HOPOPTS && type != IPV6_DSTOPTS)
77 return(-1);
78
79 ch->cmsg_level = IPPROTO_IPV6;
80 ch->cmsg_type = type;
81 ch->cmsg_len = CMSG_LEN(0);
82
83 *cmsgp = ch;
84 return(0);
85}
86
87/*
88 * This function appends a Hop-by-Hop option or a Destination option
89 * into an ancillary data object that has been initialized by
90 * inet6_option_init(). This function returns 0 if it succeeds or -1 on
91 * an error.
92 * multx is the value x in the alignment term "xn + y" described
93 * earlier. It must have a value of 1, 2, 4, or 8.
94 * plusy is the value y in the alignment term "xn + y" described
95 * earlier. It must have a value between 0 and 7, inclusive.
96 */
97int
98inet6_option_append(cmsg, typep, multx, plusy)
99 struct cmsghdr *cmsg;
100 const u_int8_t *typep;
101 int multx;
102 int plusy;
103{
104 int padlen, optlen, off;
105 register u_char *bp = (u_char *)cmsg + cmsg->cmsg_len;
106 struct ip6_ext *eh = (struct ip6_ext *)CMSG_DATA(cmsg);
107
108 /* argument validation */
109 if (multx != 1 && multx != 2 && multx != 4 && multx != 8)
110 return(-1);
111 if (plusy < 0 || plusy > 7)
112 return(-1);
113 if (typep[0] > 255)
114 return(-1);
115
116 /*
117 * If this is the first option, allocate space for the
118 * first 2 bytes(for next header and length fields) of
119 * the option header.
120 */
121 if (bp == (u_char *)eh) {
122 bp += 2;
123 cmsg->cmsg_len += 2;
124 }
125
126 /* calculate pad length before the option. */
127 off = bp - (u_char *)eh;
128 padlen = (((off % multx) + (multx - 1)) & ~(multx - 1)) -
129 (off % multx);
130 padlen += plusy;
131 padlen %= multx; /* keep the pad as short as possible */
132 /* insert padding */
133 inet6_insert_padopt(bp, padlen);
134 cmsg->cmsg_len += padlen;
135 bp += padlen;
136
137 /* copy the option */
138 if (typep[0] == IP6OPT_PAD1)
139 optlen = 1;
140 else
141 optlen = typep[1] + 2;
142 memcpy(bp, typep, optlen);
143 bp += optlen;
144 cmsg->cmsg_len += optlen;
145
146 /* calculate pad length after the option and insert the padding */
147 off = bp - (u_char *)eh;
148 padlen = ((off + 7) & ~7) - off;
149 inet6_insert_padopt(bp, padlen);
150 bp += padlen;
151 cmsg->cmsg_len += padlen;
152
153 /* update the length field of the ip6 option header */
154 eh->ip6e_len = ((bp - (u_char *)eh) >> 3) - 1;
155
156 return(0);
157}
158
159/*
160 * This function appends a Hop-by-Hop option or a Destination option
161 * into an ancillary data object that has been initialized by
162 * inet6_option_init(). This function returns a pointer to the 8-bit
163 * option type field that starts the option on success, or NULL on an
164 * error.
165 * The difference between this function and inet6_option_append() is
166 * that the latter copies the contents of a previously built option into
167 * the ancillary data object while the current function returns a
168 * pointer to the space in the data object where the option's TLV must
169 * then be built by the caller.
170 *
171 */
172u_int8_t *
173inet6_option_alloc(cmsg, datalen, multx, plusy)
174 struct cmsghdr *cmsg;
175 int datalen;
176 int multx;
177 int plusy;
178{
179 int padlen, off;
180 register u_int8_t *bp = (u_char *)cmsg + cmsg->cmsg_len;
181 u_int8_t *retval;
182 struct ip6_ext *eh = (struct ip6_ext *)CMSG_DATA(cmsg);
183
184 /* argument validation */
185 if (multx != 1 && multx != 2 && multx != 4 && multx != 8)
186 return(NULL);
187 if (plusy < 0 || plusy > 7)
188 return(NULL);
189
190 /*
191 * If this is the first option, allocate space for the
192 * first 2 bytes(for next header and length fields) of
193 * the option header.
194 */
195 if (bp == (u_char *)eh) {
196 bp += 2;
197 cmsg->cmsg_len += 2;
198 }
199
200 /* calculate pad length before the option. */
201 off = bp - (u_char *)eh;
202 padlen = (((off % multx) + (multx - 1)) & ~(multx - 1)) -
203 (off % multx);
204 padlen += plusy;
205 padlen %= multx; /* keep the pad as short as possible */
206 /* insert padding */
207 inet6_insert_padopt(bp, padlen);
208 cmsg->cmsg_len += padlen;
209 bp += padlen;
210
211 /* keep space to store specified length of data */
212 retval = bp;
213 bp += datalen;
214 cmsg->cmsg_len += datalen;
215
216 /* calculate pad length after the option and insert the padding */
217 off = bp - (u_char *)eh;
218 padlen = ((off + 7) & ~7) - off;
219 inet6_insert_padopt(bp, padlen);
220 bp += padlen;
221 cmsg->cmsg_len += padlen;
222
223 /* update the length field of the ip6 option header */
224 eh->ip6e_len = ((bp - (u_char *)eh) >> 3) - 1;
225
226 return(retval);
227}
228
229/*
230 * This function processes the next Hop-by-Hop option or Destination
231 * option in an ancillary data object. If another option remains to be
232 * processed, the return value of the function is 0 and *tptrp points to
233 * the 8-bit option type field (which is followed by the 8-bit option
234 * data length, followed by the option data). If no more options remain
235 * to be processed, the return value is -1 and *tptrp is NULL. If an
236 * error occurs, the return value is -1 and *tptrp is not NULL.
237 * (RFC 2292, 6.3.5)
238 */
239int
240inet6_option_next(cmsg, tptrp)
241 const struct cmsghdr *cmsg;
242 u_int8_t **tptrp;
243{
244 struct ip6_ext *ip6e;
245 int hdrlen, optlen;
246 u_int8_t *lim;
247
248 if (cmsg->cmsg_level != IPPROTO_IPV6 ||
249 (cmsg->cmsg_type != IPV6_HOPOPTS &&
250 cmsg->cmsg_type != IPV6_DSTOPTS))
251 return(-1);
252
253 /* message length validation */
254 if (cmsg->cmsg_len < CMSG_SPACE(sizeof(struct ip6_ext)))
255 return(-1);
256 ip6e = (struct ip6_ext *)CMSG_DATA(cmsg);
257 hdrlen = (ip6e->ip6e_len + 1) << 3;
258 if (cmsg->cmsg_len < CMSG_SPACE(hdrlen))
259 return(-1);
260
261 /*
262 * If the caller does not specify the starting point,
263 * simply return the 1st option.
264 * Otherwise, search the option list for the next option.
265 */
266 lim = (u_int8_t *)ip6e + hdrlen;
267 if (*tptrp == NULL)
268 *tptrp = (u_int8_t *)(ip6e + 1);
269 else {
270 if ((optlen = ip6optlen(*tptrp, lim)) == 0)
271 return(-1);
272
273 *tptrp = *tptrp + optlen;
274 }
275 if (*tptrp >= lim) { /* there is no option */
276 *tptrp = NULL;
277 return(-1);
278 }
279 /*
280 * Finally, checks if the next option is safely stored in the
281 * cmsg data.
282 */
283 if (ip6optlen(*tptrp, lim) == 0)
284 return(-1);
285 else
286 return(0);
287}
288
289/*
290 * This function is similar to the inet6_option_next() function,
291 * except this function lets the caller specify the option type to be
292 * searched for, instead of always returning the next option in the
293 * ancillary data object.
294 * Note: RFC 2292 says the type of tptrp is u_int8_t *, but we think
295 * it's a typo. The variable should be type of u_int8_t **.
296 */
297int
298inet6_option_find(cmsg, tptrp, type)
299 const struct cmsghdr *cmsg;
300 u_int8_t **tptrp;
301 int type;
302{
303 struct ip6_ext *ip6e;
304 int hdrlen, optlen;
305 u_int8_t *optp, *lim;
306
307 if (cmsg->cmsg_level != IPPROTO_IPV6 ||
308 (cmsg->cmsg_type != IPV6_HOPOPTS &&
309 cmsg->cmsg_type != IPV6_DSTOPTS))
310 return(-1);
311
312 /* message length validation */
313 if (cmsg->cmsg_len < CMSG_SPACE(sizeof(struct ip6_ext)))
314 return(-1);
315 ip6e = (struct ip6_ext *)CMSG_DATA(cmsg);
316 hdrlen = (ip6e->ip6e_len + 1) << 3;
317 if (cmsg->cmsg_len < CMSG_SPACE(hdrlen))
318 return(-1);
319
320 /*
321 * If the caller does not specify the starting point,
322 * search from the beginning of the option list.
323 * Otherwise, search from *the next option* of the specified point.
324 */
325 lim = (u_int8_t *)ip6e + hdrlen;
326 if (*tptrp == NULL)
327 *tptrp = (u_int8_t *)(ip6e + 1);
328 else {
329 if ((optlen = ip6optlen(*tptrp, lim)) == 0)
330 return(-1);
331
332 *tptrp = *tptrp + optlen;
333 }
334 for (optp = *tptrp; optp < lim; optp += optlen) {
335 if (*optp == type) {
336 *tptrp = optp;
337 return(0);
338 }
339 if ((optlen = ip6optlen(optp, lim)) == 0)
340 return(-1);
341 }
342
343 /* search failed */
344 *tptrp = NULL;
345 return(-1);
346}
347
348/*
349 * Calculate the length of a given IPv6 option. Also checks
350 * if the option is safely stored in user's buffer according to the
351 * calculated length and the limitation of the buffer.
352 */
353static int
354ip6optlen(opt, lim)
355 u_int8_t *opt, *lim;
356{
357 int optlen;
358
359 if (*opt == IP6OPT_PAD1)
360 optlen = 1;
361 else {
362 /* is there enough space to store type and len? */
363 if (opt + 2 > lim)
364 return(0);
365 optlen = *(opt + 1) + 2;
366 }
367 if (opt + optlen <= lim)
368 return(optlen);
369
370 return(0);
371}
372
373static void
374inet6_insert_padopt(u_char *p, int len)
375{
376 switch(len) {
377 case 0:
378 return;
379 case 1:
380 p[0] = IP6OPT_PAD1;
381 return;
382 default:
383 p[0] = IP6OPT_PADN;
384 p[1] = len - 2;
385 memset(&p[2], 0, len - 2);
386 return;
387 }
388}
diff --git a/src/lib/libc/net/ipx.3 b/src/lib/libc/net/ipx.3
new file mode 100644
index 0000000000..21c57a355d
--- /dev/null
+++ b/src/lib/libc/net/ipx.3
@@ -0,0 +1,127 @@
1.\" $OpenBSD: ipx.3,v 1.8 2001/08/02 20:37:35 hugh Exp $
2.\"
3.\" Copyright (c) 1986, 1991, 1993
4.\" The Regents of the University of California. All rights reserved.
5.\"
6.\" Redistribution and use in source and binary forms, with or without
7.\" modification, are permitted provided that the following conditions
8.\" are met:
9.\" 1. Redistributions of source code must retain the above copyright
10.\" notice, this list of conditions and the following disclaimer.
11.\" 2. Redistributions in binary form must reproduce the above copyright
12.\" notice, this list of conditions and the following disclaimer in the
13.\" documentation and/or other materials provided with the distribution.
14.\" 3. All advertising materials mentioning features or use of this software
15.\" must display the following acknowledgement:
16.\" This product includes software developed by the University of
17.\" California, Berkeley and its contributors.
18.\" 4. Neither the name of the University nor the names of its contributors
19.\" may be used to endorse or promote products derived from this software
20.\" without specific prior written permission.
21.\"
22.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32.\" SUCH DAMAGE.
33.\"
34.Dd June 4, 1993
35.Dt IPX 3
36.Os
37.Sh NAME
38.Nm ipx_addr ,
39.Nm ipx_ntoa
40.Nd IPX address conversion routines
41.Sh SYNOPSIS
42.Fd #include <sys/types.h>
43.Fd #include <netipx/ipx.h>
44.Ft struct ipx_addr
45.Fn ipx_addr "const char *cp"
46.Ft char *
47.Fn ipx_ntoa "struct ipx_addr ipx"
48.Sh DESCRIPTION
49The routine
50.Fn ipx_addr
51interprets character strings representing
52.Tn IPX
53addresses, returning binary information suitable
54for use in system calls.
55The routine
56.Fn ipx_ntoa
57takes
58.Tn IPX
59addresses and returns
60.Tn ASCII
61strings representing the address in a
62notation in common use:
63.Bd -filled -offset indent
64<network number>.<host number>.<port number>
65.Ed
66.Pp
67Trailing zero fields are suppressed, and each number is printed in hexadecimal,
68in a format suitable for input to
69.Fn ipx_addr .
70Any fields lacking super-decimal digits will have a
71trailing
72.Sq H
73appended.
74.Pp
75An effort has been made to ensure that
76.Fn ipx_addr
77be compatible with most formats in common use.
78It will first separate an address into 1 to 3 fields using a single delimiter
79chosen from
80period
81.Pq Ql \&. ,
82colon
83.Pq Ql \&: ,
84or pound-sign
85.Pq Ql # .
86Each field is then examined for byte separators (colon or period).
87If there are byte separators, each subfield separated is taken to be
88a small hexadecimal number, and the entirety is taken as a network-byte-ordered
89quantity to be zero extended in the high-network-order bytes.
90Next, the field is inspected for hyphens, in which case
91the field is assumed to be a number in decimal notation
92with hyphens separating the millenia.
93Next, the field is assumed to be a number:
94It is interpreted
95as hexadecimal if there is a leading
96.Ql 0x
97(as in C),
98a trailing
99.Sq H
100(as in Mesa), or there are any super-decimal digits present.
101It is interpreted as octal is there is a leading
102.Ql 0
103and there are no super-octal digits.
104Otherwise, it is converted as a decimal number.
105.Sh RETURN VALUES
106None.
107(See
108.Sx BUGS . )
109.Sh SEE ALSO
110.Xr ns 4 ,
111.Xr hosts 5 ,
112.Xr networks 5
113.Sh HISTORY
114The precursor
115.Fn ns_addr
116and
117.Fn ns_ntoa
118functions appeared in
119.Bx 4.3 .
120.Sh BUGS
121The string returned by
122.Fn ipx_ntoa
123resides in a static memory area.
124The function
125.Fn ipx_addr
126should diagnose improperly formed input, and there should be an unambiguous
127way to recognize this.
diff --git a/src/lib/libc/net/ipx_addr.c b/src/lib/libc/net/ipx_addr.c
new file mode 100644
index 0000000000..0d225e281b
--- /dev/null
+++ b/src/lib/libc/net/ipx_addr.c
@@ -0,0 +1,228 @@
1/*
2 * Copyright (c) 1986, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * J.Q. Johnson.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * from @(#)ipx_addr.c
37 */
38
39#if defined(LIBC_SCCS) && !defined(lint)
40static char rcsid[] = "$OpenBSD: ipx_addr.c,v 1.5 2001/06/27 00:58:55 lebel Exp $";
41#endif /* LIBC_SCCS and not lint */
42
43#include <sys/param.h>
44#include <netipx/ipx.h>
45#include <stdio.h>
46#include <string.h>
47
48static struct ipx_addr addr, zero_addr;
49
50static void Field(), cvtbase();
51
52struct ipx_addr
53ipx_addr(name)
54 const char *name;
55{
56 char separator;
57 char *hostname, *socketname, *cp;
58 char buf[50];
59
60 strlcpy(buf, name, sizeof(buf));
61
62 /*
63 * First, figure out what he intends as a field separtor.
64 * Despite the way this routine is written, the prefered
65 * form 2-272.AA001234H.01777, i.e. XDE standard.
66 * Great efforts are made to insure backward compatibility.
67 */
68 if ((hostname = strchr(buf, '#')))
69 separator = '#';
70 else {
71 hostname = strchr(buf, '.');
72 if ((cp = strchr(buf, ':')) &&
73 ((hostname && cp < hostname) || (hostname == 0))) {
74 hostname = cp;
75 separator = ':';
76 } else
77 separator = '.';
78 }
79 if (hostname)
80 *hostname++ = 0;
81
82 addr = zero_addr;
83 Field(buf, addr.ipx_net.c_net, 4);
84 if (hostname == 0)
85 return (addr); /* No separator means net only */
86
87 socketname = strchr(hostname, separator);
88 if (socketname) {
89 *socketname++ = 0;
90 Field(socketname, (u_char *)&addr.ipx_port, 2);
91 }
92
93 Field(hostname, addr.ipx_host.c_host, 6);
94
95 return (addr);
96}
97
98static void
99Field(buf, out, len)
100 char *buf;
101 u_char *out;
102 int len;
103{
104 register char *bp = buf;
105 int i, ibase, base16 = 0, base10 = 0, clen = 0;
106 int hb[6], *hp;
107 char *fmt;
108
109 /*
110 * first try 2-273#2-852-151-014#socket
111 */
112 if ((*buf != '-') &&
113 (1 < (i = sscanf(buf, "%d-%d-%d-%d-%d",
114 &hb[0], &hb[1], &hb[2], &hb[3], &hb[4])))) {
115 cvtbase(1000L, 256, hb, i, out, len);
116 return;
117 }
118 /*
119 * try form 8E1#0.0.AA.0.5E.E6#socket
120 */
121 if (1 < (i = sscanf(buf,"%x.%x.%x.%x.%x.%x",
122 &hb[0], &hb[1], &hb[2], &hb[3], &hb[4], &hb[5]))) {
123 cvtbase(256L, 256, hb, i, out, len);
124 return;
125 }
126 /*
127 * try form 8E1#0:0:AA:0:5E:E6#socket
128 */
129 if (1 < (i = sscanf(buf,"%x:%x:%x:%x:%x:%x",
130 &hb[0], &hb[1], &hb[2], &hb[3], &hb[4], &hb[5]))) {
131 cvtbase(256L, 256, hb, i, out, len);
132 return;
133 }
134 /*
135 * This is REALLY stretching it but there was a
136 * comma notation separting shorts -- definitely non standard
137 */
138 if (1 < (i = sscanf(buf,"%x,%x,%x",
139 &hb[0], &hb[1], &hb[2]))) {
140 hb[0] = htons(hb[0]); hb[1] = htons(hb[1]);
141 hb[2] = htons(hb[2]);
142 cvtbase(65536L, 256, hb, i, out, len);
143 return;
144 }
145
146 /* Need to decide if base 10, 16 or 8 */
147 while (*bp) switch (*bp++) {
148
149 case '0': case '1': case '2': case '3': case '4': case '5':
150 case '6': case '7': case '-':
151 break;
152
153 case '8': case '9':
154 base10 = 1;
155 break;
156
157 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
158 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
159 base16 = 1;
160 break;
161
162 case 'x': case 'X':
163 *--bp = '0';
164 base16 = 1;
165 break;
166
167 case 'h': case 'H':
168 base16 = 1;
169 /* fall into */
170
171 default:
172 *--bp = 0; /* Ends Loop */
173 }
174 if (base16) {
175 fmt = "%3x";
176 ibase = 4096;
177 } else if (base10 == 0 && *buf == '0') {
178 fmt = "%3o";
179 ibase = 512;
180 } else {
181 fmt = "%3d";
182 ibase = 1000;
183 }
184
185 for (bp = buf; *bp++; ) clen++;
186 if (clen == 0) clen++;
187 if (clen > 18) clen = 18;
188 i = ((clen - 1) / 3) + 1;
189 bp = clen + buf - 3;
190 hp = hb + i - 1;
191
192 while (hp > hb) {
193 (void)sscanf(bp, fmt, hp);
194 bp[0] = 0;
195 hp--;
196 bp -= 3;
197 }
198 (void)sscanf(buf, fmt, hp);
199 cvtbase((long)ibase, 256, hb, i, out, len);
200}
201
202static void
203cvtbase(oldbase,newbase,input,inlen,result,reslen)
204 long oldbase;
205 int newbase;
206 int input[];
207 int inlen;
208 unsigned char result[];
209 int reslen;
210{
211 int d, e;
212 long sum;
213
214 e = 1;
215 while (e > 0 && reslen > 0) {
216 d = 0; e = 0; sum = 0;
217 /* long division: input=input/newbase */
218 while (d < inlen) {
219 sum = sum*oldbase + (long) input[d];
220 e += (sum > 0);
221 input[d++] = sum / newbase;
222 sum %= newbase;
223 }
224 result[--reslen] = sum; /* accumulate remainder */
225 }
226 for (d=0; d < reslen; d++)
227 result[d] = 0;
228}
diff --git a/src/lib/libc/net/ipx_ntoa.c b/src/lib/libc/net/ipx_ntoa.c
new file mode 100644
index 0000000000..598c94d599
--- /dev/null
+++ b/src/lib/libc/net/ipx_ntoa.c
@@ -0,0 +1,58 @@
1/*
2 * Copyright (c) 1986, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#if defined(LIBC_SCCS) && !defined(lint)
35static char rcsid[] = "$OpenBSD: ipx_ntoa.c,v 1.3 2002/05/24 21:22:37 deraadt Exp $";
36#endif /* LIBC_SCCS and not lint */
37
38#include <sys/param.h>
39#include <netipx/ipx.h>
40#include <stdio.h>
41
42char *
43ipx_ntoa(addr)
44 struct ipx_addr addr;
45{
46 static char obuf[] = "xxxx.xx:xx:xx:xx:xx:xx.uuuuu";
47
48 snprintf(obuf, sizeof obuf, "%8xH.%02x:%02x:%02x:%02x:%02x:%02x.%u",
49 ntohl(addr.ipx_net.l_net),
50 addr.ipx_host.c_host[0],
51 addr.ipx_host.c_host[1],
52 addr.ipx_host.c_host[2],
53 addr.ipx_host.c_host[3],
54 addr.ipx_host.c_host[4],
55 addr.ipx_host.c_host[5],
56 ntohs(addr.ipx_port));
57 return (obuf);
58}
diff --git a/src/lib/libc/net/iso_addr.3 b/src/lib/libc/net/iso_addr.3
new file mode 100644
index 0000000000..8655a63973
--- /dev/null
+++ b/src/lib/libc/net/iso_addr.3
@@ -0,0 +1,111 @@
1.\" $OpenBSD: iso_addr.3,v 1.4 1999/07/05 06:08:05 aaron Exp $
2.\"
3.\" Copyright (c) 1993
4.\" The Regents of the University of California. All rights reserved.
5.\"
6.\" Redistribution and use in source and binary forms, with or without
7.\" modification, are permitted provided that the following conditions
8.\" are met:
9.\" 1. Redistributions of source code must retain the above copyright
10.\" notice, this list of conditions and the following disclaimer.
11.\" 2. Redistributions in binary form must reproduce the above copyright
12.\" notice, this list of conditions and the following disclaimer in the
13.\" documentation and/or other materials provided with the distribution.
14.\" 3. All advertising materials mentioning features or use of this software
15.\" must display the following acknowledgement:
16.\" This product includes software developed by the University of
17.\" California, Berkeley and its contributors.
18.\" 4. Neither the name of the University nor the names of its contributors
19.\" may be used to endorse or promote products derived from this software
20.\" without specific prior written permission.
21.\"
22.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32.\" SUCH DAMAGE.
33.\"
34.Dd June 4, 1993
35.Dt ISO_ADDR 3
36.Os
37.Sh NAME
38.Nm iso_addr ,
39.Nm iso_ntoa
40.Nd "network address conversion routines for Open System Interconnection"
41.Sh SYNOPSIS
42.Fd #include <sys/types.h>
43.Fd #include <netiso/iso.h>
44.Ft struct iso_addr *
45.Fn iso_addr "char *cp"
46.Ft char *
47.Fn iso_ntoa "struct iso_addr *isoa"
48.Sh DESCRIPTION
49The routine
50.Fn iso_addr
51interprets character strings representing
52.Tn OSI
53addresses, returning binary information suitable
54for use in system calls.
55The routine
56.Fn iso_ntoa
57takes
58.Tn OSI
59addresses and returns
60.Tn ASCII
61strings representing NSAPs (network service
62access points) in a
63notation inverse to that accepted by
64.Fn iso_addr .
65.Pp
66Unfortunately, no universal standard exists for representing
67.Tn OSI
68network addresses.
69.Pp
70The format employed by
71.Fn iso_addr
72is a sequence of hexadecimal
73.Dq digits
74(optionally separated by periods),
75of the form:
76.Bd -filled -offset indent
77<hex digits>.<hex digits>.<hex digits>
78.Ed
79.Pp
80Each pair of hexadecimal digits represents a byte
81with the leading digit indicating the higher-ordered bits.
82A period following an even number of bytes has no
83effect (but may be used to increase legibility).
84A period following an odd number of bytes has the
85effect of causing the byte of address being translated
86to have its higher order bits filled with zeros.
87.Sh RETURN VALUES
88.Fn iso_ntoa
89always returns a null terminated string.
90.Fn iso_addr
91always returns a pointer to a
92.Li struct iso_addr .
93(See
94.Sx BUGS . )
95.Sh SEE ALSO
96.Xr iso 4
97.Sh HISTORY
98The
99.Fn iso_addr
100and
101.Fn iso_ntoa
102functions appeared in
103.Bx 4.3 Reno .
104.Sh BUGS
105The returned values
106reside in a static memory area.
107.Pp
108The function
109.Fn iso_addr
110should diagnose improperly formed input, and there should be an unambiguous
111way to recognize this.
diff --git a/src/lib/libc/net/iso_addr.c b/src/lib/libc/net/iso_addr.c
new file mode 100644
index 0000000000..01561e395b
--- /dev/null
+++ b/src/lib/libc/net/iso_addr.c
@@ -0,0 +1,119 @@
1/*
2 * Copyright (c) 1989, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#if defined(LIBC_SCCS) && !defined(lint)
35static char rcsid[] = "$OpenBSD: iso_addr.c,v 1.2 1996/08/19 08:29:23 tholo Exp $";
36#endif /* LIBC_SCCS and not lint */
37
38#include <sys/types.h>
39#include <netiso/iso.h>
40#include <string.h>
41
42/* States*/
43#define VIRGIN 0
44#define GOTONE 1
45#define GOTTWO 2
46/* Inputs */
47#define DIGIT (4*0)
48#define END (4*1)
49#define DELIM (4*2)
50
51struct iso_addr *
52iso_addr(addr)
53 register const char *addr;
54{
55 static struct iso_addr out_addr;
56 register char *cp = out_addr.isoa_genaddr;
57 char *cplim = cp + sizeof(out_addr.isoa_genaddr);
58 register int byte = 0, state = VIRGIN, new;
59
60 bzero((char *)&out_addr, sizeof(out_addr));
61 do {
62 if ((*addr >= '0') && (*addr <= '9')) {
63 new = *addr - '0';
64 } else if ((*addr >= 'a') && (*addr <= 'f')) {
65 new = *addr - 'a' + 10;
66 } else if ((*addr >= 'A') && (*addr <= 'F')) {
67 new = *addr - 'A' + 10;
68 } else if (*addr == 0)
69 state |= END;
70 else
71 state |= DELIM;
72 addr++;
73 switch (state /* | INPUT */) {
74 case GOTTWO | DIGIT:
75 *cp++ = byte; /*FALLTHROUGH*/
76 case VIRGIN | DIGIT:
77 state = GOTONE; byte = new; continue;
78 case GOTONE | DIGIT:
79 state = GOTTWO; byte = new + (byte << 4); continue;
80 default: /* | DELIM */
81 state = VIRGIN; *cp++ = byte; byte = 0; continue;
82 case GOTONE | END:
83 case GOTTWO | END:
84 *cp++ = byte; /* FALLTHROUGH */
85 case VIRGIN | END:
86 break;
87 }
88 break;
89 } while (cp < cplim);
90 out_addr.isoa_len = cp - out_addr.isoa_genaddr;
91 return (&out_addr);
92}
93static char hexlist[] = "0123456789abcdef";
94
95char *
96iso_ntoa(isoa)
97 const struct iso_addr *isoa;
98{
99 static char obuf[64];
100 register char *out = obuf;
101 register int i;
102 register u_char *in = (u_char *)isoa->isoa_genaddr;
103 u_char *inlim = in + isoa->isoa_len;
104
105 out[1] = 0;
106 while (in < inlim) {
107 i = *in++;
108 *out++ = '.';
109 if (i > 0xf) {
110 out[1] = hexlist[i & 0xf];
111 i >>= 4;
112 out[0] = hexlist[i];
113 out += 2;
114 } else
115 *out++ = hexlist[i];
116 }
117 *out = 0;
118 return(obuf + 1);
119}
diff --git a/src/lib/libc/net/link_addr.3 b/src/lib/libc/net/link_addr.3
new file mode 100644
index 0000000000..29c2449f77
--- /dev/null
+++ b/src/lib/libc/net/link_addr.3
@@ -0,0 +1,131 @@
1.\" $OpenBSD: link_addr.3,v 1.7 2000/04/18 03:01:32 aaron Exp $
2.\"
3.\" Copyright (c) 1993
4.\" The Regents of the University of California. All rights reserved.
5.\"
6.\" This code is derived from software contributed to Berkeley by
7.\" Donn Seeley at BSDI.
8.\"
9.\" Redistribution and use in source and binary forms, with or without
10.\" modification, are permitted provided that the following conditions
11.\" are met:
12.\" 1. Redistributions of source code must retain the above copyright
13.\" notice, this list of conditions and the following disclaimer.
14.\" 2. Redistributions in binary form must reproduce the above copyright
15.\" notice, this list of conditions and the following disclaimer in the
16.\" documentation and/or other materials provided with the distribution.
17.\" 3. All advertising materials mentioning features or use of this software
18.\" must display the following acknowledgement:
19.\" This product includes software developed by the University of
20.\" California, Berkeley and its contributors.
21.\" 4. Neither the name of the University nor the names of its contributors
22.\" may be used to endorse or promote products derived from this software
23.\" without specific prior written permission.
24.\"
25.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35.\" SUCH DAMAGE.
36.\"
37.Dd July 28, 1993
38.Dt LINK_ADDR 3
39.Os
40.Sh NAME
41.Nm link_addr ,
42.Nm link_ntoa
43.Nd elementary address specification routines for link level access
44.Sh SYNOPSIS
45.Fd #include <sys/types.h>
46.Fd #include <sys/socket.h>
47.Fd #include <net/if_dl.h>
48.Ft void
49.Fn link_addr "const char *addr" "struct sockaddr_dl *sdl"
50.Ft char *
51.Fn link_ntoa "const struct sockaddr_dl *sdl"
52.Sh DESCRIPTION
53The
54.Fn link_addr
55function interprets character strings representing
56link-level addresses, returning binary information suitable
57for use in system calls.
58.Fn link_ntoa
59takes
60a link-level
61address and returns an
62.Tn ASCII
63string representing some of the information present,
64including the link level address itself, and the interface name
65or number, if present.
66This facility is experimental and is
67still subject to change.
68.Pp
69For
70.Fn link_addr ,
71the string
72.Fa addr
73may contain
74an optional network interface identifier of the form
75.Dq name unit-number ,
76suitable for the first argument to
77.Xr ifconfig 8 ,
78followed in all cases by a colon and
79an interface address in the form of
80groups of hexadecimal digits
81separated by periods.
82Each group represents a byte of address;
83address bytes are filled left to right from
84low order bytes through high order bytes.
85.Pp
86.\" A regular expression may make this format clearer:
87.\" .Bd -literal -offset indent
88.\" ([a-z]+[0-9]+:)?[0-9a-f]+(\e.[0-9a-f]+)*
89.\" .Ed
90.\" .Pp
91Thus
92.Li le0:8.0.9.13.d.30
93represents an Ethernet address
94to be transmitted on the first Lance Ethernet interface.
95.Sh RETURN VALUES
96.Fn link_ntoa
97always returns a null-terminated string.
98.Fn link_addr
99has no return value.
100(See
101.Sx BUGS . )
102.Sh SEE ALSO
103.Xr iso 4 ,
104.Xr ifconfig 8
105.Sh HISTORY
106The
107.Fn link_addr
108and
109.Fn link_ntoa
110functions appeared in
111.Bx 4.3 Reno .
112.Sh BUGS
113The returned values for link_ntoa
114reside in a static memory area.
115.Pp
116The function
117.Fn link_addr
118should diagnose improperly formed input, and there should be an unambiguous
119way to recognize this.
120.Pp
121If the
122.Fa sdl_len
123field of the link socket address
124.Fa sdl
125is 0,
126.Fn link_ntoa
127will not insert a colon before the interface address bytes.
128If this translated address is given to
129.Fn link_addr
130without inserting an initial colon,
131the latter will not interpret it correctly.
diff --git a/src/lib/libc/net/linkaddr.c b/src/lib/libc/net/linkaddr.c
new file mode 100644
index 0000000000..fb522f3233
--- /dev/null
+++ b/src/lib/libc/net/linkaddr.c
@@ -0,0 +1,158 @@
1/*-
2 * Copyright (c) 1990, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#if defined(LIBC_SCCS) && !defined(lint)
35static char rcsid[] = "$OpenBSD: linkaddr.c,v 1.2 1996/08/19 08:29:27 tholo Exp $";
36#endif /* LIBC_SCCS and not lint */
37
38#include <sys/types.h>
39#include <sys/socket.h>
40#include <net/if_dl.h>
41#include <string.h>
42
43/* States*/
44#define NAMING 0
45#define GOTONE 1
46#define GOTTWO 2
47#define RESET 3
48/* Inputs */
49#define DIGIT (4*0)
50#define END (4*1)
51#define DELIM (4*2)
52#define LETTER (4*3)
53
54void
55link_addr(addr, sdl)
56 register const char *addr;
57 register struct sockaddr_dl *sdl;
58{
59 register char *cp = sdl->sdl_data;
60 char *cplim = sdl->sdl_len + (char *)sdl;
61 register int byte = 0, state = NAMING, new;
62
63 bzero((char *)&sdl->sdl_family, sdl->sdl_len - 1);
64 sdl->sdl_family = AF_LINK;
65 do {
66 state &= ~LETTER;
67 if ((*addr >= '0') && (*addr <= '9')) {
68 new = *addr - '0';
69 } else if ((*addr >= 'a') && (*addr <= 'f')) {
70 new = *addr - 'a' + 10;
71 } else if ((*addr >= 'A') && (*addr <= 'F')) {
72 new = *addr - 'A' + 10;
73 } else if (*addr == 0) {
74 state |= END;
75 } else if (state == NAMING &&
76 (((*addr >= 'A') && (*addr <= 'Z')) ||
77 ((*addr >= 'a') && (*addr <= 'z'))))
78 state |= LETTER;
79 else
80 state |= DELIM;
81 addr++;
82 switch (state /* | INPUT */) {
83 case NAMING | DIGIT:
84 case NAMING | LETTER:
85 *cp++ = addr[-1];
86 continue;
87 case NAMING | DELIM:
88 state = RESET;
89 sdl->sdl_nlen = cp - sdl->sdl_data;
90 continue;
91 case GOTTWO | DIGIT:
92 *cp++ = byte;
93 /* FALLTHROUGH */
94 case RESET | DIGIT:
95 state = GOTONE;
96 byte = new;
97 continue;
98 case GOTONE | DIGIT:
99 state = GOTTWO;
100 byte = new + (byte << 4);
101 continue;
102 default: /* | DELIM */
103 state = RESET;
104 *cp++ = byte;
105 byte = 0;
106 continue;
107 case GOTONE | END:
108 case GOTTWO | END:
109 *cp++ = byte;
110 /* FALLTHROUGH */
111 case RESET | END:
112 break;
113 }
114 break;
115 } while (cp < cplim);
116 sdl->sdl_alen = cp - LLADDR(sdl);
117 new = cp - (char *)sdl;
118 if (new > sizeof(*sdl))
119 sdl->sdl_len = new;
120 return;
121}
122
123static char hexlist[] = "0123456789abcdef";
124
125char *
126link_ntoa(sdl)
127 register const struct sockaddr_dl *sdl;
128{
129 static char obuf[64];
130 register char *out = obuf;
131 register int i;
132 register u_char *in = (u_char *)LLADDR(sdl);
133 u_char *inlim = in + sdl->sdl_alen;
134 int firsttime = 1;
135
136 if (sdl->sdl_nlen) {
137 bcopy(sdl->sdl_data, obuf, sdl->sdl_nlen);
138 out += sdl->sdl_nlen;
139 if (sdl->sdl_alen)
140 *out++ = ':';
141 }
142 while (in < inlim) {
143 if (firsttime)
144 firsttime = 0;
145 else
146 *out++ = '.';
147 i = *in++;
148 if (i > 0xf) {
149 out[1] = hexlist[i & 0xf];
150 i >>= 4;
151 out[0] = hexlist[i];
152 out += 2;
153 } else
154 *out++ = hexlist[i];
155 }
156 *out = 0;
157 return (obuf);
158}
diff --git a/src/lib/libc/net/net_addrcmp.3 b/src/lib/libc/net/net_addrcmp.3
new file mode 100644
index 0000000000..f1ce4c8cd1
--- /dev/null
+++ b/src/lib/libc/net/net_addrcmp.3
@@ -0,0 +1,91 @@
1.\" $OpenBSD: net_addrcmp.3,v 1.3 2001/08/07 06:53:27 deraadt Exp $
2.\"
3.\" Copyright (c) 1999 Theo de Raadt
4.\"
5.\" Redistribution and use in source and binary forms, with or without
6.\" modification, are permitted provided that the following conditions
7.\" are met:
8.\" 1. Redistributions of source code must retain the above copyright
9.\" notice, this list of conditions and the following disclaimer.
10.\" 2. Redistributions in binary form must reproduce the above copyright
11.\" notice, this list of conditions and the following disclaimer in the
12.\" documentation and/or other materials provided with the distribution.
13.\"
14.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24.\"
25.Dd July 3, 1999
26.Dt NET_ADDRCMP 3
27.Os
28.Sh NAME
29.Nm net_addrcmp
30.Nd compare socket address structures
31.Sh SYNOPSIS
32.Fd #include <netdb.h>
33.Ft int
34.Fn net_addrcmp "struct sockaddr *sa1" "struct sockaddr *sa2"
35.Sh DESCRIPTION
36The
37.Fn net_addrcmp
38function compares two socket address structures,
39.Fa sa1
40and
41.Fa sa2 .
42.Sh RETURN VALUES
43If
44.Fa sa1
45and
46.Fa sa2
47are for the same address,
48.Fn net_addrcmp
49returns 0.
50.Pp
51The
52.Fa sa_len
53fields are compared first.
54If they do not match,
55.Fn net_addrcmp
56returns \-1 or 1 if
57.Li sa1->sa_len
58is less than or greater than
59.Li sa2->sa_len ,
60respectively.
61.Pp
62Next, the
63.Fa sa_family
64members are compared.
65If they do not match,
66.Fn net_addrcmp
67returns \-1 or 1 if
68.Li sa1->sa_family
69is less than or greater than
70.Li sa2->sa_family ,
71respectively.
72.Pp
73Lastly, if each socket address structure's
74.Fa sa_len
75and
76.Fa sa_family
77fields match,
78the protocol-specific data (the
79.Fa sa_data
80field) is compared.
81If there's a match, both
82.Fa sa1
83and
84.Fa sa2
85must refer to the same address, and 0 is returned; otherwise, a value >0
86or <0 is returned.
87.Sh HISTORY
88A
89.Fn net_addrcmp
90function was added in
91.Ox 2.5 .
diff --git a/src/lib/libc/net/net_addrcmp.c b/src/lib/libc/net/net_addrcmp.c
new file mode 100644
index 0000000000..c77a2fda48
--- /dev/null
+++ b/src/lib/libc/net/net_addrcmp.c
@@ -0,0 +1,68 @@
1/*
2 * Copyright (c) 1999 Theo de Raadt
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include <sys/types.h>
27#include <sys/socket.h>
28#include <sys/un.h>
29#include <netinet/in.h>
30#include <netns/ns.h>
31#include <string.h>
32
33int
34net_addrcmp(sa1, sa2)
35 struct sockaddr *sa1;
36 struct sockaddr *sa2;
37{
38
39 if (sa1->sa_len != sa2->sa_len)
40 return (sa1->sa_len < sa2->sa_len) ? -1 : 1;
41 if (sa1->sa_family != sa2->sa_family)
42 return (sa1->sa_family < sa2->sa_family) ? -1 : 1;
43
44 switch(sa1->sa_family) {
45 case AF_INET:
46 return (memcmp(&((struct sockaddr_in *)sa1)->sin_addr,
47 &((struct sockaddr_in *)sa2)->sin_addr,
48 sizeof(struct in_addr)));
49 case AF_INET6:
50 if (((struct sockaddr_in6 *)sa1)->sin6_scope_id !=
51 ((struct sockaddr_in6 *)sa2)->sin6_scope_id)
52 return (((struct sockaddr_in6 *)sa1)->sin6_scope_id <
53 ((struct sockaddr_in6 *)sa2)->sin6_scope_id)
54 ? -1 : 1;
55 return memcmp(&((struct sockaddr_in6 *)sa1)->sin6_addr,
56 &((struct sockaddr_in6 *)sa2)->sin6_addr,
57 sizeof(struct in6_addr));
58 case AF_NS:
59 return (memcmp(&((struct sockaddr_ns *)sa1)->sns_addr,
60 &((struct sockaddr_ns *)sa2)->sns_addr,
61 sizeof(struct ns_addr)));
62 case AF_LOCAL:
63 return (strcmp(((struct sockaddr_un *)sa1)->sun_path,
64 ((struct sockaddr_un *)sa1)->sun_path));
65 default:
66 return -1;
67 }
68}
diff --git a/src/lib/libc/net/ns.3 b/src/lib/libc/net/ns.3
new file mode 100644
index 0000000000..14e234c347
--- /dev/null
+++ b/src/lib/libc/net/ns.3
@@ -0,0 +1,131 @@
1.\" $OpenBSD: ns.3,v 1.7 2001/08/02 20:37:35 hugh Exp $
2.\"
3.\" Copyright (c) 1986, 1991, 1993
4.\" The Regents of the University of California. All rights reserved.
5.\"
6.\" Redistribution and use in source and binary forms, with or without
7.\" modification, are permitted provided that the following conditions
8.\" are met:
9.\" 1. Redistributions of source code must retain the above copyright
10.\" notice, this list of conditions and the following disclaimer.
11.\" 2. Redistributions in binary form must reproduce the above copyright
12.\" notice, this list of conditions and the following disclaimer in the
13.\" documentation and/or other materials provided with the distribution.
14.\" 3. All advertising materials mentioning features or use of this software
15.\" must display the following acknowledgement:
16.\" This product includes software developed by the University of
17.\" California, Berkeley and its contributors.
18.\" 4. Neither the name of the University nor the names of its contributors
19.\" may be used to endorse or promote products derived from this software
20.\" without specific prior written permission.
21.\"
22.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32.\" SUCH DAMAGE.
33.\"
34.Dd June 4, 1993
35.Dt NS 3
36.Os
37.Sh NAME
38.Nm ns_addr ,
39.Nm ns_ntoa
40.Nd Xerox
41.Tn NS Ns (tm)
42address conversion routines
43.Sh SYNOPSIS
44.Fd #include <sys/types.h>
45.Fd #include <netns/ns.h>
46.Ft struct ns_addr
47.Fn ns_addr "char *cp"
48.Ft char *
49.Fn ns_ntoa "struct ns_addr ns"
50.Sh DESCRIPTION
51The routine
52.Fn ns_addr
53interprets character strings representing
54.Tn XNS
55addresses, returning binary information suitable
56for use in system calls.
57The routine
58.Fn ns_ntoa
59takes
60.Tn XNS
61addresses and returns
62.Tn ASCII
63strings representing the address in a
64notation in common use in the Xerox Development Environment:
65.Bd -filled -offset indent
66<network number>.<host number>.<port number>
67.Ed
68.Pp
69Trailing zero fields are suppressed, and each number is printed in hexadecimal,
70in a format suitable for input to
71.Fn ns_addr .
72Any fields lacking super-decimal digits will have a
73trailing
74.Sq H
75appended.
76.Pp
77Unfortunately, no universal standard exists for representing
78.Tn XNS
79addresses.
80An effort has been made to ensure that
81.Fn ns_addr
82be compatible with most formats in common use.
83It will first separate an address into 1 to 3 fields using a single delimiter
84chosen from
85period
86.Pq Ql \&. ,
87colon
88.Pq Ql \&: ,
89or pound-sign
90.Ql # .
91Each field is then examined for byte separators (colon or period).
92If there are byte separators, each subfield separated is taken to be
93a small hexadecimal number, and the entirety is taken as a network-byte-ordered
94quantity to be zero extended in the high-network-order bytes.
95Next, the field is inspected for hyphens, in which case
96the field is assumed to be a number in decimal notation
97with hyphens separating the millenia.
98Next, the field is assumed to be a number:
99It is interpreted
100as hexadecimal if there is a leading
101.Ql 0x
102(as in C),
103a trailing
104.Sq H
105(as in Mesa), or there are any super-decimal digits present.
106It is interpreted as octal is there is a leading
107.Ql 0
108and there are no super-octal digits.
109Otherwise, it is converted as a decimal number.
110.Sh RETURN VALUES
111None.
112(See
113.Sx BUGS . )
114.Sh SEE ALSO
115.Xr hosts 5 ,
116.Xr networks 5
117.Sh HISTORY
118The
119.Fn ns_addr
120and
121.Fn ns_toa
122functions appeared in
123.Bx 4.3 .
124.Sh BUGS
125The string returned by
126.Fn ns_ntoa
127resides in a static memory area.
128The function
129.Fn ns_addr
130should diagnose improperly formed input, and there should be an unambiguous
131way to recognize this.
diff --git a/src/lib/libc/net/ns_addr.c b/src/lib/libc/net/ns_addr.c
new file mode 100644
index 0000000000..0d1b45858f
--- /dev/null
+++ b/src/lib/libc/net/ns_addr.c
@@ -0,0 +1,227 @@
1/*
2 * Copyright (c) 1986, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * J.Q. Johnson.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37#if defined(LIBC_SCCS) && !defined(lint)
38static char rcsid[] = "$OpenBSD: ns_addr.c,v 1.7 2002/02/16 21:27:23 millert Exp $";
39#endif /* LIBC_SCCS and not lint */
40
41#include <sys/param.h>
42#include <netns/ns.h>
43#include <stdio.h>
44#include <string.h>
45
46static struct ns_addr addr, zero_addr;
47
48static void Field(char *, u_int8_t *, int);
49static void cvtbase(long, int, int[], int, u_int8_t[], int);
50
51struct ns_addr
52ns_addr(name)
53 const char *name;
54{
55 char separator;
56 char *hostname, *socketname, *cp;
57 char buf[50];
58
59 strlcpy(buf, name, sizeof(buf));
60
61 /*
62 * First, figure out what he intends as a field separtor.
63 * Despite the way this routine is written, the prefered
64 * form 2-272.AA001234H.01777, i.e. XDE standard.
65 * Great efforts are made to insure backward compatibility.
66 */
67 if ((hostname = strchr(buf, '#')))
68 separator = '#';
69 else {
70 hostname = strchr(buf, '.');
71 if ((cp = strchr(buf, ':')) &&
72 ((hostname && cp < hostname) || (hostname == 0))) {
73 hostname = cp;
74 separator = ':';
75 } else
76 separator = '.';
77 }
78 if (hostname)
79 *hostname++ = 0;
80
81 addr = zero_addr;
82 Field(buf, addr.x_net.c_net, 4);
83 if (hostname == 0)
84 return (addr); /* No separator means net only */
85
86 socketname = strchr(hostname, separator);
87 if (socketname) {
88 *socketname++ = 0;
89 Field(socketname, (u_char *)&addr.x_port, 2);
90 }
91
92 Field(hostname, (u_char *)addr.x_host.c_host, 6);
93
94 return (addr);
95}
96
97static void
98Field(buf, out, len)
99 char *buf;
100 u_char *out;
101 int len;
102{
103 register char *bp = buf;
104 int i, ibase, base16 = 0, base10 = 0, clen = 0;
105 int hb[6], *hp;
106 char *fmt;
107
108 /*
109 * first try 2-273#2-852-151-014#socket
110 */
111 if ((*buf != '-') &&
112 (1 < (i = sscanf(buf, "%d-%d-%d-%d-%d",
113 &hb[0], &hb[1], &hb[2], &hb[3], &hb[4])))) {
114 cvtbase(1000L, 256, hb, i, out, len);
115 return;
116 }
117 /*
118 * try form 8E1#0.0.AA.0.5E.E6#socket
119 */
120 if (1 < (i = sscanf(buf,"%x.%x.%x.%x.%x.%x",
121 &hb[0], &hb[1], &hb[2], &hb[3], &hb[4], &hb[5]))) {
122 cvtbase(256L, 256, hb, i, out, len);
123 return;
124 }
125 /*
126 * try form 8E1#0:0:AA:0:5E:E6#socket
127 */
128 if (1 < (i = sscanf(buf,"%x:%x:%x:%x:%x:%x",
129 &hb[0], &hb[1], &hb[2], &hb[3], &hb[4], &hb[5]))) {
130 cvtbase(256L, 256, hb, i, out, len);
131 return;
132 }
133 /*
134 * This is REALLY stretching it but there was a
135 * comma notation separting shorts -- definitely non standard
136 */
137 if (1 < (i = sscanf(buf,"%x,%x,%x",
138 &hb[0], &hb[1], &hb[2]))) {
139 hb[0] = htons(hb[0]); hb[1] = htons(hb[1]);
140 hb[2] = htons(hb[2]);
141 cvtbase(65536L, 256, hb, i, out, len);
142 return;
143 }
144
145 /* Need to decide if base 10, 16 or 8 */
146 while (*bp) switch (*bp++) {
147
148 case '0': case '1': case '2': case '3': case '4': case '5':
149 case '6': case '7': case '-':
150 break;
151
152 case '8': case '9':
153 base10 = 1;
154 break;
155
156 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
157 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
158 base16 = 1;
159 break;
160
161 case 'x': case 'X':
162 *--bp = '0';
163 base16 = 1;
164 break;
165
166 case 'h': case 'H':
167 base16 = 1;
168 /* fall into */
169
170 default:
171 *--bp = 0; /* Ends Loop */
172 }
173 if (base16) {
174 fmt = "%3x";
175 ibase = 4096;
176 } else if (base10 == 0 && *buf == '0') {
177 fmt = "%3o";
178 ibase = 512;
179 } else {
180 fmt = "%3d";
181 ibase = 1000;
182 }
183
184 for (bp = buf; *bp++; ) clen++;
185 if (clen == 0) clen++;
186 if (clen > 18) clen = 18;
187 i = ((clen - 1) / 3) + 1;
188 bp = clen + buf - 3;
189 hp = hb + i - 1;
190
191 while (hp > hb) {
192 (void)sscanf(bp, fmt, hp);
193 bp[0] = 0;
194 hp--;
195 bp -= 3;
196 }
197 (void)sscanf(buf, fmt, hp);
198 cvtbase((long)ibase, 256, hb, i, out, len);
199}
200
201static void
202cvtbase(oldbase,newbase,input,inlen,result,reslen)
203 long oldbase;
204 int newbase;
205 int input[];
206 int inlen;
207 unsigned char result[];
208 int reslen;
209{
210 int d, e;
211 long sum;
212
213 e = 1;
214 while (e > 0 && reslen > 0) {
215 d = 0; e = 0; sum = 0;
216 /* long division: input=input/newbase */
217 while (d < inlen) {
218 sum = sum*oldbase + (long) input[d];
219 e += (sum > 0);
220 input[d++] = sum / newbase;
221 sum %= newbase;
222 }
223 result[--reslen] = sum; /* accumulate remainder */
224 }
225 for (d=0; d < reslen; d++)
226 result[d] = 0;
227}
diff --git a/src/lib/libc/net/ns_ntoa.c b/src/lib/libc/net/ns_ntoa.c
new file mode 100644
index 0000000000..5ff410e28a
--- /dev/null
+++ b/src/lib/libc/net/ns_ntoa.c
@@ -0,0 +1,104 @@
1/*
2 * Copyright (c) 1986, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#if defined(LIBC_SCCS) && !defined(lint)
35static char rcsid[] = "$OpenBSD: ns_ntoa.c,v 1.10 2002/07/25 21:12:47 deraadt Exp $";
36#endif /* LIBC_SCCS and not lint */
37
38#include <sys/param.h>
39#include <netns/ns.h>
40#include <stdio.h>
41
42static char *spectHex(char *);
43
44char *
45ns_ntoa(struct ns_addr addr)
46{
47 static char obuf[40];
48 union { union ns_net net_e; u_int32_t long_e; } net;
49 in_port_t port = htons(addr.x_port);
50 char *cp, *cp2;
51 u_char *up = addr.x_host.c_host;
52 u_char *uplim = up + 6;
53
54 net.net_e = addr.x_net;
55 snprintf(obuf, sizeof obuf, "%x", ntohl(net.long_e));
56 cp = spectHex(obuf);
57 cp2 = cp + 1;
58 while (*up==0 && up < uplim)
59 up++;
60 if (up == uplim) {
61 if (port) {
62 sprintf(cp, ".0");
63 cp += 2;
64 }
65 } else {
66 sprintf(cp, ".%x", *up++);
67 while (up < uplim) {
68 while (*cp)
69 cp++;
70 sprintf(cp, "%02x", *up++);
71 }
72 cp = spectHex(cp2);
73 }
74 if (port) {
75 sprintf(cp, ".%x", port);
76 spectHex(cp + 1);
77 }
78 return (obuf);
79}
80
81static char *
82spectHex(char *p0)
83{
84 int ok = 0, nonzero = 0;
85 char *p = p0;
86
87 for (; *p; p++) {
88 switch (*p) {
89 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
90 *p += ('A' - 'a');
91 /* fall into . . . */
92 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
93 ok = 1;
94 case '1': case '2': case '3': case '4': case '5':
95 case '6': case '7': case '8': case '9':
96 nonzero = 1;
97 }
98 }
99 if (nonzero && !ok) {
100 *p++ = 'H';
101 *p = 0;
102 }
103 return (p);
104}
diff --git a/src/lib/libc/net/nsap_addr.c b/src/lib/libc/net/nsap_addr.c
new file mode 100644
index 0000000000..22a5f8d66e
--- /dev/null
+++ b/src/lib/libc/net/nsap_addr.c
@@ -0,0 +1,109 @@
1/* $OpenBSD: nsap_addr.c,v 1.4 1997/07/09 01:08:45 millert Exp $ */
2
3/*
4 * Copyright (c) 1996 by Internet Software Consortium.
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
11 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
12 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
13 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
16 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
17 * SOFTWARE.
18 */
19
20#if defined(LIBC_SCCS) && !defined(lint)
21#if 0
22static char rcsid[] = "$From: nsap_addr.c,v 8.3 1996/08/05 08:31:35 vixie Exp $";
23#else
24static char rcsid[] = "$OpenBSD: nsap_addr.c,v 1.4 1997/07/09 01:08:45 millert Exp $";
25#endif
26#endif /* LIBC_SCCS and not lint */
27
28#include <sys/types.h>
29#include <sys/param.h>
30#include <sys/socket.h>
31#include <netinet/in.h>
32#include <arpa/nameser.h>
33#include <ctype.h>
34#include <resolv.h>
35
36static char
37xtob(c)
38 register int c;
39{
40 return (c - (((c >= '0') && (c <= '9')) ? '0' : '7'));
41}
42
43u_int
44inet_nsap_addr(ascii, binary, maxlen)
45 const char *ascii;
46 u_char *binary;
47 int maxlen;
48{
49 register u_char c, nib;
50 u_int len = 0;
51
52 while ((c = *ascii++) != '\0' && len < maxlen) {
53 if (c == '.' || c == '+' || c == '/')
54 continue;
55 if (!isascii(c))
56 return (0);
57 if (islower(c))
58 c = toupper(c);
59 if (isxdigit(c)) {
60 nib = xtob(c);
61 if ((c = *ascii++)) {
62 c = toupper(c);
63 if (isxdigit(c)) {
64 *binary++ = (nib << 4) | xtob(c);
65 len++;
66 } else
67 return (0);
68 }
69 else
70 return (0);
71 }
72 else
73 return (0);
74 }
75 return (len);
76}
77
78char *
79inet_nsap_ntoa(binlen, binary, ascii)
80 int binlen;
81 register const u_char *binary;
82 register char *ascii;
83{
84 register int nib;
85 int i;
86 static char tmpbuf[255*3];
87 char *start;
88
89 if (ascii)
90 start = ascii;
91 else {
92 ascii = tmpbuf;
93 start = tmpbuf;
94 }
95
96 if (binlen > 255)
97 binlen = 255;
98
99 for (i = 0; i < binlen; i++) {
100 nib = *binary >> 4;
101 *ascii++ = nib + (nib < 10 ? '0' : '7');
102 nib = *binary++ & 0x0f;
103 *ascii++ = nib + (nib < 10 ? '0' : '7');
104 if (((i % 2) == 0 && (i + 1) < binlen))
105 *ascii++ = '.';
106 }
107 *ascii = '\0';
108 return (start);
109}
diff --git a/src/lib/libc/net/ntohl.c b/src/lib/libc/net/ntohl.c
new file mode 100644
index 0000000000..7d3e227e60
--- /dev/null
+++ b/src/lib/libc/net/ntohl.c
@@ -0,0 +1,25 @@
1/*
2 * Written by J.T. Conklin <jtc@netbsd.org>.
3 * Public domain.
4 */
5
6#if defined(LIBC_SCCS) && !defined(lint)
7static char *rcsid = "$OpenBSD: ntohl.c,v 1.4 1996/12/12 03:19:56 tholo Exp $";
8#endif /* LIBC_SCCS and not lint */
9
10#include <sys/types.h>
11#include <machine/endian.h>
12
13#undef ntohl
14
15u_int32_t
16ntohl(x)
17 u_int32_t x;
18{
19#if BYTE_ORDER == LITTLE_ENDIAN
20 u_char *s = (u_char *)&x;
21 return (u_int32_t)(s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3]);
22#else
23 return x;
24#endif
25}
diff --git a/src/lib/libc/net/ntohs.c b/src/lib/libc/net/ntohs.c
new file mode 100644
index 0000000000..4c3ab33f31
--- /dev/null
+++ b/src/lib/libc/net/ntohs.c
@@ -0,0 +1,24 @@
1/*
2 * Written by J.T. Conklin <jtc@netbsd.org>.
3 * Public domain.
4 */
5
6#if defined(LIBC_SCCS) && !defined(lint)
7static char *rcsid = "$OpenBSD: ntohs.c,v 1.7 2002/02/19 19:39:36 millert Exp $";
8#endif /* LIBC_SCCS and not lint */
9
10#include <sys/types.h>
11#include <machine/endian.h>
12
13#undef ntohs
14
15u_int16_t
16ntohs(u_int16_t x)
17{
18#if BYTE_ORDER == LITTLE_ENDIAN
19 u_char *s = (u_char *) &x;
20 return (u_int16_t)(s[0] << 8 | s[1]);
21#else
22 return x;
23#endif
24}
diff --git a/src/lib/libc/net/rcmd.3 b/src/lib/libc/net/rcmd.3
new file mode 100644
index 0000000000..7cf5af9519
--- /dev/null
+++ b/src/lib/libc/net/rcmd.3
@@ -0,0 +1,270 @@
1.\" $OpenBSD: rcmd.3,v 1.24 2002/05/06 23:34:33 millert Exp $
2.\"
3.\" Copyright (c) 1983, 1991, 1993
4.\" The Regents of the University of California. All rights reserved.
5.\"
6.\" Redistribution and use in source and binary forms, with or without
7.\" modification, are permitted provided that the following conditions
8.\" are met:
9.\" 1. Redistributions of source code must retain the above copyright
10.\" notice, this list of conditions and the following disclaimer.
11.\" 2. Redistributions in binary form must reproduce the above copyright
12.\" notice, this list of conditions and the following disclaimer in the
13.\" documentation and/or other materials provided with the distribution.
14.\" 3. All advertising materials mentioning features or use of this software
15.\" must display the following acknowledgement:
16.\" This product includes software developed by the University of
17.\" California, Berkeley and its contributors.
18.\" 4. Neither the name of the University nor the names of its contributors
19.\" may be used to endorse or promote products derived from this software
20.\" without specific prior written permission.
21.\"
22.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32.\" SUCH DAMAGE.
33.\"
34.Dd June 4, 1993
35.Dt RCMD 3
36.Os
37.Sh NAME
38.Nm rcmd ,
39.Nm rcmd_af ,
40.Nm rresvport ,
41.Nm rresvport_af ,
42.Nm iruserok ,
43.Nm ruserok ,
44.Nm iruserok_sa
45.Nd routines for returning a stream to a remote command
46.Sh SYNOPSIS
47.Fd #include <unistd.h>
48.Ft int
49.Fn rcmd "char **ahost" "int inport" "const char *locuser" "const char *remuser" "const char *cmd" "int *fd2p"
50.Ft int
51.Fn rcmd_af "char **ahost" "int inport" "const char *locuser" "const char *remuser" "const char *cmd" "int *fd2p" "int af"
52.Ft int
53.Fn rresvport "int *port"
54.Ft int
55.Fn rresvport_af "int *port" "int af"
56.Ft int
57.Fn iruserok "u_int32_t raddr" "int superuser" "const char *ruser" "const char *luser"
58.Ft int
59.Fn ruserok "const char *rhost" "int superuser" "const char *ruser" "const char *luser"
60.Ft int
61.Fn iruserok_sa "const void *sa" "int salen" "int superuser" "const char *ruser"
62.Sh DESCRIPTION
63The
64.Fn rcmd
65function is used by the superuser to execute a command on a remote
66machine using an authentication scheme based on reserved
67port numbers.
68If the calling process is not setuid, the
69.Ev RSH
70environment variable is set, and
71.Fa inport
72is
73.Dq shell/tcp ,
74.Xr rcmdsh 3
75is called instead with the value of
76.Ev RSH .
77Alternately, if the user is not the superuser,
78.Fn rcmd
79will invoke
80.Xr rcmdsh 3
81to run the command via
82.Xr rsh 1 .
83While
84.Fn rcmd
85can handle IPv4 cases only,
86the
87.Fn rcmd_af
88function can handle other cases as well.
89.Pp
90The
91.Fn rresvport
92and
93.Fn rresvport_af
94functions return a descriptor to a socket
95with an address in the privileged port space.
96The
97.Fn iruserok
98and
99.Fn ruserok
100functions are used by servers
101to authenticate clients requesting service with
102.Fn rcmd .
103All four functions are present in the same file and are used
104by the
105.Xr rshd 8
106server (among others).
107.Fn iruserok_sa
108is an address family independent variant of
109.Fn iruserok .
110.Pp
111The
112.Fn rcmd
113function looks up the host
114.Fa *ahost
115using
116.Xr gethostbyname 3 ,
117returning \-1 if the host does not exist.
118Otherwise
119.Fa *ahost
120is set to the standard name of the host
121and a connection is established to a server
122residing at the well-known Internet port
123.Fa inport .
124If the user is not the superuser, the only valid port is
125.Dq shell/tcp
126(usually port 514).
127.Pp
128If the connection succeeds,
129a socket in the Internet domain of type
130.Dv SOCK_STREAM
131is returned to the caller, and given to the remote
132command as stdin and stdout.
133If
134.Fa fd2p
135is non-zero, then an auxiliary channel to a control
136process will be set up, and a descriptor for it will be placed
137in
138.Fa *fd2p .
139The control process will return diagnostic
140output from the command (unit 2) on this channel, and will also
141accept bytes on this channel as being
142.Tn UNIX
143signal numbers, to be
144forwarded to the process group of the command.
145If
146.Fa fd2p
147is
148.Va NULL ,
149then the standard error (unit 2 of the remote command) will be made
150the same as the standard output and no provision is made for sending
151arbitrary signals to the remote process, although you may be able to
152get its attention by using out-of-band data.
153Note that if the user is not the superuser,
154.Fa fd2p
155must be
156.Va NULL .
157.Pp
158.Fn rcmd_af
159takes address family in the last argument.
160If the last argument is
161.Dv PF_UNSPEC ,
162interpretation of
163.Fa *ahost
164will obey the underlying address resolution like DNS.
165.Pp
166The protocol is described in detail in
167.Xr rshd 8 .
168.Pp
169The
170.Fn rresvport
171and
172.Fn rresvport_af
173functions are used to obtain a socket with a privileged
174address bound to it.
175This socket is suitable for use by
176.Fn rcmd
177and several other functions.
178Privileged Internet ports are those in the range 0 to
179.Va IPPORT_RESERVED - 1 ,
180which happens to be 1023.
181Only the superuser is allowed to bind an address of this sort to a socket.
182.Fn rresvport
183and
184.Fn rresvport_af
185need to be seeded with a port number; if that port
186is not available these functions will find another.
187.Pp
188The
189.Fn iruserok
190and
191.Fn ruserok
192functions take a remote host's IP address or name, respectively,
193two user names and a flag indicating whether the local user's
194name is that of the superuser.
195Then, if the user is
196.Em not
197the superuser, it checks the
198.Pa /etc/hosts.equiv
199file.
200If that lookup is not done, or is unsuccessful, the
201.Pa .rhosts
202in the local user's home directory is checked to see if the request for
203service is allowed.
204.Pp
205If this file does not exist, is not a regular file, is owned by anyone
206other than the user or the superuser, or is writeable by anyone other
207than the owner, the check automatically fails.
208Zero is returned if the machine name is listed in the
209.Pa hosts.equiv
210file, or the host and remote user name are found in the
211.Pa .rhosts
212file; otherwise
213.Fn iruserok
214and
215.Fn ruserok
216return \-1.
217If the local domain (as obtained from
218.Xr gethostname 3 )
219is the same as the remote domain, only the machine name need be specified.
220.Pp
221If the IP address of the remote host is known,
222.Fn iruserok
223should be used in preference to
224.Fn ruserok ,
225as it does not require trusting the DNS server for the remote host's domain.
226.Pp
227While
228.Fn iruserok
229can handle IPv4 addresses only,
230.Fn iruserok_sa
231and
232.Fn ruserok
233can handle other address families as well, like IPv6.
234The first argument of
235.Fn iruserok_sa
236is typed as
237.Li "void *"
238to avoid dependency between
239.Aq Pa unistd.h
240and
241.Aq Pa sys/socket.h .
242.Sh DIAGNOSTICS
243The
244.Fn rcmd
245function returns a valid socket descriptor on success.
246It returns \-1 on error and prints a diagnostic message on the standard error.
247.Pp
248The
249.Fn rresvport
250and
251.Fn rresvport_af
252functions return a valid, bound socket descriptor on success.
253It returns \-1 on error with the global value
254.Va errno
255set according to the reason for failure.
256The error code
257.Er EAGAIN
258is overloaded to mean
259.Dq all network ports in use .
260.Sh SEE ALSO
261.Xr rsh 1 ,
262.Xr intro 2 ,
263.Xr bindresvport 3 ,
264.Xr bindresvport_sa 3 ,
265.Xr rcmdsh 3 ,
266.Xr rshd 8
267.Sh HISTORY
268These
269functions appeared in
270.Bx 4.2 .
diff --git a/src/lib/libc/net/rcmd.c b/src/lib/libc/net/rcmd.c
new file mode 100644
index 0000000000..d3d2d751b5
--- /dev/null
+++ b/src/lib/libc/net/rcmd.c
@@ -0,0 +1,733 @@
1/*
2 * Copyright (c) 1995, 1996, 1998 Theo de Raadt. All rights reserved.
3 * Copyright (c) 1983, 1993, 1994
4 * The Regents of the University of California. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed by the University of
17 * California, Berkeley and its contributors.
18 * This product includes software developed by Theo de Raadt.
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
36#if defined(LIBC_SCCS) && !defined(lint)
37static char *rcsid = "$OpenBSD: rcmd.c,v 1.44 2002/09/06 18:35:12 deraadt Exp $";
38#endif /* LIBC_SCCS and not lint */
39
40#include <sys/param.h>
41#include <sys/socket.h>
42#include <sys/stat.h>
43
44#include <netinet/in.h>
45#include <arpa/inet.h>
46
47#include <signal.h>
48#include <fcntl.h>
49#include <netdb.h>
50#include <unistd.h>
51#include <pwd.h>
52#include <errno.h>
53#include <stdio.h>
54#include <ctype.h>
55#include <string.h>
56#include <syslog.h>
57#include <stdlib.h>
58#include <netgroup.h>
59
60int __ivaliduser(FILE *, in_addr_t, const char *, const char *);
61int __ivaliduser_sa(FILE *, struct sockaddr *, socklen_t,
62 const char *, const char *);
63static int __icheckhost(struct sockaddr *, socklen_t, const char *);
64static char *__gethostloop(struct sockaddr *, socklen_t);
65
66int
67rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
68 char **ahost;
69 in_port_t rport;
70 const char *locuser, *remuser, *cmd;
71 int *fd2p;
72{
73 return rcmd_af(ahost, rport, locuser, remuser, cmd, fd2p, AF_INET);
74}
75
76int
77rcmd_af(ahost, rport, locuser, remuser, cmd, fd2p, af)
78 char **ahost;
79 in_port_t rport;
80 const char *locuser, *remuser, *cmd;
81 int *fd2p;
82 int af;
83{
84 static char hbuf[MAXHOSTNAMELEN];
85 char pbuf[NI_MAXSERV];
86 struct addrinfo hints, *res, *r;
87 int error;
88 struct sockaddr_storage from;
89 fd_set *readsp = NULL;
90 sigset_t oldmask, mask;
91 pid_t pid;
92 int s, lport, timo;
93 char c, *p;
94 int refused;
95
96 /* call rcmdsh() with specified remote shell if appropriate. */
97 if (!issetugid() && (p = getenv("RSH")) && *p) {
98 struct servent *sp = getservbyname("shell", "tcp");
99
100 if (sp && sp->s_port == rport)
101 return (rcmdsh(ahost, rport, locuser, remuser,
102 cmd, p));
103 }
104
105 /* use rsh(1) if non-root and remote port is shell. */
106 if (geteuid()) {
107 struct servent *sp = getservbyname("shell", "tcp");
108
109 if (sp && sp->s_port == rport)
110 return (rcmdsh(ahost, rport, locuser, remuser,
111 cmd, NULL));
112 }
113
114 pid = getpid();
115 snprintf(pbuf, sizeof(pbuf), "%u", ntohs(rport));
116 memset(&hints, 0, sizeof(hints));
117 hints.ai_family = af;
118 hints.ai_socktype = SOCK_STREAM;
119 hints.ai_flags = AI_CANONNAME;
120 error = getaddrinfo(*ahost, pbuf, &hints, &res);
121 if (error) {
122#if 0
123 warnx("%s: %s", *ahost, gai_strerror(error));
124#endif
125 return (-1);
126 }
127 if (res->ai_canonname) {
128 strlcpy(hbuf, res->ai_canonname, sizeof(hbuf));
129 *ahost = hbuf;
130 } else
131 ; /*XXX*/
132
133 r = res;
134 refused = 0;
135 sigemptyset(&mask);
136 sigaddset(&mask, SIGURG);
137 oldmask = sigprocmask(SIG_BLOCK, &mask, &oldmask);
138 for (timo = 1, lport = IPPORT_RESERVED - 1;;) {
139 s = rresvport_af(&lport, r->ai_family);
140 if (s < 0) {
141 if (errno == EAGAIN)
142 (void)fprintf(stderr,
143 "rcmd: socket: All ports in use\n");
144 else
145 (void)fprintf(stderr, "rcmd: socket: %s\n",
146 strerror(errno));
147 if (r->ai_next) {
148 r = r->ai_next;
149 continue;
150 } else {
151 sigprocmask(SIG_SETMASK, &oldmask, NULL);
152 freeaddrinfo(res);
153 return (-1);
154 }
155 }
156 fcntl(s, F_SETOWN, pid);
157 if (connect(s, r->ai_addr, r->ai_addrlen) >= 0)
158 break;
159 (void)close(s);
160 if (errno == EADDRINUSE) {
161 lport--;
162 continue;
163 }
164 if (errno == ECONNREFUSED)
165 refused++;
166 if (r->ai_next) {
167 int oerrno = errno;
168 char hbuf[NI_MAXHOST];
169#ifdef NI_WITHSCOPEID
170 const int niflags = NI_NUMERICHOST | NI_WITHSCOPEID;
171#else
172 const int niflags = NI_NUMERICHOST;
173#endif
174
175 hbuf[0] = '\0';
176 if (getnameinfo(r->ai_addr, r->ai_addrlen,
177 hbuf, sizeof(hbuf), NULL, 0, niflags) != 0)
178 strlcpy(hbuf, "(invalid)", sizeof hbuf);
179 (void)fprintf(stderr, "connect to address %s: ", hbuf);
180 errno = oerrno;
181 perror(0);
182 r = r->ai_next;
183 hbuf[0] = '\0';
184 if (getnameinfo(r->ai_addr, r->ai_addrlen,
185 hbuf, sizeof(hbuf), NULL, 0, niflags) != 0)
186 strlcpy(hbuf, "(invalid)", sizeof hbuf);
187 (void)fprintf(stderr, "Trying %s...\n", hbuf);
188 continue;
189 }
190 if (refused && timo <= 16) {
191 (void)sleep(timo);
192 timo *= 2;
193 r = res;
194 refused = 0;
195 continue;
196 }
197 (void)fprintf(stderr, "%s: %s\n", res->ai_canonname,
198 strerror(errno));
199 sigprocmask(SIG_SETMASK, &oldmask, NULL);
200 freeaddrinfo(res);
201 return (-1);
202 }
203 /* given "af" can be PF_UNSPEC, we need the real af for "s" */
204 af = r->ai_family;
205 freeaddrinfo(res);
206#if 0
207 /*
208 * try to rresvport() to the same port. This will make rresvport()
209 * fail it's first bind, resulting in it choosing a random port.
210 */
211 lport--;
212#endif
213 if (fd2p == 0) {
214 write(s, "", 1);
215 lport = 0;
216 } else {
217 char num[8];
218 int s2 = rresvport_af(&lport, af), s3;
219 socklen_t len = sizeof(from);
220 int fdssize = howmany(MAX(s, s2)+1, NFDBITS) * sizeof(fd_mask);
221
222 if (s2 < 0)
223 goto bad;
224 readsp = (fd_set *)malloc(fdssize);
225 if (readsp == NULL)
226 goto bad;
227 listen(s2, 1);
228 (void)snprintf(num, sizeof(num), "%d", lport);
229 if (write(s, num, strlen(num)+1) != strlen(num)+1) {
230 (void)fprintf(stderr,
231 "rcmd: write (setting up stderr): %s\n",
232 strerror(errno));
233 (void)close(s2);
234 goto bad;
235 }
236again:
237 bzero(readsp, fdssize);
238 FD_SET(s, readsp);
239 FD_SET(s2, readsp);
240 errno = 0;
241 if (select(MAX(s, s2) + 1, readsp, 0, 0, 0) < 1 ||
242 !FD_ISSET(s2, readsp)) {
243 if (errno != 0)
244 (void)fprintf(stderr,
245 "rcmd: select (setting up stderr): %s\n",
246 strerror(errno));
247 else
248 (void)fprintf(stderr,
249 "select: protocol failure in circuit setup\n");
250 (void)close(s2);
251 goto bad;
252 }
253 s3 = accept(s2, (struct sockaddr *)&from, &len);
254 /*
255 * XXX careful for ftp bounce attacks. If discovered, shut them
256 * down and check for the real auxiliary channel to connect.
257 */
258 switch (from.ss_family) {
259 case AF_INET:
260 case AF_INET6:
261 if (getnameinfo((struct sockaddr *)&from, len,
262 NULL, 0, num, sizeof(num), NI_NUMERICSERV) == 0 &&
263 atoi(num) != 20) {
264 break;
265 }
266 close(s3);
267 goto again;
268 default:
269 break;
270 }
271 (void)close(s2);
272 if (s3 < 0) {
273 (void)fprintf(stderr,
274 "rcmd: accept: %s\n", strerror(errno));
275 lport = 0;
276 goto bad;
277 }
278 *fd2p = s3;
279 switch (from.ss_family) {
280 case AF_INET:
281 case AF_INET6:
282 if (getnameinfo((struct sockaddr *)&from, len,
283 NULL, 0, num, sizeof(num), NI_NUMERICSERV) != 0 ||
284 (atoi(num) >= IPPORT_RESERVED ||
285 atoi(num) < IPPORT_RESERVED / 2)) {
286 (void)fprintf(stderr,
287 "socket: protocol failure in circuit setup.\n");
288 goto bad2;
289 }
290 break;
291 default:
292 break;
293 }
294 }
295 (void)write(s, locuser, strlen(locuser)+1);
296 (void)write(s, remuser, strlen(remuser)+1);
297 (void)write(s, cmd, strlen(cmd)+1);
298 if (read(s, &c, 1) != 1) {
299 (void)fprintf(stderr,
300 "rcmd: %s: %s\n", *ahost, strerror(errno));
301 goto bad2;
302 }
303 if (c != 0) {
304 while (read(s, &c, 1) == 1) {
305 (void)write(STDERR_FILENO, &c, 1);
306 if (c == '\n')
307 break;
308 }
309 goto bad2;
310 }
311 sigprocmask(SIG_SETMASK, &oldmask, NULL);
312 free(readsp);
313 return (s);
314bad2:
315 if (lport)
316 (void)close(*fd2p);
317bad:
318 if (readsp)
319 free(readsp);
320 (void)close(s);
321 sigprocmask(SIG_SETMASK, &oldmask, NULL);
322 return (-1);
323}
324
325int __check_rhosts_file = 1;
326char *__rcmd_errstr;
327
328int
329ruserok(rhost, superuser, ruser, luser)
330 const char *rhost, *ruser, *luser;
331 int superuser;
332{
333 struct addrinfo hints, *res, *r;
334 int error;
335
336 memset(&hints, 0, sizeof(hints));
337 hints.ai_family = PF_UNSPEC;
338 hints.ai_socktype = SOCK_DGRAM; /*dummy*/
339 error = getaddrinfo(rhost, "0", &hints, &res);
340 if (error)
341 return (-1);
342
343 for (r = res; r; r = r->ai_next) {
344 if (iruserok_sa(r->ai_addr, r->ai_addrlen, superuser, ruser,
345 luser) == 0) {
346 freeaddrinfo(res);
347 return (0);
348 }
349 }
350 freeaddrinfo(res);
351 return (-1);
352}
353
354/*
355 * New .rhosts strategy: We are passed an ip address. We spin through
356 * hosts.equiv and .rhosts looking for a match. When the .rhosts only
357 * has ip addresses, we don't have to trust a nameserver. When it
358 * contains hostnames, we spin through the list of addresses the nameserver
359 * gives us and look for a match.
360 *
361 * Returns 0 if ok, -1 if not ok.
362 */
363int
364iruserok(raddr, superuser, ruser, luser)
365 u_int32_t raddr;
366 int superuser;
367 const char *ruser, *luser;
368{
369 struct sockaddr_in sin;
370
371 memset(&sin, 0, sizeof(sin));
372 sin.sin_family = AF_INET;
373 sin.sin_len = sizeof(struct sockaddr_in);
374 memcpy(&sin.sin_addr, &raddr, sizeof(sin.sin_addr));
375 return iruserok_sa(&sin, sizeof(struct sockaddr_in), superuser, ruser,
376 luser);
377}
378
379int
380iruserok_sa(raddr, rlen, superuser, ruser, luser)
381 const void *raddr;
382 int rlen;
383 int superuser;
384 const char *ruser, *luser;
385{
386 struct sockaddr *sa;
387 register char *cp;
388 struct stat sbuf;
389 struct passwd *pwd;
390 FILE *hostf;
391 uid_t uid;
392 int first;
393 char pbuf[MAXPATHLEN];
394
395 sa = (struct sockaddr *)raddr;
396 first = 1;
397 hostf = superuser ? NULL : fopen(_PATH_HEQUIV, "r");
398again:
399 if (hostf) {
400 if (__ivaliduser_sa(hostf, sa, rlen, luser, ruser) == 0) {
401 (void)fclose(hostf);
402 return (0);
403 }
404 (void)fclose(hostf);
405 }
406 if (first == 1 && (__check_rhosts_file || superuser)) {
407 first = 0;
408 if ((pwd = getpwnam(luser)) == NULL)
409 return (-1);
410 snprintf(pbuf, sizeof pbuf, "%s/.rhosts", pwd->pw_dir);
411
412 /*
413 * Change effective uid while opening .rhosts. If root and
414 * reading an NFS mounted file system, can't read files that
415 * are protected read/write owner only.
416 */
417 uid = geteuid();
418 (void)seteuid(pwd->pw_uid);
419 hostf = fopen(pbuf, "r");
420 (void)seteuid(uid);
421
422 if (hostf == NULL)
423 return (-1);
424 /*
425 * If not a regular file, or is owned by someone other than
426 * user or root or if writeable by anyone but the owner, quit.
427 */
428 cp = NULL;
429 if (lstat(pbuf, &sbuf) < 0)
430 cp = ".rhosts lstat failed";
431 else if (!S_ISREG(sbuf.st_mode))
432 cp = ".rhosts not regular file";
433 else if (fstat(fileno(hostf), &sbuf) < 0)
434 cp = ".rhosts fstat failed";
435 else if (sbuf.st_uid && sbuf.st_uid != pwd->pw_uid)
436 cp = "bad .rhosts owner";
437 else if (sbuf.st_mode & (S_IWGRP|S_IWOTH))
438 cp = ".rhosts writeable by other than owner";
439 /* If there were any problems, quit. */
440 if (cp) {
441 __rcmd_errstr = cp;
442 (void)fclose(hostf);
443 return (-1);
444 }
445 goto again;
446 }
447 return (-1);
448}
449
450/*
451 * XXX
452 * Don't make static, used by lpd(8).
453 *
454 * Returns 0 if ok, -1 if not ok.
455 */
456int
457__ivaliduser(hostf, raddrl, luser, ruser)
458 FILE *hostf;
459 in_addr_t raddrl;
460 const char *luser, *ruser;
461{
462 struct sockaddr_in sin;
463
464 memset(&sin, 0, sizeof(sin));
465 sin.sin_family = AF_INET;
466 sin.sin_len = sizeof(struct sockaddr_in);
467 memcpy(&sin.sin_addr, &raddrl, sizeof(sin.sin_addr));
468 return __ivaliduser_sa(hostf, (struct sockaddr *)&sin, sin.sin_len,
469 luser, ruser);
470}
471
472int
473__ivaliduser_sa(hostf, raddr, salen, luser, ruser)
474 FILE *hostf;
475 struct sockaddr *raddr;
476 socklen_t salen;
477 const char *luser, *ruser;
478{
479 register char *user, *p;
480 char *buf;
481 const char *auser, *ahost;
482 int hostok, userok;
483 char *rhost = (char *)-1;
484 char domain[MAXHOSTNAMELEN];
485 size_t buflen;
486
487 getdomainname(domain, sizeof(domain));
488
489 while ((buf = fgetln(hostf, &buflen))) {
490 p = buf;
491 if (*p == '#')
492 continue;
493 while (*p != '\n' && *p != ' ' && *p != '\t' && p < buf + buflen) {
494 if (!isprint(*p))
495 goto bail;
496 *p = isupper(*p) ? tolower(*p) : *p;
497 p++;
498 }
499 if (p >= buf + buflen)
500 continue;
501 if (*p == ' ' || *p == '\t') {
502 *p++ = '\0';
503 while ((*p == ' ' || *p == '\t') && p < buf + buflen)
504 p++;
505 if (p >= buf + buflen)
506 continue;
507 user = p;
508 while (*p != '\n' && *p != ' ' &&
509 *p != '\t' && p < buf + buflen) {
510 if (!isprint(*p))
511 goto bail;
512 p++;
513 }
514 } else
515 user = p;
516 *p = '\0';
517
518 if (p == buf)
519 continue;
520
521 auser = *user ? user : luser;
522 ahost = buf;
523
524 if (strlen(ahost) >= MAXHOSTNAMELEN)
525 continue;
526
527 /*
528 * innetgr() must lookup a hostname (we do not attempt
529 * to change the semantics so that netgroups may have
530 * #.#.#.# addresses in the list.)
531 */
532 if (ahost[0] == '+')
533 switch (ahost[1]) {
534 case '\0':
535 hostok = 1;
536 break;
537 case '@':
538 if (rhost == (char *)-1)
539 rhost = __gethostloop(raddr, salen);
540 hostok = 0;
541 if (rhost)
542 hostok = innetgr(&ahost[2], rhost,
543 NULL, domain);
544 break;
545 default:
546 hostok = __icheckhost(raddr, salen, &ahost[1]);
547 break;
548 }
549 else if (ahost[0] == '-')
550 switch (ahost[1]) {
551 case '\0':
552 hostok = -1;
553 break;
554 case '@':
555 if (rhost == (char *)-1)
556 rhost = __gethostloop(raddr, salen);
557 hostok = 0;
558 if (rhost)
559 hostok = -innetgr(&ahost[2], rhost,
560 NULL, domain);
561 break;
562 default:
563 hostok = -__icheckhost(raddr, salen, &ahost[1]);
564 break;
565 }
566 else
567 hostok = __icheckhost(raddr, salen, ahost);
568
569
570 if (auser[0] == '+')
571 switch (auser[1]) {
572 case '\0':
573 userok = 1;
574 break;
575 case '@':
576 userok = innetgr(&auser[2], NULL, ruser,
577 domain);
578 break;
579 default:
580 userok = strcmp(ruser, &auser[1]) ? 0 : 1;
581 break;
582 }
583 else if (auser[0] == '-')
584 switch (auser[1]) {
585 case '\0':
586 userok = -1;
587 break;
588 case '@':
589 userok = -innetgr(&auser[2], NULL, ruser,
590 domain);
591 break;
592 default:
593 userok = strcmp(ruser, &auser[1]) ? 0 : -1;
594 break;
595 }
596 else
597 userok = strcmp(ruser, auser) ? 0 : 1;
598
599 /* Check if one component did not match */
600 if (hostok == 0 || userok == 0)
601 continue;
602
603 /* Check if we got a forbidden pair */
604 if (userok <= -1 || hostok <= -1)
605 return (-1);
606
607 /* Check if we got a valid pair */
608 if (hostok >= 1 && userok >= 1)
609 return (0);
610 }
611bail:
612 return (-1);
613}
614
615/*
616 * Returns "true" if match, 0 if no match. If we do not find any
617 * semblance of an A->PTR->A loop, allow a simple #.#.#.# match to work.
618 *
619 * NI_WITHSCOPEID is useful for comparing sin6_scope_id portion
620 * if af == AF_INET6.
621 */
622static int
623__icheckhost(raddr, salen, lhost)
624 struct sockaddr *raddr;
625 socklen_t salen;
626 const char *lhost;
627{
628 struct addrinfo hints, *res, *r;
629 char h1[NI_MAXHOST], h2[NI_MAXHOST];
630 int error;
631#ifdef NI_WITHSCOPEID
632 const int niflags = NI_NUMERICHOST | NI_WITHSCOPEID;
633#else
634 const int niflags = NI_NUMERICHOST;
635#endif
636
637 h1[0] = '\0';
638 if (getnameinfo(raddr, salen, h1, sizeof(h1), NULL, 0,
639 niflags) != 0)
640 return (0);
641
642 /* Resolve laddr into sockaddr */
643 memset(&hints, 0, sizeof(hints));
644 hints.ai_family = raddr->sa_family;
645 hints.ai_socktype = SOCK_DGRAM; /*dummy*/
646 res = NULL;
647 error = getaddrinfo(lhost, "0", &hints, &res);
648 if (error)
649 return (0);
650
651 /*
652 * Try string comparisons between raddr and laddr.
653 */
654 for (r = res; r; r = r->ai_next) {
655 h2[0] = '\0';
656 if (getnameinfo(r->ai_addr, r->ai_addrlen, h2, sizeof(h2),
657 NULL, 0, niflags) != 0)
658 continue;
659 if (strcmp(h1, h2) == 0) {
660 freeaddrinfo(res);
661 return (1);
662 }
663 }
664
665 /* No match. */
666 freeaddrinfo(res);
667 return (0);
668}
669
670/*
671 * Return the hostname associated with the supplied address.
672 * Do a reverse lookup as well for security. If a loop cannot
673 * be found, pack the result of inet_ntoa() into the string.
674 *
675 * NI_WITHSCOPEID is useful for comparing sin6_scope_id portion
676 * if af == AF_INET6.
677 */
678static char *
679__gethostloop(raddr, salen)
680 struct sockaddr *raddr;
681 socklen_t salen;
682{
683 static char remotehost[NI_MAXHOST];
684 char h1[NI_MAXHOST], h2[NI_MAXHOST];
685 struct addrinfo hints, *res, *r;
686 int error;
687#ifdef NI_WITHSCOPEID
688 const int niflags = NI_NUMERICHOST | NI_WITHSCOPEID;
689#else
690 const int niflags = NI_NUMERICHOST;
691#endif
692
693 h1[0] = remotehost[0] = '\0';
694 if (getnameinfo(raddr, salen, remotehost, sizeof(remotehost),
695 NULL, 0, NI_NAMEREQD) != 0)
696 return (NULL);
697 if (getnameinfo(raddr, salen, h1, sizeof(h1), NULL, 0,
698 niflags) != 0)
699 return (NULL);
700
701 /*
702 * Look up the name and check that the supplied
703 * address is in the list
704 */
705 memset(&hints, 0, sizeof(hints));
706 hints.ai_family = raddr->sa_family;
707 hints.ai_socktype = SOCK_DGRAM; /*dummy*/
708 hints.ai_flags = AI_CANONNAME;
709 res = NULL;
710 error = getaddrinfo(remotehost, "0", &hints, &res);
711 if (error)
712 return (NULL);
713
714 for (r = res; r; r = r->ai_next) {
715 h2[0] = '\0';
716 if (getnameinfo(r->ai_addr, r->ai_addrlen, h2, sizeof(h2),
717 NULL, 0, niflags) != 0)
718 continue;
719 if (strcmp(h1, h2) == 0) {
720 freeaddrinfo(res);
721 return (remotehost);
722 }
723 }
724
725 /*
726 * either the DNS adminstrator has made a configuration
727 * mistake, or someone has attempted to spoof us
728 */
729 syslog(LOG_NOTICE, "rcmd: address %s not listed for host %s",
730 h1, res->ai_canonname ? res->ai_canonname : remotehost);
731 freeaddrinfo(res);
732 return (NULL);
733}
diff --git a/src/lib/libc/net/rcmdsh.3 b/src/lib/libc/net/rcmdsh.3
new file mode 100644
index 0000000000..e0c59efb85
--- /dev/null
+++ b/src/lib/libc/net/rcmdsh.3
@@ -0,0 +1,97 @@
1.\" $OpenBSD: rcmdsh.3,v 1.8 2000/12/24 00:30:56 aaron Exp $
2.\"
3.\" Copyright (c) 1983, 1991, 1993
4.\" The Regents of the University of California. All rights reserved.
5.\"
6.\" Redistribution and use in source and binary forms, with or without
7.\" modification, are permitted provided that the following conditions
8.\" are met:
9.\" 1. Redistributions of source code must retain the above copyright
10.\" notice, this list of conditions and the following disclaimer.
11.\" 2. Redistributions in binary form must reproduce the above copyright
12.\" notice, this list of conditions and the following disclaimer in the
13.\" documentation and/or other materials provided with the distribution.
14.\" 3. All advertising materials mentioning features or use of this software
15.\" must display the following acknowledgement:
16.\" This product includes software developed by the University of
17.\" California, Berkeley and its contributors.
18.\" 4. Neither the name of the University nor the names of its contributors
19.\" may be used to endorse or promote products derived from this software
20.\" without specific prior written permission.
21.\"
22.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32.\" SUCH DAMAGE.
33.\"
34.Dd September 1, 1996
35.Dt RCMDSH 3
36.Os
37.Sh NAME
38.Nm rcmdsh
39.Nd return a stream to a remote command without superuser
40.Sh SYNOPSIS
41.Fd #include <unistd.h>
42.Ft int
43.Fn rcmdsh "char **ahost" "int inport" "const char *locuser" "const char *remuser" "const char *cmd" "char *rshprog"
44.Sh DESCRIPTION
45The
46.Fn rcmdsh
47function is used by normal users to execute a command on a remote machine
48using an authentication scheme based on reserved port numbers using
49.Xr rshd 8
50or the value of
51.Fa rshprog
52(if non-null).
53.Pp
54The
55.Fn rcmdsh
56function looks up the host
57.Fa *ahost
58using
59.Xr gethostbyname 3 ,
60returning \-1 if the host does not exist.
61Otherwise
62.Fa *ahost
63is set to the standard name of the host and a connection is established to
64a server residing at the well-known Internet port
65.Li shell/tcp
66(or whatever port is used by
67.Fa rshprog ) .
68The parameter
69.Fa inport
70is ignored; it is only included to provide an interface similar to
71.Xr rcmd 3 .
72.Pp
73If the connection succeeds, a socket in the
74.Tn UNIX
75domain of type
76.Dv SOCK_STREAM
77is returned to the caller, and given to the remote
78command as stdin and stdout, and stderr.
79.Sh DIAGNOSTICS
80The
81.Fn rcmdsh
82function returns a valid socket descriptor on success.
83It returns \-1 on error and prints a diagnostic message on the standard error.
84.Sh SEE ALSO
85.Xr rsh 1 ,
86.Xr socketpair 2 ,
87.Xr rcmd 3 ,
88.Xr rshd 8
89.Sh BUGS
90If
91.Xr rsh 1
92encounters an error, a file descriptor is still returned instead of \-1.
93.Sh HISTORY
94The
95.Fn rcmdsh
96function first appeared in
97.Ox 2.0 .
diff --git a/src/lib/libc/net/rcmdsh.c b/src/lib/libc/net/rcmdsh.c
new file mode 100644
index 0000000000..a1c7e7d6b8
--- /dev/null
+++ b/src/lib/libc/net/rcmdsh.c
@@ -0,0 +1,153 @@
1/* $OpenBSD: rcmdsh.c,v 1.7 2002/03/12 00:05:44 millert Exp $ */
2
3/*
4 * Copyright (c) 2001, MagniComp
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the MagniComp nor the names of its contributors may
16 * be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
28 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31/*
32 * This is an rcmd() replacement originally by
33 * Chris Siebenmann <cks@utcc.utoronto.ca>.
34 */
35
36#if defined(LIBC_SCCS) && !defined(lint)
37static char *rcsid = "$OpenBSD: rcmdsh.c,v 1.7 2002/03/12 00:05:44 millert Exp $";
38#endif /* LIBC_SCCS and not lint */
39
40#include <sys/types.h>
41#include <sys/socket.h>
42#include <sys/wait.h>
43#include <signal.h>
44#include <errno.h>
45#include <netdb.h>
46#include <stdio.h>
47#include <string.h>
48#include <pwd.h>
49#include <paths.h>
50#include <unistd.h>
51
52/*
53 * This is a replacement rcmd() function that uses the rsh(1)
54 * program in place of a direct rcmd(3) function call so as to
55 * avoid having to be root. Note that rport is ignored.
56 */
57/* ARGSUSED */
58int
59rcmdsh(ahost, rport, locuser, remuser, cmd, rshprog)
60 char **ahost;
61 int rport;
62 const char *locuser, *remuser, *cmd;
63 char *rshprog;
64{
65 struct hostent *hp;
66 int sp[2];
67 pid_t cpid;
68 char *p;
69 struct passwd *pw;
70
71 /* What rsh/shell to use. */
72 if (rshprog == NULL)
73 rshprog = _PATH_RSH;
74
75 /* locuser must exist on this host. */
76 if ((pw = getpwnam(locuser)) == NULL) {
77 (void) fprintf(stderr, "rcmdsh: unknown user: %s\n", locuser);
78 return(-1);
79 }
80
81 /* Validate remote hostname. */
82 if (strcmp(*ahost, "localhost") != 0) {
83 if ((hp = gethostbyname(*ahost)) == NULL) {
84 herror(*ahost);
85 return(-1);
86 }
87 *ahost = hp->h_name;
88 }
89
90 /* Get a socketpair we'll use for stdin and stdout. */
91 if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, sp) < 0) {
92 perror("rcmdsh: socketpair");
93 return(-1);
94 }
95
96 cpid = fork();
97 if (cpid < 0) {
98 perror("rcmdsh: fork failed");
99 return(-1);
100 } else if (cpid == 0) {
101 /*
102 * Child. We use sp[1] to be stdin/stdout, and close sp[0].
103 */
104 (void) close(sp[0]);
105 if (dup2(sp[1], 0) < 0 || dup2(0, 1) < 0) {
106 perror("rcmdsh: dup2 failed");
107 _exit(255);
108 }
109 /* Fork again to lose parent. */
110 cpid = fork();
111 if (cpid < 0) {
112 perror("rcmdsh: fork to lose parent failed");
113 _exit(255);
114 }
115 if (cpid > 0)
116 _exit(0);
117
118 /* In grandchild here. Become local user for rshprog. */
119 if (setuid(pw->pw_uid)) {
120 (void) fprintf(stderr, "rcmdsh: setuid(%u): %s\n",
121 pw->pw_uid, strerror(errno));
122 _exit(255);
123 }
124
125 /*
126 * If remote host is "localhost" and local and remote user
127 * are the same, avoid running remote shell for efficiency.
128 */
129 if (!strcmp(*ahost, "localhost") && !strcmp(locuser, remuser)) {
130 if (pw->pw_shell[0] == '\0')
131 rshprog = _PATH_BSHELL;
132 else
133 rshprog = pw->pw_shell;
134 p = strrchr(rshprog, '/');
135 execlp(rshprog, p ? p+1 : rshprog, "-c", cmd,
136 (char *) NULL);
137 } else {
138 p = strrchr(rshprog, '/');
139 execlp(rshprog, p ? p+1 : rshprog, *ahost, "-l",
140 remuser, cmd, (char *) NULL);
141 }
142 (void) fprintf(stderr, "rcmdsh: execlp %s failed: %s\n",
143 rshprog, strerror(errno));
144 _exit(255);
145 } else {
146 /* Parent. close sp[1], return sp[0]. */
147 (void) close(sp[1]);
148 /* Reap child. */
149 (void) wait(NULL);
150 return(sp[0]);
151 }
152 /* NOTREACHED */
153}
diff --git a/src/lib/libc/net/recv.c b/src/lib/libc/net/recv.c
new file mode 100644
index 0000000000..d209a07213
--- /dev/null
+++ b/src/lib/libc/net/recv.c
@@ -0,0 +1,50 @@
1/*
2 * Copyright (c) 1988, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#if defined(LIBC_SCCS) && !defined(lint)
35static char rcsid[] = "$OpenBSD: recv.c,v 1.2 1996/08/19 08:29:40 tholo Exp $";
36#endif /* LIBC_SCCS and not lint */
37
38#include <sys/types.h>
39#include <sys/socket.h>
40
41#include <stddef.h>
42
43ssize_t
44recv(s, buf, len, flags)
45 int s, flags;
46 size_t len;
47 void *buf;
48{
49 return (recvfrom(s, buf, len, flags, NULL, 0));
50}
diff --git a/src/lib/libc/net/res_comp.c b/src/lib/libc/net/res_comp.c
new file mode 100644
index 0000000000..25e196b2cf
--- /dev/null
+++ b/src/lib/libc/net/res_comp.c
@@ -0,0 +1,503 @@
1/* $OpenBSD: res_comp.c,v 1.10 2002/02/19 19:39:36 millert Exp $ */
2
3/*
4 * ++Copyright++ 1985, 1993
5 * -
6 * Copyright (c) 1985, 1993
7 * The Regents of the University of California. All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by the University of
20 * California, Berkeley and its contributors.
21 * 4. Neither the name of the University nor the names of its contributors
22 * may be used to endorse or promote products derived from this software
23 * without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
36 * -
37 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
38 *
39 * Permission to use, copy, modify, and distribute this software for any
40 * purpose with or without fee is hereby granted, provided that the above
41 * copyright notice and this permission notice appear in all copies, and that
42 * the name of Digital Equipment Corporation not be used in advertising or
43 * publicity pertaining to distribution of the document or software without
44 * specific, written prior permission.
45 *
46 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
47 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
48 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
49 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
50 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
51 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
52 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
53 * SOFTWARE.
54 * -
55 * --Copyright--
56 */
57
58#if defined(LIBC_SCCS) && !defined(lint)
59#if 0
60static char sccsid[] = "@(#)res_comp.c 8.1 (Berkeley) 6/4/93";
61static char rcsid[] = "$From: res_comp.c,v 8.11 1996/12/02 09:17:22 vixie Exp $";
62#else
63static char rcsid[] = "$OpenBSD: res_comp.c,v 1.10 2002/02/19 19:39:36 millert Exp $";
64#endif
65#endif /* LIBC_SCCS and not lint */
66
67#include <sys/types.h>
68#include <sys/param.h>
69#include <netinet/in.h>
70#include <arpa/nameser.h>
71
72#include <stdio.h>
73#include <resolv.h>
74#include <ctype.h>
75
76#include <unistd.h>
77#include <string.h>
78
79static int dn_find(u_char *, u_char *, u_char **, u_char **);
80
81/*
82 * Expand compressed domain name 'comp_dn' to full domain name.
83 * 'msg' is a pointer to the begining of the message,
84 * 'eomorig' points to the first location after the message,
85 * 'exp_dn' is a pointer to a buffer of size 'length' for the result.
86 * Return size of compressed name or -1 if there was an error.
87 */
88int
89dn_expand(msg, eomorig, comp_dn, exp_dn, length)
90 const u_char *msg, *eomorig, *comp_dn;
91 char *exp_dn;
92 int length;
93{
94 register const u_char *cp;
95 register char *dn;
96 register int n, c;
97 char *eom;
98 int len = -1, checked = 0;
99
100 dn = exp_dn;
101 cp = comp_dn;
102 if (length > MAXHOSTNAMELEN-1)
103 length = MAXHOSTNAMELEN-1;
104 eom = exp_dn + length;
105 /*
106 * fetch next label in domain name
107 */
108 while ((n = *cp++)) {
109 /*
110 * Check for indirection
111 */
112 switch (n & INDIR_MASK) {
113 case 0:
114 if (dn != exp_dn) {
115 if (dn >= eom)
116 return (-1);
117 *dn++ = '.';
118 }
119 if (dn+n >= eom)
120 return (-1);
121 checked += n + 1;
122 while (--n >= 0) {
123 if (((c = *cp++) == '.') || (c == '\\')) {
124 if (dn + n + 2 >= eom)
125 return (-1);
126 *dn++ = '\\';
127 }
128 *dn++ = c;
129 if (cp >= eomorig) /* out of range */
130 return (-1);
131 }
132 break;
133
134 case INDIR_MASK:
135 if (len < 0)
136 len = cp - comp_dn + 1;
137 cp = msg + (((n & 0x3f) << 8) | (*cp & 0xff));
138 if (cp < msg || cp >= eomorig) /* out of range */
139 return (-1);
140 checked += 2;
141 /*
142 * Check for loops in the compressed name;
143 * if we've looked at the whole message,
144 * there must be a loop.
145 */
146 if (checked >= eomorig - msg)
147 return (-1);
148 break;
149
150 default:
151 return (-1); /* flag error */
152 }
153 }
154 *dn = '\0';
155 if (len < 0)
156 len = cp - comp_dn;
157 return (len);
158}
159
160/*
161 * Compress domain name 'exp_dn' into 'comp_dn'.
162 * Return the size of the compressed name or -1.
163 * 'length' is the size of the array pointed to by 'comp_dn'.
164 * 'dnptrs' is a list of pointers to previous compressed names. dnptrs[0]
165 * is a pointer to the beginning of the message. The list ends with NULL.
166 * 'lastdnptr' is a pointer to the end of the arrary pointed to
167 * by 'dnptrs'. Side effect is to update the list of pointers for
168 * labels inserted into the message as we compress the name.
169 * If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr'
170 * is NULL, we don't update the list.
171 */
172int
173dn_comp(exp_dn, comp_dn, length, dnptrs, lastdnptr)
174 const char *exp_dn;
175 u_char *comp_dn, **dnptrs, **lastdnptr;
176 int length;
177{
178 register u_char *cp, *dn;
179 register int c, l;
180 u_char **cpp, **lpp, *sp, *eob;
181 u_char *msg;
182
183 dn = (u_char *)exp_dn;
184 cp = comp_dn;
185 eob = cp + length;
186 lpp = cpp = NULL;
187 if (dnptrs != NULL) {
188 if ((msg = *dnptrs++) != NULL) {
189 for (cpp = dnptrs; *cpp != NULL; cpp++)
190 ;
191 lpp = cpp; /* end of list to search */
192 }
193 } else
194 msg = NULL;
195 for (c = *dn++; c != '\0'; ) {
196 /* look to see if we can use pointers */
197 if (msg != NULL) {
198 if ((l = dn_find(dn-1, msg, dnptrs, lpp)) >= 0) {
199 if (cp+1 >= eob)
200 return (-1);
201 *cp++ = (l >> 8) | INDIR_MASK;
202 *cp++ = l % 256;
203 return (cp - comp_dn);
204 }
205 /* not found, save it */
206 if (lastdnptr != NULL && cpp < lastdnptr-1) {
207 *cpp++ = cp;
208 *cpp = NULL;
209 }
210 }
211 sp = cp++; /* save ptr to length byte */
212 do {
213 if (c == '.') {
214 c = *dn++;
215 break;
216 }
217 if (c == '\\') {
218 if ((c = *dn++) == '\0')
219 break;
220 }
221 if (cp >= eob) {
222 if (msg != NULL)
223 *lpp = NULL;
224 return (-1);
225 }
226 *cp++ = c;
227 } while ((c = *dn++) != '\0');
228 /* catch trailing '.'s but not '..' */
229 if ((l = cp - sp - 1) == 0 && c == '\0') {
230 cp--;
231 break;
232 }
233 if (l <= 0 || l > MAXLABEL) {
234 if (msg != NULL)
235 *lpp = NULL;
236 return (-1);
237 }
238 *sp = l;
239 }
240 if (cp >= eob) {
241 if (msg != NULL)
242 *lpp = NULL;
243 return (-1);
244 }
245 *cp++ = '\0';
246 return (cp - comp_dn);
247}
248
249/*
250 * Skip over a compressed domain name. Return the size or -1.
251 */
252int
253__dn_skipname(comp_dn, eom)
254 const u_char *comp_dn, *eom;
255{
256 register const u_char *cp;
257 register int n;
258
259 cp = comp_dn;
260 while (cp < eom && (n = *cp++)) {
261 /*
262 * check for indirection
263 */
264 switch (n & INDIR_MASK) {
265 case 0: /* normal case, n == len */
266 cp += n;
267 continue;
268 case INDIR_MASK: /* indirection */
269 cp++;
270 break;
271 default: /* illegal type */
272 return (-1);
273 }
274 break;
275 }
276 if (cp > eom)
277 return (-1);
278 return (cp - comp_dn);
279}
280
281static int
282mklower(ch)
283 register int ch;
284{
285 if (isascii(ch) && isupper(ch))
286 return (tolower(ch));
287 return (ch);
288}
289
290/*
291 * Search for expanded name from a list of previously compressed names.
292 * Return the offset from msg if found or -1.
293 * dnptrs is the pointer to the first name on the list,
294 * not the pointer to the start of the message.
295 */
296static int
297dn_find(exp_dn, msg, dnptrs, lastdnptr)
298 u_char *exp_dn, *msg;
299 u_char **dnptrs, **lastdnptr;
300{
301 register u_char *dn, *cp, **cpp;
302 register int n;
303 u_char *sp;
304
305 for (cpp = dnptrs; cpp < lastdnptr; cpp++) {
306 dn = exp_dn;
307 sp = cp = *cpp;
308 while ((n = *cp++)) {
309 /*
310 * check for indirection
311 */
312 switch (n & INDIR_MASK) {
313 case 0: /* normal case, n == len */
314 while (--n >= 0) {
315 if (*dn == '.')
316 goto next;
317 if (*dn == '\\')
318 dn++;
319 if (mklower(*dn++) != mklower(*cp++))
320 goto next;
321 }
322 if ((n = *dn++) == '\0' && *cp == '\0')
323 return (sp - msg);
324 if (n == '.')
325 continue;
326 goto next;
327
328 case INDIR_MASK: /* indirection */
329 cp = msg + (((n & 0x3f) << 8) | *cp);
330 break;
331
332 default: /* illegal type */
333 return (-1);
334 }
335 }
336 if (*dn == '\0')
337 return (sp - msg);
338 next: ;
339 }
340 return (-1);
341}
342
343/*
344 * Verify that a domain name uses an acceptable character set.
345 */
346
347/*
348 * Note the conspicuous absence of ctype macros in these definitions. On
349 * non-ASCII hosts, we can't depend on string literals or ctype macros to
350 * tell us anything about network-format data. The rest of the BIND system
351 * is not careful about this, but for some reason, we're doing it right here.
352 */
353#define PERIOD 0x2e
354#define hyphenchar(c) ((c) == 0x2d)
355#define bslashchar(c) ((c) == 0x5c)
356#define periodchar(c) ((c) == PERIOD)
357#define asterchar(c) ((c) == 0x2a)
358#define alphachar(c) (((c) >= 0x41 && (c) <= 0x5a) \
359 || ((c) >= 0x61 && (c) <= 0x7a))
360#define digitchar(c) ((c) >= 0x30 && (c) <= 0x39)
361
362#define borderchar(c) (alphachar(c) || digitchar(c))
363#define middlechar(c) (borderchar(c) || hyphenchar(c))
364#define domainchar(c) ((c) > 0x20 && (c) < 0x7f)
365
366int
367res_hnok(dn)
368 const char *dn;
369{
370 int pch = PERIOD, ch = *dn++;
371
372 while (ch != '\0') {
373 int nch = *dn++;
374
375 if (periodchar(ch)) {
376 ;
377 } else if (periodchar(pch)) {
378 if (!borderchar(ch))
379 return (0);
380 } else if (periodchar(nch) || nch == '\0') {
381 if (!borderchar(ch))
382 return (0);
383 } else {
384 if (!middlechar(ch))
385 return (0);
386 }
387 pch = ch, ch = nch;
388 }
389 return (1);
390}
391
392/*
393 * hostname-like (A, MX, WKS) owners can have "*" as their first label
394 * but must otherwise be as a host name.
395 */
396int
397res_ownok(dn)
398 const char *dn;
399{
400 if (asterchar(dn[0])) {
401 if (periodchar(dn[1]))
402 return (res_hnok(dn+2));
403 if (dn[1] == '\0')
404 return (1);
405 }
406 return (res_hnok(dn));
407}
408
409/*
410 * SOA RNAMEs and RP RNAMEs can have any printable character in their first
411 * label, but the rest of the name has to look like a host name.
412 */
413int
414res_mailok(dn)
415 const char *dn;
416{
417 int ch, escaped = 0;
418
419 /* "." is a valid missing representation */
420 if (*dn == '\0')
421 return(1);
422
423 /* otherwise <label>.<hostname> */
424 while ((ch = *dn++) != '\0') {
425 if (!domainchar(ch))
426 return (0);
427 if (!escaped && periodchar(ch))
428 break;
429 if (escaped)
430 escaped = 0;
431 else if (bslashchar(ch))
432 escaped = 1;
433 }
434 if (periodchar(ch))
435 return (res_hnok(dn));
436 return(0);
437}
438
439/*
440 * This function is quite liberal, since RFC 1034's character sets are only
441 * recommendations.
442 */
443int
444res_dnok(dn)
445 const char *dn;
446{
447 int ch;
448
449 while ((ch = *dn++) != '\0')
450 if (!domainchar(ch))
451 return (0);
452 return (1);
453}
454
455/*
456 * Routines to insert/extract short/long's.
457 */
458
459u_int16_t
460_getshort(msgp)
461 register const u_char *msgp;
462{
463 register u_int16_t u;
464
465 GETSHORT(u, msgp);
466 return (u);
467}
468
469#ifdef NeXT
470/*
471 * nExt machines have some funky library conventions, which we must maintain.
472 */
473u_int16_t
474res_getshort(msgp)
475 register const u_char *msgp;
476{
477 return (_getshort(msgp));
478}
479#endif
480
481u_int32_t
482_getlong(msgp)
483 register const u_char *msgp;
484{
485 register u_int32_t u;
486
487 GETLONG(u, msgp);
488 return (u);
489}
490
491void
492__putshort(register u_int16_t s, register u_char *msgp)
493{
494 PUTSHORT(s, msgp);
495}
496
497void
498__putlong(l, msgp)
499 register u_int32_t l;
500 register u_char *msgp;
501{
502 PUTLONG(l, msgp);
503}
diff --git a/src/lib/libc/net/res_data.c b/src/lib/libc/net/res_data.c
new file mode 100644
index 0000000000..b0d19c36bb
--- /dev/null
+++ b/src/lib/libc/net/res_data.c
@@ -0,0 +1,117 @@
1/* $OpenBSD: res_data.c,v 1.1 1997/03/13 19:07:36 downsj Exp $ */
2
3/*
4 * ++Copyright++ 1995
5 * -
6 * Copyright (c) 1995
7 * The Regents of the University of California. All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by the University of
20 * California, Berkeley and its contributors.
21 * 4. Neither the name of the University nor the names of its contributors
22 * may be used to endorse or promote products derived from this software
23 * without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
36 * -
37 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
38 *
39 * Permission to use, copy, modify, and distribute this software for any
40 * purpose with or without fee is hereby granted, provided that the above
41 * copyright notice and this permission notice appear in all copies, and that
42 * the name of Digital Equipment Corporation not be used in advertising or
43 * publicity pertaining to distribution of the document or software without
44 * specific, written prior permission.
45 *
46 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
47 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
48 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
49 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
50 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
51 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
52 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
53 * SOFTWARE.
54 * -
55 * --Copyright--
56 */
57
58#if defined(LIBC_SCCS) && !defined(lint)
59#if 0
60static char rcsid[] = "$From: res_data.c,v 8.2 1996/08/05 08:31:35 vixie Exp $";
61#else
62static char rcsid[] = "$OpenBSD: res_data.c,v 1.1 1997/03/13 19:07:36 downsj Exp $";
63#endif
64#endif /* LIBC_SCCS and not lint */
65
66#include <sys/types.h>
67#include <sys/param.h>
68#include <sys/socket.h>
69#include <sys/time.h>
70#include <netinet/in.h>
71#include <arpa/inet.h>
72#include <arpa/nameser.h>
73
74#include <stdio.h>
75#include <ctype.h>
76#include <resolv.h>
77#include <unistd.h>
78#include <stdlib.h>
79#include <string.h>
80
81const char *_res_opcodes[] = {
82 "QUERY",
83 "IQUERY",
84 "CQUERYM",
85 "CQUERYU", /* experimental */
86 "NOTIFY", /* experimental */
87 "5",
88 "6",
89 "7",
90 "8",
91 "UPDATEA",
92 "UPDATED",
93 "UPDATEDA",
94 "UPDATEM",
95 "UPDATEMA",
96 "ZONEINIT",
97 "ZONEREF",
98};
99
100const char *_res_resultcodes[] = {
101 "NOERROR",
102 "FORMERR",
103 "SERVFAIL",
104 "NXDOMAIN",
105 "NOTIMP",
106 "REFUSED",
107 "6",
108 "7",
109 "8",
110 "9",
111 "10",
112 "11",
113 "12",
114 "13",
115 "14",
116 "NOCHANGE",
117};
diff --git a/src/lib/libc/net/res_debug.c b/src/lib/libc/net/res_debug.c
new file mode 100644
index 0000000000..2ea9173fe9
--- /dev/null
+++ b/src/lib/libc/net/res_debug.c
@@ -0,0 +1,1560 @@
1/* $OpenBSD: res_debug.c,v 1.14 2002/07/25 21:55:30 deraadt Exp $ */
2
3/*
4 * ++Copyright++ 1985, 1990, 1993
5 * -
6 * Copyright (c) 1985, 1990, 1993
7 * The Regents of the University of California. All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by the University of
20 * California, Berkeley and its contributors.
21 * 4. Neither the name of the University nor the names of its contributors
22 * may be used to endorse or promote products derived from this software
23 * without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
36 * -
37 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
38 *
39 * Permission to use, copy, modify, and distribute this software for any
40 * purpose with or without fee is hereby granted, provided that the above
41 * copyright notice and this permission notice appear in all copies, and that
42 * the name of Digital Equipment Corporation not be used in advertising or
43 * publicity pertaining to distribution of the document or software without
44 * specific, written prior permission.
45 *
46 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
47 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
48 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
49 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
50 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
51 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
52 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
53 * SOFTWARE.
54 * -
55 * Portions Copyright (c) 1995 by International Business Machines, Inc.
56 *
57 * International Business Machines, Inc. (hereinafter called IBM) grants
58 * permission under its copyrights to use, copy, modify, and distribute this
59 * Software with or without fee, provided that the above copyright notice and
60 * all paragraphs of this notice appear in all copies, and that the name of IBM
61 * not be used in connection with the marketing of any product incorporating
62 * the Software or modifications thereof, without specific, written prior
63 * permission.
64 *
65 * To the extent it has a right to do so, IBM grants an immunity from suit
66 * under its patents, if any, for the use, sale or manufacture of products to
67 * the extent that such products are used for performing Domain Name System
68 * dynamic updates in TCP/IP networks by means of the Software. No immunity is
69 * granted for any product per se or for any other function of any product.
70 *
71 * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
72 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
73 * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
74 * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
75 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
76 * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
77 * --Copyright--
78 */
79
80#if defined(LIBC_SCCS) && !defined(lint)
81#if 0
82static char sccsid[] = "@(#)res_debug.c 8.1 (Berkeley) 6/4/93";
83static char rcsid[] = "$From: res_debug.c,v 8.19 1996/11/26 10:11:23 vixie Exp $";
84#else
85static char rcsid[] = "$OpenBSD: res_debug.c,v 1.14 2002/07/25 21:55:30 deraadt Exp $";
86#endif
87#endif /* LIBC_SCCS and not lint */
88
89#include <sys/param.h>
90#include <sys/types.h>
91#include <sys/socket.h>
92#include <netinet/in.h>
93#include <arpa/inet.h>
94#include <arpa/nameser.h>
95
96#include <ctype.h>
97#include <netdb.h>
98#include <resolv.h>
99#include <stdio.h>
100#include <time.h>
101
102#include <stdlib.h>
103#include <string.h>
104
105extern const char *_res_opcodes[];
106extern const char *_res_resultcodes[];
107
108static const char *loc_ntoal(const u_char *binary, char *ascii, int ascii_len);
109
110/* XXX: we should use getservbyport() instead. */
111static const char *
112dewks(wks)
113 int wks;
114{
115 static char nbuf[20];
116
117 switch (wks) {
118 case 5: return "rje";
119 case 7: return "echo";
120 case 9: return "discard";
121 case 11: return "systat";
122 case 13: return "daytime";
123 case 15: return "netstat";
124 case 17: return "qotd";
125 case 19: return "chargen";
126 case 20: return "ftp-data";
127 case 21: return "ftp";
128 case 23: return "telnet";
129 case 25: return "smtp";
130 case 37: return "time";
131 case 39: return "rlp";
132 case 42: return "name";
133 case 43: return "whois";
134 case 53: return "domain";
135 case 57: return "apts";
136 case 59: return "apfs";
137 case 67: return "bootps";
138 case 68: return "bootpc";
139 case 69: return "tftp";
140 case 77: return "rje";
141 case 79: return "finger";
142 case 87: return "link";
143 case 95: return "supdup";
144 case 100: return "newacct";
145 case 101: return "hostnames";
146 case 102: return "iso-tsap";
147 case 103: return "x400";
148 case 104: return "x400-snd";
149 case 105: return "csnet-ns";
150 case 109: return "pop-2";
151 case 111: return "sunrpc";
152 case 113: return "auth";
153 case 115: return "sftp";
154 case 117: return "uucp-path";
155 case 119: return "nntp";
156 case 121: return "erpc";
157 case 123: return "ntp";
158 case 133: return "statsrv";
159 case 136: return "profile";
160 case 144: return "NeWS";
161 case 161: return "snmp";
162 case 162: return "snmp-trap";
163 case 170: return "print-srv";
164 default:
165 (void) snprintf(nbuf, sizeof nbuf, "%d", wks);
166 return (nbuf);
167 }
168}
169
170/* XXX: we should use getprotobynumber() instead. */
171static const char *
172deproto(protonum)
173 int protonum;
174{
175 static char nbuf[20];
176
177 switch (protonum) {
178 case 1: return "icmp";
179 case 2: return "igmp";
180 case 3: return "ggp";
181 case 5: return "st";
182 case 6: return "tcp";
183 case 7: return "ucl";
184 case 8: return "egp";
185 case 9: return "igp";
186 case 11: return "nvp-II";
187 case 12: return "pup";
188 case 16: return "chaos";
189 case 17: return "udp";
190 default:
191 (void) snprintf(nbuf, sizeof nbuf, "%d", protonum);
192 return (nbuf);
193 }
194}
195
196static const u_char *
197do_rrset(msg, len, cp, cnt, pflag, file, hs)
198 int cnt, pflag, len;
199 const u_char *cp, *msg;
200 const char *hs;
201 FILE *file;
202{
203 int n;
204 int sflag;
205
206 /*
207 * Print answer records.
208 */
209 sflag = (_res.pfcode & pflag);
210 if ((n = ntohs(cnt))) {
211 if ((!_res.pfcode) ||
212 ((sflag) && (_res.pfcode & RES_PRF_HEAD1)))
213 fprintf(file, "%s", hs);
214 while (--n >= 0) {
215 if ((!_res.pfcode) || sflag) {
216 cp = p_rr(cp, msg, file);
217 } else {
218 unsigned int dlen;
219 cp += __dn_skipname(cp, cp + MAXCDNAME);
220 cp += INT16SZ;
221 cp += INT16SZ;
222 cp += INT32SZ;
223 dlen = _getshort((u_char*)cp);
224 cp += INT16SZ;
225 cp += dlen;
226 }
227 if ((cp - msg) > len)
228 return (NULL);
229 }
230 if ((!_res.pfcode) ||
231 ((sflag) && (_res.pfcode & RES_PRF_HEAD1)))
232 putc('\n', file);
233 }
234 return (cp);
235}
236
237void
238__p_query(msg)
239 const u_char *msg;
240{
241 __fp_query(msg, stdout);
242}
243
244/*
245 * Print the current options.
246 * This is intended to be primarily a debugging routine.
247 */
248void
249__fp_resstat(statp, file)
250 struct __res_state *statp;
251 FILE *file;
252{
253 register u_long mask;
254
255 fprintf(file, ";; res options:");
256 if (!statp)
257 statp = &_res;
258 for (mask = 1; mask != 0; mask <<= 1)
259 if (statp->options & mask)
260 fprintf(file, " %s", p_option(mask));
261 putc('\n', file);
262}
263
264/*
265 * Print the contents of a query.
266 * This is intended to be primarily a debugging routine.
267 */
268void
269__fp_nquery(msg, len, file)
270 const u_char *msg;
271 int len;
272 FILE *file;
273{
274 register const u_char *cp, *endMark;
275 register const HEADER *hp;
276 register int n;
277
278 if ((_res.options & RES_INIT) == 0 && res_init() == -1)
279 return;
280
281#define TruncTest(x) if (x > endMark) goto trunc
282#define ErrorTest(x) if (x == NULL) goto error
283
284 /*
285 * Print header fields.
286 */
287 hp = (HEADER *)msg;
288 cp = msg + HFIXEDSZ;
289 endMark = msg + len;
290 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEADX) || hp->rcode) {
291 fprintf(file, ";; ->>HEADER<<- opcode: %s, status: %s, id: %u",
292 _res_opcodes[hp->opcode],
293 _res_resultcodes[hp->rcode],
294 ntohs(hp->id));
295 putc('\n', file);
296 }
297 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEADX))
298 putc(';', file);
299 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD2)) {
300 fprintf(file, "; flags:");
301 if (hp->qr)
302 fprintf(file, " qr");
303 if (hp->aa)
304 fprintf(file, " aa");
305 if (hp->tc)
306 fprintf(file, " tc");
307 if (hp->rd)
308 fprintf(file, " rd");
309 if (hp->ra)
310 fprintf(file, " ra");
311 if (hp->unused)
312 fprintf(file, " UNUSED-BIT-ON");
313 if (hp->ad)
314 fprintf(file, " ad");
315 if (hp->cd)
316 fprintf(file, " cd");
317 }
318 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD1)) {
319 fprintf(file, "; Ques: %u", ntohs(hp->qdcount));
320 fprintf(file, ", Ans: %u", ntohs(hp->ancount));
321 fprintf(file, ", Auth: %u", ntohs(hp->nscount));
322 fprintf(file, ", Addit: %u", ntohs(hp->arcount));
323 }
324 if ((!_res.pfcode) || (_res.pfcode &
325 (RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1))) {
326 putc('\n',file);
327 }
328 /*
329 * Print question records.
330 */
331 if ((n = ntohs(hp->qdcount))) {
332 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
333 fprintf(file, ";; QUESTIONS:\n");
334 while (--n >= 0) {
335 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
336 fprintf(file, ";;\t");
337 TruncTest(cp);
338 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
339 cp = p_cdnname(cp, msg, len, file);
340 else {
341 int n;
342 char name[MAXDNAME];
343
344 if ((n = dn_expand(msg, msg+len, cp, name,
345 sizeof name)) < 0)
346 cp = NULL;
347 else
348 cp += n;
349 }
350 ErrorTest(cp);
351 TruncTest(cp);
352 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
353 fprintf(file, ", type = %s",
354 __p_type(_getshort((u_char*)cp)));
355 cp += INT16SZ;
356 TruncTest(cp);
357 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
358 fprintf(file, ", class = %s\n",
359 __p_class(_getshort((u_char*)cp)));
360 cp += INT16SZ;
361 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
362 putc('\n', file);
363 }
364 }
365 /*
366 * Print authoritative answer records
367 */
368 TruncTest(cp);
369 cp = do_rrset(msg, len, cp, hp->ancount, RES_PRF_ANS, file,
370 ";; ANSWERS:\n");
371 ErrorTest(cp);
372
373 /*
374 * print name server records
375 */
376 TruncTest(cp);
377 cp = do_rrset(msg, len, cp, hp->nscount, RES_PRF_AUTH, file,
378 ";; AUTHORITY RECORDS:\n");
379 ErrorTest(cp);
380
381 TruncTest(cp);
382 /*
383 * print additional records
384 */
385 cp = do_rrset(msg, len, cp, hp->arcount, RES_PRF_ADD, file,
386 ";; ADDITIONAL RECORDS:\n");
387 ErrorTest(cp);
388 return;
389 trunc:
390 fprintf(file, "\n;; ...truncated\n");
391 return;
392 error:
393 fprintf(file, "\n;; ...malformed\n");
394}
395
396void
397__fp_query(msg, file)
398 const u_char *msg;
399 FILE *file;
400{
401 fp_nquery(msg, PACKETSZ, file);
402}
403
404const u_char *
405__p_cdnname(cp, msg, len, file)
406 const u_char *cp, *msg;
407 int len;
408 FILE *file;
409{
410 char name[MAXDNAME];
411 int n;
412
413 if ((n = dn_expand(msg, msg + len, cp, name, sizeof name)) < 0)
414 return (NULL);
415 if (name[0] == '\0')
416 putc('.', file);
417 else
418 fputs(name, file);
419 return (cp + n);
420}
421
422const u_char *
423__p_cdname(cp, msg, file)
424 const u_char *cp, *msg;
425 FILE *file;
426{
427 return (p_cdnname(cp, msg, PACKETSZ, file));
428}
429
430
431/* Return a fully-qualified domain name from a compressed name (with
432 length supplied). */
433
434const u_char *
435__p_fqnname(cp, msg, msglen, name, namelen)
436 const u_char *cp, *msg;
437 int msglen;
438 char *name;
439 int namelen;
440{
441 int n, newlen;
442
443 if ((n = dn_expand(msg, cp + msglen, cp, name, namelen)) < 0)
444 return (NULL);
445 newlen = strlen(name);
446 if (newlen == 0 || name[newlen - 1] != '.') {
447 if (newlen+1 >= namelen) /* Lack space for final dot */
448 return (NULL);
449 else
450 strcpy(name + newlen, ".");
451 }
452 return (cp + n);
453}
454
455/* XXX: the rest of these functions need to become length-limited, too. (vix)
456 */
457
458const u_char *
459__p_fqname(cp, msg, file)
460 const u_char *cp, *msg;
461 FILE *file;
462{
463 char name[MAXDNAME];
464 const u_char *n;
465
466 n = __p_fqnname(cp, msg, MAXCDNAME, name, sizeof name);
467 if (n == NULL)
468 return (NULL);
469 fputs(name, file);
470 return (n);
471}
472
473/*
474 * Print resource record fields in human readable form.
475 */
476const u_char *
477__p_rr(cp, msg, file)
478 const u_char *cp, *msg;
479 FILE *file;
480{
481 int type, class, dlen, n, c;
482 struct in_addr inaddr;
483 const u_char *cp1, *cp2;
484 u_int32_t tmpttl, t;
485 int lcnt;
486 u_int16_t keyflags;
487 char rrname[MAXDNAME]; /* The fqdn of this RR */
488 char base64_key[MAX_KEY_BASE64];
489
490 if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
491 h_errno = NETDB_INTERNAL;
492 return (NULL);
493 }
494 cp = __p_fqnname(cp, msg, MAXCDNAME, rrname, sizeof rrname);
495 if (!cp)
496 return (NULL); /* compression error */
497 fputs(rrname, file);
498
499 type = _getshort((u_char*)cp);
500 cp += INT16SZ;
501 class = _getshort((u_char*)cp);
502 cp += INT16SZ;
503 tmpttl = _getlong((u_char*)cp);
504 cp += INT32SZ;
505 dlen = _getshort((u_char*)cp);
506 cp += INT16SZ;
507 cp1 = cp;
508 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_TTLID))
509 fprintf(file, "\t%lu", (u_long)tmpttl);
510 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_CLASS))
511 fprintf(file, "\t%s", __p_class(class));
512 fprintf(file, "\t%s", __p_type(type));
513 /*
514 * Print type specific data, if appropriate
515 */
516 switch (type) {
517 case T_A:
518 switch (class) {
519 case C_IN:
520 case C_HS:
521 bcopy(cp, (char *)&inaddr, INADDRSZ);
522 if (dlen == 4) {
523 fprintf(file, "\t%s", inet_ntoa(inaddr));
524 cp += dlen;
525 } else if (dlen == 7) {
526 char *address;
527 u_char protocol;
528 in_port_t port;
529
530 address = inet_ntoa(inaddr);
531 cp += INADDRSZ;
532 protocol = *(u_char*)cp;
533 cp += sizeof (u_char);
534 port = _getshort((u_char*)cp);
535 cp += INT16SZ;
536 fprintf(file, "\t%s\t; proto %u, port %u",
537 address, protocol, port);
538 }
539 break;
540 default:
541 cp += dlen;
542 }
543 break;
544 case T_CNAME:
545 case T_MB:
546 case T_MG:
547 case T_MR:
548 case T_NS:
549 case T_PTR:
550 putc('\t', file);
551 if ((cp = p_fqname(cp, msg, file)) == NULL)
552 return (NULL);
553 break;
554
555 case T_HINFO:
556 case T_ISDN:
557 cp2 = cp + dlen;
558 (void) fputs("\t\"", file);
559 if ((n = (unsigned char) *cp++) != 0) {
560 for (c = n; c > 0 && cp < cp2; c--) {
561 if (strchr("\n\"\\", *cp))
562 (void) putc('\\', file);
563 (void) putc(*cp++, file);
564 }
565 }
566 putc('"', file);
567 if (cp < cp2 && (n = (unsigned char) *cp++) != 0) {
568 (void) fputs ("\t\"", file);
569 for (c = n; c > 0 && cp < cp2; c--) {
570 if (strchr("\n\"\\", *cp))
571 (void) putc('\\', file);
572 (void) putc(*cp++, file);
573 }
574 putc('"', file);
575 } else if (type == T_HINFO) {
576 (void) fputs("\"?\"", file);
577 fprintf(file, "\n;; *** Warning *** OS-type missing");
578 }
579 break;
580
581 case T_SOA:
582 putc('\t', file);
583 if ((cp = p_fqname(cp, msg, file)) == NULL)
584 return (NULL);
585 putc(' ', file);
586 if ((cp = p_fqname(cp, msg, file)) == NULL)
587 return (NULL);
588 fputs(" (\n", file);
589 t = _getlong((u_char*)cp); cp += INT32SZ;
590 fprintf(file, "\t\t\t%lu\t; serial\n", (u_long)t);
591 t = _getlong((u_char*)cp); cp += INT32SZ;
592 fprintf(file, "\t\t\t%lu\t; refresh (%s)\n",
593 (u_long)t, __p_time(t));
594 t = _getlong((u_char*)cp); cp += INT32SZ;
595 fprintf(file, "\t\t\t%lu\t; retry (%s)\n",
596 (u_long)t, __p_time(t));
597 t = _getlong((u_char*)cp); cp += INT32SZ;
598 fprintf(file, "\t\t\t%lu\t; expire (%s)\n",
599 (u_long)t, __p_time(t));
600 t = _getlong((u_char*)cp); cp += INT32SZ;
601 fprintf(file, "\t\t\t%lu )\t; minimum (%s)",
602 (u_long)t, __p_time(t));
603 break;
604
605 case T_MX:
606 case T_AFSDB:
607 case T_RT:
608 fprintf(file, "\t%u ", _getshort((u_char*)cp));
609 cp += INT16SZ;
610 if ((cp = p_fqname(cp, msg, file)) == NULL)
611 return (NULL);
612 break;
613
614 case T_PX:
615 fprintf(file, "\t%u ", _getshort((u_char*)cp));
616 cp += INT16SZ;
617 if ((cp = p_fqname(cp, msg, file)) == NULL)
618 return (NULL);
619 putc(' ', file);
620 if ((cp = p_fqname(cp, msg, file)) == NULL)
621 return (NULL);
622 break;
623
624 case T_X25:
625 cp2 = cp + dlen;
626 (void) fputs("\t\"", file);
627 if ((n = (unsigned char) *cp++) != 0) {
628 for (c = n; c > 0 && cp < cp2; c--) {
629 if (strchr("\n\"\\", *cp))
630 (void) putc('\\', file);
631 (void) putc(*cp++, file);
632 }
633 }
634 putc('"', file);
635 break;
636
637 case T_TXT:
638 (void) putc('\t', file);
639 cp2 = cp1 + dlen;
640 while (cp < cp2) {
641 putc('"', file);
642 if ((n = (unsigned char) *cp++)) {
643 for (c = n; c > 0 && cp < cp2; c--) {
644 if (strchr("\n\"\\", *cp))
645 (void) putc('\\', file);
646 (void) putc(*cp++, file);
647 }
648 }
649 putc('"', file);
650 if (cp < cp2)
651 putc(' ', file);
652 }
653 break;
654
655 case T_NSAP:
656 (void) fprintf(file, "\t%s", inet_nsap_ntoa(dlen, cp, NULL));
657 cp += dlen;
658 break;
659
660 case T_AAAA: {
661 char t[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"];
662
663 fprintf(file, "\t%s", inet_ntop(AF_INET6, cp, t, sizeof t));
664 cp += dlen;
665 break;
666 }
667
668 case T_LOC: {
669 char t[255];
670
671 fprintf(file, "\t%s", loc_ntoal(cp, t, sizeof t));
672 cp += dlen;
673 break;
674 }
675
676 case T_NAPTR: {
677 u_int order, preference;
678
679 order = _getshort(cp); cp += INT16SZ;
680 preference = _getshort(cp); cp += INT16SZ;
681 fprintf(file, "\t%u %u ",order, preference);
682 /* Flags */
683 n = *cp++;
684 fprintf(file,"\"%.*s\" ", (int)n, cp);
685 cp += n;
686 /* Service */
687 n = *cp++;
688 fprintf(file,"\"%.*s\" ", (int)n, cp);
689 cp += n;
690 /* Regexp */
691 n = *cp++;
692 fprintf(file,"\"%.*s\" ", (int)n, cp);
693 cp += n;
694 if ((cp = p_fqname(cp, msg, file)) == NULL)
695 return (NULL);
696 break;
697 }
698
699 case T_SRV: {
700 u_int priority, weight, port;
701
702 priority = _getshort(cp); cp += INT16SZ;
703 weight = _getshort(cp); cp += INT16SZ;
704 port = _getshort(cp); cp += INT16SZ;
705 fprintf(file, "\t%u %u %u ", priority, weight, port);
706 if ((cp = p_fqname(cp, msg, file)) == NULL)
707 return (NULL);
708 break;
709 }
710
711 case T_MINFO:
712 case T_RP:
713 putc('\t', file);
714 if ((cp = p_fqname(cp, msg, file)) == NULL)
715 return (NULL);
716 putc(' ', file);
717 if ((cp = p_fqname(cp, msg, file)) == NULL)
718 return (NULL);
719 break;
720
721 case T_UINFO:
722 putc('\t', file);
723 fputs((char *)cp, file);
724 cp += dlen;
725 break;
726
727 case T_UID:
728 case T_GID:
729 if (dlen == 4) {
730 fprintf(file, "\t%u", _getlong((u_char*)cp));
731 cp += INT32SZ;
732 }
733 break;
734
735 case T_WKS:
736 if (dlen < INT32SZ + 1)
737 break;
738 bcopy(cp, (char *)&inaddr, INADDRSZ);
739 cp += INT32SZ;
740 fprintf(file, "\t%s %s ( ",
741 inet_ntoa(inaddr),
742 deproto((int) *cp));
743 cp += sizeof (u_char);
744 n = 0;
745 lcnt = 0;
746 while (cp < cp1 + dlen) {
747 c = *cp++;
748 do {
749 if (c & 0200) {
750 if (lcnt == 0) {
751 fputs("\n\t\t\t", file);
752 lcnt = 5;
753 }
754 fputs(dewks(n), file);
755 putc(' ', file);
756 lcnt--;
757 }
758 c <<= 1;
759 } while (++n & 07);
760 }
761 putc(')', file);
762 break;
763
764 case T_KEY:
765 putc('\t', file);
766 keyflags = _getshort(cp);
767 cp += 2;
768 fprintf(file,"0x%04x", keyflags ); /* flags */
769 fprintf(file," %u", *cp++); /* protocol */
770 fprintf(file," %u (", *cp++); /* algorithm */
771
772 n = b64_ntop(cp, (cp1 + dlen) - cp,
773 base64_key, sizeof base64_key);
774 for (c = 0; c < n; ++c) {
775 if (0 == (c & 0x3F))
776 fprintf(file, "\n\t");
777 putc(base64_key[c], file); /* public key data */
778 }
779
780 fprintf(file, " )");
781 if (n < 0)
782 fprintf(file, "\t; BAD BASE64");
783 fflush(file);
784 cp = cp1 + dlen;
785 break;
786
787 case T_SIG:
788 type = _getshort((u_char*)cp);
789 cp += INT16SZ;
790 fprintf(file, " %s", p_type(type));
791 fprintf(file, "\t%u", *cp++); /* algorithm */
792 /* Check label value and print error if wrong. */
793 n = *cp++;
794 c = dn_count_labels (rrname);
795 if (n != c)
796 fprintf(file, "\t; LABELS WRONG (%d should be %d)\n\t",
797 n, c);
798 /* orig ttl */
799 n = _getlong((u_char*)cp);
800 if (n != tmpttl)
801 fprintf(file, " %u", n);
802 cp += INT32SZ;
803 /* sig expire */
804 fprintf(file, " (\n\t%s",
805 __p_secstodate(_getlong((u_char*)cp)));
806 cp += INT32SZ;
807 /* time signed */
808 fprintf(file, " %s", __p_secstodate(_getlong((u_char*)cp)));
809 cp += INT32SZ;
810 /* sig footprint */
811 fprintf(file," %u ", _getshort((u_char*)cp));
812 cp += INT16SZ;
813 /* signer's name */
814 cp = p_fqname(cp, msg, file);
815 n = b64_ntop(cp, (cp1 + dlen) - cp,
816 base64_key, sizeof base64_key);
817 for (c = 0; c < n; c++) {
818 if (0 == (c & 0x3F))
819 fprintf (file, "\n\t");
820 putc(base64_key[c], file); /* signature */
821 }
822 /* Clean up... */
823 fprintf(file, " )");
824 if (n < 0)
825 fprintf(file, "\t; BAD BASE64");
826 fflush(file);
827 cp = cp1+dlen;
828 break;
829
830#ifdef ALLOW_T_UNSPEC
831 case T_UNSPEC:
832 {
833 int NumBytes = 8;
834 u_char *DataPtr;
835 int i;
836
837 if (dlen < NumBytes) NumBytes = dlen;
838 fprintf(file, "\tFirst %d bytes of hex data:",
839 NumBytes);
840 for (i = 0, DataPtr = cp; i < NumBytes; i++, DataPtr++)
841 fprintf(file, " %x", *DataPtr);
842 cp += dlen;
843 }
844 break;
845#endif /* ALLOW_T_UNSPEC */
846
847 default:
848 fprintf(file, "\t?%d?", type);
849 cp += dlen;
850 }
851#if 0
852 fprintf(file, "\t; dlen=%d, ttl %s\n", dlen, __p_time(tmpttl));
853#else
854 putc('\n', file);
855#endif
856 if (cp - cp1 != dlen) {
857 fprintf(file, ";; packet size error (found %ld, dlen was %d)\n",
858 (long)(cp - cp1), dlen);
859 cp = NULL;
860 }
861 return (cp);
862}
863
864/*
865 * Names of RR classes and qclasses. Classes and qclasses are the same, except
866 * that C_ANY is a qclass but not a class. (You can ask for records of class
867 * C_ANY, but you can't have any records of that class in the database.)
868 */
869const struct res_sym __p_class_syms[] = {
870 {C_IN, "IN"},
871 {C_CHAOS, "CHAOS"},
872 {C_HS, "HS"},
873 {C_HS, "HESIOD"},
874 {C_ANY, "ANY"},
875 {C_IN, (char *)0}
876};
877
878/*
879 * Names of RR types and qtypes. Types and qtypes are the same, except
880 * that T_ANY is a qtype but not a type. (You can ask for records of type
881 * T_ANY, but you can't have any records of that type in the database.)
882 */
883const struct res_sym __p_type_syms[] = {
884 {T_A, "A", "address"},
885 {T_NS, "NS", "name server"},
886 {T_MD, "MD", "mail destination (deprecated)"},
887 {T_MF, "MF", "mail forwarder (deprecated)"},
888 {T_CNAME, "CNAME", "canonical name"},
889 {T_SOA, "SOA", "start of authority"},
890 {T_MB, "MB", "mailbox"},
891 {T_MG, "MG", "mail group member"},
892 {T_MR, "MR", "mail rename"},
893 {T_NULL, "NULL", "null"},
894 {T_WKS, "WKS", "well-known service (deprecated)"},
895 {T_PTR, "PTR", "domain name pointer"},
896 {T_HINFO, "HINFO", "host information"},
897 {T_MINFO, "MINFO", "mailbox information"},
898 {T_MX, "MX", "mail exchanger"},
899 {T_TXT, "TXT", "text"},
900 {T_RP, "RP", "responsible person"},
901 {T_AFSDB, "AFSDB", "DCE or AFS server"},
902 {T_X25, "X25", "X25 address"},
903 {T_ISDN, "ISDN", "ISDN address"},
904 {T_RT, "RT", "router"},
905 {T_NSAP, "NSAP", "nsap address"},
906 {T_NSAP_PTR, "NSAP_PTR", "domain name pointer"},
907 {T_SIG, "SIG", "signature"},
908 {T_KEY, "KEY", "key"},
909 {T_PX, "PX", "mapping information"},
910 {T_GPOS, "GPOS", "geographical position (withdrawn)"},
911 {T_AAAA, "AAAA", "IPv6 address"},
912 {T_LOC, "LOC", "location"},
913 {T_NXT, "NXT", "next valid name (unimplemented)"},
914 {T_EID, "EID", "endpoint identifier (unimplemented)"},
915 {T_NIMLOC, "NIMLOC", "NIMROD locator (unimplemented)"},
916 {T_SRV, "SRV", "server selection"},
917 {T_ATMA, "ATMA", "ATM address (unimplemented)"},
918 {T_IXFR, "IXFR", "incremental zone transfer"},
919 {T_AXFR, "AXFR", "zone transfer"},
920 {T_MAILB, "MAILB", "mailbox-related data (deprecated)"},
921 {T_MAILA, "MAILA", "mail agent (deprecated)"},
922 {T_UINFO, "UINFO", "user information (nonstandard)"},
923 {T_UID, "UID", "user ID (nonstandard)"},
924 {T_GID, "GID", "group ID (nonstandard)"},
925 {T_NAPTR, "NAPTR", "URN Naming Authority"},
926#ifdef ALLOW_T_UNSPEC
927 {T_UNSPEC, "UNSPEC", "unspecified data (nonstandard)"},
928#endif /* ALLOW_T_UNSPEC */
929 {T_ANY, "ANY", "\"any\""},
930 {0, NULL, NULL}
931};
932
933int
934__sym_ston(syms, name, success)
935 const struct res_sym *syms;
936 char *name;
937 int *success;
938{
939 for (; syms->name != 0; syms++) {
940 if (strcasecmp (name, syms->name) == 0) {
941 if (success)
942 *success = 1;
943 return (syms->number);
944 }
945 }
946 if (success)
947 *success = 0;
948 return (syms->number); /* The default value. */
949}
950
951const char *
952__sym_ntos(syms, number, success)
953 const struct res_sym *syms;
954 int number;
955 int *success;
956{
957 static char unname[20];
958
959 for (; syms->name != 0; syms++) {
960 if (number == syms->number) {
961 if (success)
962 *success = 1;
963 return (syms->name);
964 }
965 }
966
967 snprintf(unname, sizeof unname, "%d", number);
968 if (success)
969 *success = 0;
970 return (unname);
971}
972
973
974const char *
975__sym_ntop(syms, number, success)
976 const struct res_sym *syms;
977 int number;
978 int *success;
979{
980 static char unname[20];
981
982 for (; syms->name != 0; syms++) {
983 if (number == syms->number) {
984 if (success)
985 *success = 1;
986 return (syms->humanname);
987 }
988 }
989 snprintf(unname, sizeof unname, "%d", number);
990 if (success)
991 *success = 0;
992 return (unname);
993}
994
995/*
996 * Return a string for the type
997 */
998const char *
999__p_type(type)
1000 int type;
1001{
1002 return (__sym_ntos (__p_type_syms, type, (int *)0));
1003}
1004
1005/*
1006 * Return a mnemonic for class
1007 */
1008const char *
1009__p_class(class)
1010 int class;
1011{
1012 return (__sym_ntos (__p_class_syms, class, (int *)0));
1013}
1014
1015/*
1016 * Return a mnemonic for an option
1017 */
1018const char *
1019__p_option(option)
1020 u_long option;
1021{
1022 static char nbuf[40];
1023
1024 switch (option) {
1025 case RES_INIT: return "init";
1026 case RES_DEBUG: return "debug";
1027 case RES_AAONLY: return "aaonly(unimpl)";
1028 case RES_USEVC: return "usevc";
1029 case RES_PRIMARY: return "primry(unimpl)";
1030 case RES_IGNTC: return "igntc";
1031 case RES_RECURSE: return "recurs";
1032 case RES_DEFNAMES: return "defnam";
1033 case RES_STAYOPEN: return "styopn";
1034 case RES_DNSRCH: return "dnsrch";
1035 case RES_INSECURE1: return "insecure1";
1036 case RES_INSECURE2: return "insecure2";
1037 case RES_USE_INET6: return "inet6";
1038 case RES_USE_EDNS0: return "edns0";
1039 default:
1040 snprintf(nbuf, sizeof nbuf, "?0x%lx?", (u_long)option);
1041 return (nbuf);
1042 }
1043}
1044
1045/*
1046 * Return a mnemonic for a time to live
1047 */
1048const char *
1049p_time(value)
1050 u_int32_t value;
1051{
1052 static char nbuf[40];
1053 char *ebuf;
1054 int secs, mins, hours, days;
1055 register char *p;
1056 int tmp;
1057
1058 if (value == 0) {
1059 strlcpy(nbuf, "0 secs", sizeof nbuf);
1060 return (nbuf);
1061 }
1062
1063 secs = value % 60;
1064 value /= 60;
1065 mins = value % 60;
1066 value /= 60;
1067 hours = value % 24;
1068 value /= 24;
1069 days = value;
1070 value = 0;
1071
1072#define PLURALIZE(x) x, (x == 1) ? "" : "s"
1073 p = nbuf;
1074 ebuf = nbuf + sizeof(nbuf);
1075 if (days) {
1076 if ((tmp = snprintf(p, ebuf - p, "%d day%s",
1077 PLURALIZE(days))) >= ebuf - nbuf || tmp < 0)
1078 goto full;
1079 p += tmp;
1080 }
1081 if (hours) {
1082 if (days)
1083 *p++ = ' ';
1084 if (p >= ebuf)
1085 goto full;
1086 if ((tmp = snprintf(p, ebuf - p, "%d hour%s",
1087 PLURALIZE(hours))) >= ebuf - nbuf || tmp < 0)
1088 goto full;
1089 p += tmp;
1090 }
1091 if (mins) {
1092 if (days || hours)
1093 *p++ = ' ';
1094 if (p >= ebuf)
1095 goto full;
1096 if ((tmp = snprintf(p, ebuf - p, "%d min%s",
1097 PLURALIZE(mins))) >= ebuf - nbuf || tmp < 0)
1098 goto full;
1099 p += tmp;
1100 }
1101 if (secs || ! (days || hours || mins)) {
1102 if (days || hours || mins)
1103 *p++ = ' ';
1104 if (p >= ebuf)
1105 goto full;
1106 if ((tmp = snprintf(p, ebuf - p, "%d sec%s",
1107 PLURALIZE(secs))) >= ebuf - nbuf || tmp < 0)
1108 goto full;
1109 }
1110 return (nbuf);
1111full:
1112 p = nbuf + sizeof(nbuf) - 4;
1113 *p++ = '.';
1114 *p++ = '.';
1115 *p++ = '.';
1116 *p++ = '\0';
1117 return (nbuf);
1118}
1119
1120/*
1121 * routines to convert between on-the-wire RR format and zone file format.
1122 * Does not contain conversion to/from decimal degrees; divide or multiply
1123 * by 60*60*1000 for that.
1124 */
1125
1126static unsigned int poweroften[10] = {1, 10, 100, 1000, 10000, 100000,
1127 1000000,10000000,100000000,1000000000};
1128
1129/* takes an XeY precision/size value, returns a string representation. */
1130static const char *
1131precsize_ntoa(prec)
1132 u_int8_t prec;
1133{
1134 static char retbuf[sizeof "90000000.00"];
1135 unsigned long val;
1136 int mantissa, exponent;
1137
1138 mantissa = (int)((prec >> 4) & 0x0f) % 10;
1139 exponent = (int)((prec >> 0) & 0x0f) % 10;
1140
1141 val = mantissa * poweroften[exponent];
1142
1143 (void) snprintf(retbuf, sizeof retbuf, "%ld.%.2ld", val/100, val%100);
1144 return (retbuf);
1145}
1146
1147/* converts ascii size/precision X * 10**Y(cm) to 0xXY. moves pointer. */
1148static u_int8_t
1149precsize_aton(strptr)
1150 char **strptr;
1151{
1152 unsigned int mval = 0, cmval = 0;
1153 u_int8_t retval = 0;
1154 register char *cp;
1155 register int exponent;
1156 register int mantissa;
1157
1158 cp = *strptr;
1159
1160 while (isdigit(*cp))
1161 mval = mval * 10 + (*cp++ - '0');
1162
1163 if (*cp == '.') { /* centimeters */
1164 cp++;
1165 if (isdigit(*cp)) {
1166 cmval = (*cp++ - '0') * 10;
1167 if (isdigit(*cp)) {
1168 cmval += (*cp++ - '0');
1169 }
1170 }
1171 }
1172 cmval = (mval * 100) + cmval;
1173
1174 for (exponent = 0; exponent < 9; exponent++)
1175 if (cmval < poweroften[exponent+1])
1176 break;
1177
1178 mantissa = cmval / poweroften[exponent];
1179 if (mantissa > 9)
1180 mantissa = 9;
1181
1182 retval = (mantissa << 4) | exponent;
1183
1184 *strptr = cp;
1185
1186 return (retval);
1187}
1188
1189/* converts ascii lat/lon to unsigned encoded 32-bit number. moves pointer. */
1190static u_int32_t
1191latlon2ul(latlonstrptr,which)
1192 char **latlonstrptr;
1193 int *which;
1194{
1195 register char *cp;
1196 u_int32_t retval;
1197 int deg = 0, min = 0, secs = 0, secsfrac = 0;
1198
1199 cp = *latlonstrptr;
1200
1201 while (isdigit(*cp))
1202 deg = deg * 10 + (*cp++ - '0');
1203
1204 while (isspace(*cp))
1205 cp++;
1206
1207 if (!(isdigit(*cp)))
1208 goto fndhemi;
1209
1210 while (isdigit(*cp))
1211 min = min * 10 + (*cp++ - '0');
1212
1213 while (isspace(*cp))
1214 cp++;
1215
1216 if (!(isdigit(*cp)))
1217 goto fndhemi;
1218
1219 while (isdigit(*cp))
1220 secs = secs * 10 + (*cp++ - '0');
1221
1222 if (*cp == '.') { /* decimal seconds */
1223 cp++;
1224 if (isdigit(*cp)) {
1225 secsfrac = (*cp++ - '0') * 100;
1226 if (isdigit(*cp)) {
1227 secsfrac += (*cp++ - '0') * 10;
1228 if (isdigit(*cp)) {
1229 secsfrac += (*cp++ - '0');
1230 }
1231 }
1232 }
1233 }
1234
1235 while (!isspace(*cp)) /* if any trailing garbage */
1236 cp++;
1237
1238 while (isspace(*cp))
1239 cp++;
1240
1241 fndhemi:
1242 switch (*cp) {
1243 case 'N': case 'n':
1244 case 'E': case 'e':
1245 retval = ((unsigned)1<<31)
1246 + (((((deg * 60) + min) * 60) + secs) * 1000)
1247 + secsfrac;
1248 break;
1249 case 'S': case 's':
1250 case 'W': case 'w':
1251 retval = ((unsigned)1<<31)
1252 - (((((deg * 60) + min) * 60) + secs) * 1000)
1253 - secsfrac;
1254 break;
1255 default:
1256 retval = 0; /* invalid value -- indicates error */
1257 break;
1258 }
1259
1260 switch (*cp) {
1261 case 'N': case 'n':
1262 case 'S': case 's':
1263 *which = 1; /* latitude */
1264 break;
1265 case 'E': case 'e':
1266 case 'W': case 'w':
1267 *which = 2; /* longitude */
1268 break;
1269 default:
1270 *which = 0; /* error */
1271 break;
1272 }
1273
1274 cp++; /* skip the hemisphere */
1275
1276 while (!isspace(*cp)) /* if any trailing garbage */
1277 cp++;
1278
1279 while (isspace(*cp)) /* move to next field */
1280 cp++;
1281
1282 *latlonstrptr = cp;
1283
1284 return (retval);
1285}
1286
1287/* converts a zone file representation in a string to an RDATA on-the-wire
1288 * representation. */
1289int
1290loc_aton(ascii, binary)
1291 const char *ascii;
1292 u_char *binary;
1293{
1294 const char *maxcp;
1295 u_char *bcp;
1296 char *cp;
1297
1298 u_int32_t latit = 0, longit = 0, alt = 0;
1299 u_int32_t lltemp1 = 0, lltemp2 = 0;
1300 int altmeters = 0, altfrac = 0, altsign = 1;
1301 u_int8_t hp = 0x16; /* default = 1e6 cm = 10000.00m = 10km */
1302 u_int8_t vp = 0x13; /* default = 1e3 cm = 10.00m */
1303 u_int8_t siz = 0x12; /* default = 1e2 cm = 1.00m */
1304 int which1 = 0, which2 = 0;
1305
1306 cp = (char *)ascii;
1307 maxcp = cp + strlen(ascii);
1308
1309 lltemp1 = latlon2ul(&cp, &which1);
1310
1311 lltemp2 = latlon2ul(&cp, &which2);
1312
1313 switch (which1 + which2) {
1314 case 3: /* 1 + 2, the only valid combination */
1315 if ((which1 == 1) && (which2 == 2)) { /* normal case */
1316 latit = lltemp1;
1317 longit = lltemp2;
1318 } else if ((which1 == 2) && (which2 == 1)) { /* reversed */
1319 longit = lltemp1;
1320 latit = lltemp2;
1321 } else { /* some kind of brokenness */
1322 return (0);
1323 }
1324 break;
1325 default: /* we didn't get one of each */
1326 return (0);
1327 }
1328
1329 /* altitude */
1330 if (*cp == '-') {
1331 altsign = -1;
1332 cp++;
1333 }
1334
1335 if (*cp == '+')
1336 cp++;
1337
1338 while (isdigit(*cp))
1339 altmeters = altmeters * 10 + (*cp++ - '0');
1340
1341 if (*cp == '.') { /* decimal meters */
1342 cp++;
1343 if (isdigit(*cp)) {
1344 altfrac = (*cp++ - '0') * 10;
1345 if (isdigit(*cp)) {
1346 altfrac += (*cp++ - '0');
1347 }
1348 }
1349 }
1350
1351 alt = (10000000 + (altsign * (altmeters * 100 + altfrac)));
1352
1353 while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
1354 cp++;
1355
1356 while (isspace(*cp) && (cp < maxcp))
1357 cp++;
1358
1359 if (cp >= maxcp)
1360 goto defaults;
1361
1362 siz = precsize_aton(&cp);
1363
1364 while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
1365 cp++;
1366
1367 while (isspace(*cp) && (cp < maxcp))
1368 cp++;
1369
1370 if (cp >= maxcp)
1371 goto defaults;
1372
1373 hp = precsize_aton(&cp);
1374
1375 while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
1376 cp++;
1377
1378 while (isspace(*cp) && (cp < maxcp))
1379 cp++;
1380
1381 if (cp >= maxcp)
1382 goto defaults;
1383
1384 vp = precsize_aton(&cp);
1385
1386 defaults:
1387
1388 bcp = binary;
1389 *bcp++ = (u_int8_t) 0; /* version byte */
1390 *bcp++ = siz;
1391 *bcp++ = hp;
1392 *bcp++ = vp;
1393 PUTLONG(latit,bcp);
1394 PUTLONG(longit,bcp);
1395 PUTLONG(alt,bcp);
1396
1397 return (16); /* size of RR in octets */
1398}
1399
1400const char *
1401loc_ntoa(binary, ascii)
1402 const u_char *binary;
1403 char *ascii;
1404{
1405 return loc_ntoal(binary, ascii, 255);
1406}
1407
1408/* takes an on-the-wire LOC RR and formats it in a human readable format. */
1409static const char *
1410loc_ntoal(binary, ascii, ascii_len)
1411 const u_char *binary;
1412 char *ascii;
1413 int ascii_len;
1414{
1415 static char *error = "?";
1416 register const u_char *cp = binary;
1417
1418 int latdeg, latmin, latsec, latsecfrac;
1419 int longdeg, longmin, longsec, longsecfrac;
1420 char northsouth, eastwest;
1421 int altmeters, altfrac, altsign;
1422
1423 const int referencealt = 100000 * 100;
1424
1425 int32_t latval, longval, altval;
1426 u_int32_t templ;
1427 u_int8_t sizeval, hpval, vpval, versionval;
1428
1429 char *sizestr, *hpstr, *vpstr;
1430
1431 versionval = *cp++;
1432
1433 if (versionval) {
1434 snprintf(ascii, ascii_len, "; error: unknown LOC RR version");
1435 return (ascii);
1436 }
1437
1438 sizeval = *cp++;
1439
1440 hpval = *cp++;
1441 vpval = *cp++;
1442
1443 GETLONG(templ, cp);
1444 latval = (templ - ((unsigned)1<<31));
1445
1446 GETLONG(templ, cp);
1447 longval = (templ - ((unsigned)1<<31));
1448
1449 GETLONG(templ, cp);
1450 if (templ < referencealt) { /* below WGS 84 spheroid */
1451 altval = referencealt - templ;
1452 altsign = -1;
1453 } else {
1454 altval = templ - referencealt;
1455 altsign = 1;
1456 }
1457
1458 if (latval < 0) {
1459 northsouth = 'S';
1460 latval = -latval;
1461 } else
1462 northsouth = 'N';
1463
1464 latsecfrac = latval % 1000;
1465 latval = latval / 1000;
1466 latsec = latval % 60;
1467 latval = latval / 60;
1468 latmin = latval % 60;
1469 latval = latval / 60;
1470 latdeg = latval;
1471
1472 if (longval < 0) {
1473 eastwest = 'W';
1474 longval = -longval;
1475 } else
1476 eastwest = 'E';
1477
1478 longsecfrac = longval % 1000;
1479 longval = longval / 1000;
1480 longsec = longval % 60;
1481 longval = longval / 60;
1482 longmin = longval % 60;
1483 longval = longval / 60;
1484 longdeg = longval;
1485
1486 altfrac = altval % 100;
1487 altmeters = (altval / 100) * altsign;
1488
1489 if ((sizestr = strdup(precsize_ntoa(sizeval))) == NULL)
1490 sizestr = error;
1491 if ((hpstr = strdup(precsize_ntoa(hpval))) == NULL)
1492 hpstr = error;
1493 if ((vpstr = strdup(precsize_ntoa(vpval))) == NULL)
1494 vpstr = error;
1495
1496 snprintf(ascii, ascii_len,
1497 "%d %.2d %.2d.%.3d %c %d %.2d %.2d.%.3d %c %d.%.2dm %sm %sm %sm",
1498 latdeg, latmin, latsec, latsecfrac, northsouth,
1499 longdeg, longmin, longsec, longsecfrac, eastwest,
1500 altmeters, altfrac, sizestr, hpstr, vpstr);
1501
1502 if (sizestr != error)
1503 free(sizestr);
1504 if (hpstr != error)
1505 free(hpstr);
1506 if (vpstr != error)
1507 free(vpstr);
1508
1509 return (ascii);
1510}
1511
1512
1513/* Return the number of DNS hierarchy levels in the name. */
1514int
1515__dn_count_labels(name)
1516 char *name;
1517{
1518 int i, len, count;
1519
1520 len = strlen(name);
1521
1522 for(i = 0, count = 0; i < len; i++) {
1523 if (name[i] == '.')
1524 count++;
1525 }
1526
1527 /* don't count initial wildcard */
1528 if (name[0] == '*')
1529 if (count)
1530 count--;
1531
1532 /* don't count the null label for root. */
1533 /* if terminating '.' not found, must adjust */
1534 /* count to include last label */
1535 if (len > 0 && name[len-1] != '.')
1536 count++;
1537 return (count);
1538}
1539
1540
1541/*
1542 * Make dates expressed in seconds-since-Jan-1-1970 easy to read.
1543 * SIG records are required to be printed like this, by the Secure DNS RFC.
1544 */
1545char *
1546__p_secstodate (secs)
1547 unsigned long secs;
1548{
1549 static char output[15]; /* YYYYMMDDHHMMSS and null */
1550 time_t clock = secs;
1551 struct tm *time;
1552
1553 time = gmtime(&clock);
1554 time->tm_year += 1900;
1555 time->tm_mon += 1;
1556 snprintf(output, sizeof output, "%04d%02d%02d%02d%02d%02d",
1557 time->tm_year, time->tm_mon, time->tm_mday,
1558 time->tm_hour, time->tm_min, time->tm_sec);
1559 return (output);
1560}
diff --git a/src/lib/libc/net/res_init.c b/src/lib/libc/net/res_init.c
new file mode 100644
index 0000000000..c55c7763a4
--- /dev/null
+++ b/src/lib/libc/net/res_init.c
@@ -0,0 +1,639 @@
1/* $OpenBSD: res_init.c,v 1.27 2002/07/25 21:13:45 deraadt Exp $ */
2
3/*
4 * ++Copyright++ 1985, 1989, 1993
5 * -
6 * Copyright (c) 1985, 1989, 1993
7 * The Regents of the University of California. All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by the University of
20 * California, Berkeley and its contributors.
21 * 4. Neither the name of the University nor the names of its contributors
22 * may be used to endorse or promote products derived from this software
23 * without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
36 * -
37 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
38 *
39 * Permission to use, copy, modify, and distribute this software for any
40 * purpose with or without fee is hereby granted, provided that the above
41 * copyright notice and this permission notice appear in all copies, and that
42 * the name of Digital Equipment Corporation not be used in advertising or
43 * publicity pertaining to distribution of the document or software without
44 * specific, written prior permission.
45 *
46 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
47 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
48 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
49 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
50 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
51 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
52 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
53 * SOFTWARE.
54 * -
55 * --Copyright--
56 */
57
58#ifndef INET6
59#define INET6
60#endif
61
62#if defined(LIBC_SCCS) && !defined(lint)
63#if 0
64static char sccsid[] = "@(#)res_init.c 8.1 (Berkeley) 6/7/93";
65static char rcsid[] = "$From: res_init.c,v 8.7 1996/09/28 06:51:07 vixie Exp $";
66#else
67static char rcsid[] = "$OpenBSD: res_init.c,v 1.27 2002/07/25 21:13:45 deraadt Exp $";
68#endif
69#endif /* LIBC_SCCS and not lint */
70
71#include <sys/types.h>
72#include <sys/param.h>
73#include <sys/socket.h>
74#include <sys/time.h>
75#include <netinet/in.h>
76#include <arpa/inet.h>
77#include <arpa/nameser.h>
78
79#include <stdio.h>
80#include <ctype.h>
81#include <resolv.h>
82#include <unistd.h>
83#include <stdlib.h>
84#include <string.h>
85#ifdef INET6
86#include <netdb.h>
87#endif /* INET6 */
88
89/*-------------------------------------- info about "sortlist" --------------
90 * Marc Majka 1994/04/16
91 * Allan Nathanson 1994/10/29 (BIND 4.9.3.x)
92 *
93 * NetInfo resolver configuration directory support.
94 *
95 * Allow a NetInfo directory to be created in the hierarchy which
96 * contains the same information as the resolver configuration file.
97 *
98 * - The local domain name is stored as the value of the "domain" property.
99 * - The Internet address(es) of the name server(s) are stored as values
100 * of the "nameserver" property.
101 * - The name server addresses are stored as values of the "nameserver"
102 * property.
103 * - The search list for host-name lookup is stored as values of the
104 * "search" property.
105 * - The sortlist comprised of IP address netmask pairs are stored as
106 * values of the "sortlist" property. The IP address and optional netmask
107 * should be separated by a slash (/) or ampersand (&) character.
108 * - Internal resolver variables can be set from the value of the "options"
109 * property.
110 */
111
112static void res_setoptions(char *, char *);
113
114#ifdef RESOLVSORT
115static const char sort_mask[] = "/&";
116#define ISSORTMASK(ch) (strchr(sort_mask, ch) != NULL)
117static u_int32_t net_mask(struct in_addr);
118#endif
119
120/*
121 * Resolver state default settings.
122 */
123
124struct __res_state _res
125# if defined(__BIND_RES_TEXT)
126 = { RES_TIMEOUT, } /* Motorola, et al. */
127# endif
128 ;
129#ifdef INET6
130struct __res_state_ext _res_ext;
131#endif /* INET6 */
132
133/*
134 * Set up default settings. If the configuration file exist, the values
135 * there will have precedence. Otherwise, the server address is set to
136 * INADDR_ANY and the default domain name comes from the gethostname().
137 *
138 * An interrim version of this code (BIND 4.9, pre-4.4BSD) used 127.0.0.1
139 * rather than INADDR_ANY ("0.0.0.0") as the default name server address
140 * since it was noted that INADDR_ANY actually meant ``the first interface
141 * you "ifconfig"'d at boot time'' and if this was a SLIP or PPP interface,
142 * it had to be "up" in order for you to reach your own name server. It
143 * was later decided that since the recommended practice is to always
144 * install local static routes through 127.0.0.1 for all your network
145 * interfaces, that we could solve this problem without a code change.
146 *
147 * The configuration file should always be used, since it is the only way
148 * to specify a default domain. If you are running a server on your local
149 * machine, you should say "nameserver 0.0.0.0" or "nameserver 127.0.0.1"
150 * in the configuration file.
151 *
152 * Return 0 if completes successfully, -1 on error
153 */
154int
155res_init()
156{
157 register FILE *fp;
158 register char *cp, **pp;
159 register int n;
160 char buf[BUFSIZ];
161 int nserv = 0; /* number of nameserver records read from file */
162 int haveenv = 0;
163 int havesearch = 0;
164 size_t len;
165#ifdef RESOLVSORT
166 int nsort = 0;
167 char *net;
168#endif
169#ifndef RFC1535
170 int dots;
171#endif
172
173 /*
174 * These three fields used to be statically initialized. This made
175 * it hard to use this code in a shared library. It is necessary,
176 * now that we're doing dynamic initialization here, that we preserve
177 * the old semantics: if an application modifies one of these three
178 * fields of _res before res_init() is called, res_init() will not
179 * alter them. Of course, if an application is setting them to
180 * _zero_ before calling res_init(), hoping to override what used
181 * to be the static default, we can't detect it and unexpected results
182 * will follow. Zero for any of these fields would make no sense,
183 * so one can safely assume that the applications were already getting
184 * unexpected results.
185 *
186 * _res.options is tricky since some apps were known to diddle the bits
187 * before res_init() was first called. We can't replicate that semantic
188 * with dynamic initialization (they may have turned bits off that are
189 * set in RES_DEFAULT). Our solution is to declare such applications
190 * "broken". They could fool us by setting RES_INIT but none do (yet).
191 */
192 if (!_res.retrans)
193 _res.retrans = RES_TIMEOUT;
194 if (!_res.retry)
195 _res.retry = 4;
196 if (!(_res.options & RES_INIT))
197 _res.options = RES_DEFAULT;
198
199#ifdef USELOOPBACK
200 _res.nsaddr.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1);
201#else
202 _res.nsaddr.sin_addr.s_addr = INADDR_ANY;
203#endif
204 _res.nsaddr.sin_family = AF_INET;
205 _res.nsaddr.sin_port = htons(NAMESERVER_PORT);
206 _res.nsaddr.sin_len = sizeof(struct sockaddr_in);
207#ifdef INET6
208 if (sizeof(_res_ext.nsaddr) >= _res.nsaddr.sin_len)
209 memcpy(&_res_ext.nsaddr, &_res.nsaddr, _res.nsaddr.sin_len);
210#endif
211 _res.nscount = 1;
212 _res.ndots = 1;
213 _res.pfcode = 0;
214 strlcpy(_res.lookups, "f", sizeof _res.lookups);
215
216 /* Allow user to override the local domain definition */
217 if (issetugid() == 0 && (cp = getenv("LOCALDOMAIN")) != NULL) {
218 strlcpy(_res.defdname, cp, sizeof(_res.defdname));
219 haveenv++;
220
221 /*
222 * Set search list to be blank-separated strings
223 * from rest of env value. Permits users of LOCALDOMAIN
224 * to still have a search list, and anyone to set the
225 * one that they want to use as an individual (even more
226 * important now that the rfc1535 stuff restricts searches)
227 */
228 cp = _res.defdname;
229 pp = _res.dnsrch;
230 *pp++ = cp;
231 for (n = 0; *cp && pp < _res.dnsrch + MAXDNSRCH; cp++) {
232 if (*cp == '\n') /* silly backwards compat */
233 break;
234 else if (*cp == ' ' || *cp == '\t') {
235 *cp = 0;
236 n = 1;
237 } else if (n) {
238 *pp++ = cp;
239 n = 0;
240 havesearch = 1;
241 }
242 }
243 /* null terminate last domain if there are excess */
244 while (*cp != '\0' && *cp != ' ' && *cp != '\t' && *cp != '\n')
245 cp++;
246 *cp = '\0';
247 *pp++ = 0;
248 }
249
250#define MATCH(line, name) \
251 (!strncmp(line, name, sizeof(name) - 1) && \
252 (line[sizeof(name) - 1] == ' ' || \
253 line[sizeof(name) - 1] == '\t'))
254
255 if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) {
256 strlcpy(_res.lookups, "bf", sizeof _res.lookups);
257
258 /* read the config file */
259 buf[0] = '\0';
260 while ((cp = fgetln(fp, &len)) != NULL) {
261 /* skip lines that are too long or zero length */
262 if (len >= sizeof(buf) || len == 0)
263 continue;
264 (void)memcpy(buf, cp, len);
265 buf[len] = '\0';
266 /* skip comments */
267 if ((cp = strpbrk(buf, ";#")) != NULL)
268 *cp = '\0';
269 if (buf[0] == '\0')
270 continue;
271 /* read default domain name */
272 if (MATCH(buf, "domain")) {
273 if (haveenv) /* skip if have from environ */
274 continue;
275 cp = buf + sizeof("domain") - 1;
276 while (*cp == ' ' || *cp == '\t')
277 cp++;
278 if ((*cp == '\0') || (*cp == '\n'))
279 continue;
280 strlcpy(_res.defdname, cp, sizeof(_res.defdname));
281 if ((cp = strpbrk(_res.defdname, " \t\n")) != NULL)
282 *cp = '\0';
283 havesearch = 0;
284 continue;
285 }
286 /* lookup types */
287 if (MATCH(buf, "lookup")) {
288 char *sp = NULL;
289
290 bzero(_res.lookups, sizeof _res.lookups);
291 cp = buf + sizeof("lookup") - 1;
292 for (n = 0;; cp++) {
293 if (n == MAXDNSLUS)
294 break;
295 if ((*cp == '\0') || (*cp == '\n')) {
296 if (sp) {
297 if (*sp=='y' || *sp=='b' || *sp=='f')
298 _res.lookups[n++] = *sp;
299 sp = NULL;
300 }
301 break;
302 } else if ((*cp == ' ') || (*cp == '\t') || (*cp == ',')) {
303 if (sp) {
304 if (*sp=='y' || *sp=='b' || *sp=='f')
305 _res.lookups[n++] = *sp;
306 sp = NULL;
307 }
308 } else if (sp == NULL)
309 sp = cp;
310 }
311 continue;
312 }
313 /* set search list */
314 if (MATCH(buf, "search")) {
315 if (haveenv) /* skip if have from environ */
316 continue;
317 cp = buf + sizeof("search") - 1;
318 while (*cp == ' ' || *cp == '\t')
319 cp++;
320 if ((*cp == '\0') || (*cp == '\n'))
321 continue;
322 strlcpy(_res.defdname, cp, sizeof(_res.defdname));
323 if ((cp = strchr(_res.defdname, '\n')) != NULL)
324 *cp = '\0';
325 /*
326 * Set search list to be blank-separated strings
327 * on rest of line.
328 */
329 cp = _res.defdname;
330 pp = _res.dnsrch;
331 *pp++ = cp;
332 for (n = 0; *cp && pp < _res.dnsrch + MAXDNSRCH; cp++) {
333 if (*cp == ' ' || *cp == '\t') {
334 *cp = 0;
335 n = 1;
336 } else if (n) {
337 *pp++ = cp;
338 n = 0;
339 }
340 }
341 /* null terminate last domain if there are excess */
342 while (*cp != '\0' && *cp != ' ' && *cp != '\t')
343 cp++;
344 *cp = '\0';
345 *pp++ = 0;
346 havesearch = 1;
347 continue;
348 }
349 /* read nameservers to query */
350 if (MATCH(buf, "nameserver") && nserv < MAXNS) {
351#ifdef INET6
352 char *q;
353 struct addrinfo hints, *res;
354 char pbuf[NI_MAXSERV];
355#else
356 struct in_addr a;
357#endif /* INET6 */
358
359 cp = buf + sizeof("nameserver") - 1;
360 while (*cp == ' ' || *cp == '\t')
361 cp++;
362#ifdef INET6
363 if ((*cp == '\0') || (*cp == '\n'))
364 continue;
365 for (q = cp; *q; q++) {
366 if (isspace(*q)) {
367 *q = '\0';
368 break;
369 }
370 }
371 memset(&hints, 0, sizeof(hints));
372 hints.ai_flags = AI_NUMERICHOST;
373 hints.ai_socktype = SOCK_DGRAM;
374 snprintf(pbuf, sizeof(pbuf), "%u", NAMESERVER_PORT);
375 res = NULL;
376 if (getaddrinfo(cp, pbuf, &hints, &res) == 0 &&
377 res->ai_next == NULL) {
378 if (res->ai_addrlen <= sizeof(_res_ext.nsaddr_list[nserv])) {
379 memcpy(&_res_ext.nsaddr_list[nserv], res->ai_addr,
380 res->ai_addrlen);
381 } else {
382 memset(&_res_ext.nsaddr_list[nserv], 0,
383 sizeof(_res_ext.nsaddr_list[nserv]));
384 }
385 if (res->ai_addrlen <= sizeof(_res.nsaddr_list[nserv])) {
386 memcpy(&_res.nsaddr_list[nserv], res->ai_addr,
387 res->ai_addrlen);
388 } else {
389 memset(&_res.nsaddr_list[nserv], 0,
390 sizeof(_res.nsaddr_list[nserv]));
391 }
392 nserv++;
393 }
394 if (res)
395 freeaddrinfo(res);
396#else /* INET6 */
397 if ((*cp != '\0') && (*cp != '\n') && inet_aton(cp, &a)) {
398 _res.nsaddr_list[nserv].sin_addr = a;
399 _res.nsaddr_list[nserv].sin_family = AF_INET;
400 _res.nsaddr_list[nserv].sin_port =
401 htons(NAMESERVER_PORT);
402 _res.nsaddr_list[nserv].sin_len =
403 sizeof(struct sockaddr_in);
404 nserv++;
405 }
406#endif /* INET6 */
407 continue;
408 }
409#ifdef RESOLVSORT
410 if (MATCH(buf, "sortlist")) {
411 struct in_addr a;
412#ifdef INET6
413 struct in6_addr a6;
414 int m, i;
415 u_char *u;
416#endif /* INET6 */
417
418 cp = buf + sizeof("sortlist") - 1;
419 while (nsort < MAXRESOLVSORT) {
420 while (*cp == ' ' || *cp == '\t')
421 cp++;
422 if (*cp == '\0' || *cp == '\n' || *cp == ';')
423 break;
424 net = cp;
425 while (*cp && !ISSORTMASK(*cp) && *cp != ';' &&
426 isascii(*cp) && !isspace(*cp))
427 cp++;
428 n = *cp;
429 *cp = 0;
430 if (inet_aton(net, &a)) {
431 _res.sort_list[nsort].addr = a;
432 if (ISSORTMASK(n)) {
433 *cp++ = n;
434 net = cp;
435 while (*cp && *cp != ';' &&
436 isascii(*cp) && !isspace(*cp))
437 cp++;
438 n = *cp;
439 *cp = 0;
440 if (inet_aton(net, &a)) {
441 _res.sort_list[nsort].mask = a.s_addr;
442 } else {
443 _res.sort_list[nsort].mask =
444 net_mask(_res.sort_list[nsort].addr);
445 }
446 } else {
447 _res.sort_list[nsort].mask =
448 net_mask(_res.sort_list[nsort].addr);
449 }
450#ifdef INET6
451 _res_ext.sort_list[nsort].af = AF_INET;
452 _res_ext.sort_list[nsort].addr.ina =
453 _res.sort_list[nsort].addr;
454 _res_ext.sort_list[nsort].mask.ina.s_addr =
455 _res.sort_list[nsort].mask;
456#endif /* INET6 */
457 nsort++;
458 }
459#ifdef INET6
460 else if (inet_pton(AF_INET6, net, &a6) == 1) {
461 _res_ext.sort_list[nsort].af = AF_INET6;
462 _res_ext.sort_list[nsort].addr.in6a = a6;
463 u = (u_char *)&_res_ext.sort_list[nsort].mask.in6a;
464 *cp++ = n;
465 net = cp;
466 while (*cp && *cp != ';' &&
467 isascii(*cp) && !isspace(*cp))
468 cp++;
469 m = n;
470 n = *cp;
471 *cp = 0;
472 switch (m) {
473 case '/':
474 m = atoi(net);
475 break;
476 case '&':
477 if (inet_pton(AF_INET6, net, u) == 1) {
478 m = -1;
479 break;
480 }
481 /*FALLTHRU*/
482 default:
483 m = sizeof(struct in6_addr) * NBBY;
484 break;
485 }
486 if (m >= 0) {
487 for (i = 0; i < sizeof(struct in6_addr); i++) {
488 if (m <= 0) {
489 *u = 0;
490 } else {
491 m -= NBBY;
492 *u = (u_char)~0;
493 if (m < 0)
494 *u <<= -m;
495 }
496 u++;
497 }
498 }
499 nsort++;
500 }
501#endif /* INET6 */
502 *cp = n;
503 }
504 continue;
505 }
506#endif
507 if (MATCH(buf, "options")) {
508 res_setoptions(buf + sizeof("options") - 1, "conf");
509 continue;
510 }
511 }
512 if (nserv > 1)
513 _res.nscount = nserv;
514#ifdef RESOLVSORT
515 _res.nsort = nsort;
516#endif
517 (void) fclose(fp);
518 }
519 if (_res.defdname[0] == 0 &&
520 gethostname(buf, sizeof(_res.defdname) - 1) == 0 &&
521 (cp = strchr(buf, '.')) != NULL)
522 {
523 strlcpy(_res.defdname, cp + 1,
524 sizeof(_res.defdname));
525 }
526
527 /* find components of local domain that might be searched */
528 if (havesearch == 0) {
529 pp = _res.dnsrch;
530 *pp++ = _res.defdname;
531 *pp = NULL;
532
533#ifndef RFC1535
534 dots = 0;
535 for (cp = _res.defdname; *cp; cp++)
536 dots += (*cp == '.');
537
538 cp = _res.defdname;
539 while (pp < _res.dnsrch + MAXDFLSRCH) {
540 if (dots < LOCALDOMAINPARTS)
541 break;
542 cp = strchr(cp, '.') + 1; /* we know there is one */
543 *pp++ = cp;
544 dots--;
545 }
546 *pp = NULL;
547#ifdef DEBUG
548 if (_res.options & RES_DEBUG) {
549 printf(";; res_init()... default dnsrch list:\n");
550 for (pp = _res.dnsrch; *pp; pp++)
551 printf(";;\t%s\n", *pp);
552 printf(";;\t..END..\n");
553 }
554#endif /* DEBUG */
555#endif /* !RFC1535 */
556 }
557
558 if (issetugid())
559 _res.options |= RES_NOALIASES;
560 else if ((cp = getenv("RES_OPTIONS")) != NULL)
561 res_setoptions(cp, "env");
562 _res.options |= RES_INIT;
563 return (0);
564}
565
566/* ARGSUSED */
567static void
568res_setoptions(options, source)
569 char *options, *source;
570{
571 char *cp = options;
572 char *endp;
573 long l;
574
575#ifdef DEBUG
576 if (_res.options & RES_DEBUG)
577 printf(";; res_setoptions(\"%s\", \"%s\")...\n",
578 options, source);
579#endif
580 while (*cp) {
581 /* skip leading and inner runs of spaces */
582 while (*cp == ' ' || *cp == '\t')
583 cp++;
584 /* search for and process individual options */
585 if (!strncmp(cp, "ndots:", sizeof("ndots:") - 1)) {
586 char *p = cp + sizeof("ndots:") - 1;
587 l = strtol(p, &endp, 10);
588 if (l >= 0 && endp != p &&
589 (*endp = '\0' || isspace(*endp))) {
590 if (l <= RES_MAXNDOTS)
591 _res.ndots = l;
592 else
593 _res.ndots = RES_MAXNDOTS;
594#ifdef DEBUG
595 if (_res.options & RES_DEBUG)
596 printf(";;\tndots=%u\n", _res.ndots);
597#endif
598 }
599 } else if (!strncmp(cp, "debug", sizeof("debug") - 1)) {
600#ifdef DEBUG
601 if (!(_res.options & RES_DEBUG)) {
602 printf(";; res_setoptions(\"%s\", \"%s\")..\n",
603 options, source);
604 _res.options |= RES_DEBUG;
605 }
606 printf(";;\tdebug\n");
607#endif
608 } else if (!strncmp(cp, "inet6", sizeof("inet6") - 1)) {
609 _res.options |= RES_USE_INET6;
610 } else if (!strncmp(cp, "insecure1", sizeof("insecure1") - 1)) {
611 _res.options |= RES_INSECURE1;
612 } else if (!strncmp(cp, "insecure2", sizeof("insecure2") - 1)) {
613 _res.options |= RES_INSECURE2;
614 } else if (!strncmp(cp, "edns0", sizeof("edns0") - 1)) {
615 _res.options |= RES_USE_EDNS0;
616 } else {
617 /* XXX - print a warning here? */
618 }
619 /* skip to next run of spaces */
620 while (*cp && *cp != ' ' && *cp != '\t')
621 cp++;
622 }
623}
624
625#ifdef RESOLVSORT
626/* XXX - should really support CIDR which means explicit masks always. */
627static u_int32_t
628net_mask(in) /* XXX - should really use system's version of this */
629 struct in_addr in;
630{
631 register u_int32_t i = ntohl(in.s_addr);
632
633 if (IN_CLASSA(i))
634 return (htonl(IN_CLASSA_NET));
635 else if (IN_CLASSB(i))
636 return (htonl(IN_CLASSB_NET));
637 return (htonl(IN_CLASSC_NET));
638}
639#endif
diff --git a/src/lib/libc/net/res_mkquery.c b/src/lib/libc/net/res_mkquery.c
new file mode 100644
index 0000000000..6cd6a00dbe
--- /dev/null
+++ b/src/lib/libc/net/res_mkquery.c
@@ -0,0 +1,242 @@
1/* $OpenBSD: res_mkquery.c,v 1.12 2002/08/28 03:19:38 itojun Exp $ */
2
3/*
4 * ++Copyright++ 1985, 1993
5 * -
6 * Copyright (c) 1985, 1993
7 * The Regents of the University of California. All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by the University of
20 * California, Berkeley and its contributors.
21 * 4. Neither the name of the University nor the names of its contributors
22 * may be used to endorse or promote products derived from this software
23 * without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
36 * -
37 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
38 *
39 * Permission to use, copy, modify, and distribute this software for any
40 * purpose with or without fee is hereby granted, provided that the above
41 * copyright notice and this permission notice appear in all copies, and that
42 * the name of Digital Equipment Corporation not be used in advertising or
43 * publicity pertaining to distribution of the document or software without
44 * specific, written prior permission.
45 *
46 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
47 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
48 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
49 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
50 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
51 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
52 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
53 * SOFTWARE.
54 * -
55 * --Copyright--
56 */
57
58#if defined(LIBC_SCCS) && !defined(lint)
59#if 0
60static char sccsid[] = "@(#)res_mkquery.c 8.1 (Berkeley) 6/4/93";
61static char rcsid[] = "$From: res_mkquery.c,v 8.5 1996/08/27 08:33:28 vixie Exp $";
62#else
63static char rcsid[] = "$OpenBSD: res_mkquery.c,v 1.12 2002/08/28 03:19:38 itojun Exp $";
64#endif
65#endif /* LIBC_SCCS and not lint */
66
67#include <sys/types.h>
68#include <sys/param.h>
69#include <netinet/in.h>
70#include <arpa/nameser.h>
71
72#include <stdio.h>
73#include <netdb.h>
74#include <resolv.h>
75#include <string.h>
76
77/*
78 * Form all types of queries.
79 * Returns the size of the result or -1.
80 */
81/* ARGSUSED */
82int
83res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen)
84 int op; /* opcode of query */
85 const char *dname; /* domain name */
86 int class, type; /* class and type of query */
87 const u_char *data; /* resource record data */
88 int datalen; /* length of data */
89 const u_char *newrr_in; /* new rr for modify or append */
90 u_char *buf; /* buffer to put query */
91 int buflen; /* size of buffer */
92{
93 register HEADER *hp;
94 register u_char *cp, *ep;
95 register int n;
96 u_char *dnptrs[20], **dpp, **lastdnptr;
97
98 if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
99 h_errno = NETDB_INTERNAL;
100 return (-1);
101 }
102#ifdef DEBUG
103 if (_res.options & RES_DEBUG)
104 printf(";; res_mkquery(%d, %s, %d, %d)\n",
105 op, dname, class, type);
106#endif
107 /*
108 * Initialize header fields.
109 *
110 * A special random number generator is used to create non predictable
111 * and non repeating ids over a long period. It also avoids reuse
112 * by switching between two distinct number cycles.
113 */
114
115 if ((buf == NULL) || (buflen < HFIXEDSZ))
116 return (-1);
117 bzero(buf, HFIXEDSZ);
118 hp = (HEADER *) buf;
119 _res.id = res_randomid();
120 hp->id = htons(_res.id);
121 hp->opcode = op;
122 hp->rd = (_res.options & RES_RECURSE) != 0;
123 hp->rcode = NOERROR;
124 cp = buf + HFIXEDSZ;
125 ep = buf + buflen;
126 dpp = dnptrs;
127 *dpp++ = buf;
128 *dpp++ = NULL;
129 lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0];
130 /*
131 * perform opcode specific processing
132 */
133 switch (op) {
134 case QUERY: /*FALLTHROUGH*/
135 case NS_NOTIFY_OP:
136 if (ep - cp < QFIXEDSZ)
137 return (-1);
138 if ((n = dn_comp(dname, cp, ep - cp - QFIXEDSZ, dnptrs,
139 lastdnptr)) < 0)
140 return (-1);
141 cp += n;
142 __putshort(type, cp);
143 cp += INT16SZ;
144 __putshort(class, cp);
145 cp += INT16SZ;
146 hp->qdcount = htons(1);
147 if (op == QUERY || data == NULL)
148 break;
149 /*
150 * Make an additional record for completion domain.
151 */
152 if (ep - cp < RRFIXEDSZ)
153 return (-1);
154 n = dn_comp((char *)data, cp, ep - cp - RRFIXEDSZ, dnptrs,
155 lastdnptr);
156 if (n < 0)
157 return (-1);
158 cp += n;
159 __putshort(T_NULL, cp);
160 cp += INT16SZ;
161 __putshort(class, cp);
162 cp += INT16SZ;
163 __putlong(0, cp);
164 cp += INT32SZ;
165 __putshort(0, cp);
166 cp += INT16SZ;
167 hp->arcount = htons(1);
168 break;
169
170 case IQUERY:
171 /*
172 * Initialize answer section
173 */
174 if (ep - cp < 1 + RRFIXEDSZ + datalen)
175 return (-1);
176 *cp++ = '\0'; /* no domain name */
177 __putshort(type, cp);
178 cp += INT16SZ;
179 __putshort(class, cp);
180 cp += INT16SZ;
181 __putlong(0, cp);
182 cp += INT32SZ;
183 __putshort(datalen, cp);
184 cp += INT16SZ;
185 if (datalen) {
186 bcopy(data, cp, datalen);
187 cp += datalen;
188 }
189 hp->ancount = htons(1);
190 break;
191
192 default:
193 return (-1);
194 }
195 return (cp - buf);
196}
197
198/* attach OPT pseudo-RR, as documented in RFC2671 (EDNS0). */
199int
200res_opt(n0, buf, buflen, anslen)
201 int n0;
202 u_char *buf; /* buffer to put query */
203 int buflen; /* size of buffer */
204 int anslen; /* answer buffer length */
205{
206 register HEADER *hp;
207 register u_char *cp, *ep;
208
209 hp = (HEADER *) buf;
210 cp = buf + n0;
211 ep = buf + buflen;
212
213 if (ep - cp < 1 + RRFIXEDSZ)
214 return -1;
215
216 *cp++ = 0; /* "." */
217
218 __putshort(T_OPT, cp); /* TYPE */
219 cp += INT16SZ;
220 if (anslen > 0xffff)
221 anslen = 0xffff; /* limit to 16bit value */
222 __putshort(anslen & 0xffff, cp); /* CLASS = UDP payload size */
223 cp += INT16SZ;
224 *cp++ = NOERROR; /* extended RCODE */
225 *cp++ = 0; /* EDNS version */
226 if (_res.options & RES_USE_DNSSEC) {
227#ifdef DEBUG
228 if (_res.options & RES_DEBUG)
229 printf(";; res_opt()... ENDS0 DNSSEC OK\n");
230#endif /* DEBUG */
231 __putshort(DNS_MESSAGEEXTFLAG_DO, cp); /* EDNS Z field */
232 cp += INT16SZ;
233 } else {
234 __putshort(0, cp); /* EDNS Z field */
235 cp += INT16SZ;
236 }
237 __putshort(0, cp); /* RDLEN */
238 cp += INT16SZ;
239 hp->arcount = htons(ntohs(hp->arcount) + 1);
240
241 return cp - buf;
242}
diff --git a/src/lib/libc/net/res_query.c b/src/lib/libc/net/res_query.c
new file mode 100644
index 0000000000..9c1aef1218
--- /dev/null
+++ b/src/lib/libc/net/res_query.c
@@ -0,0 +1,405 @@
1/* $OpenBSD: res_query.c,v 1.19 2002/06/27 09:55:49 itojun Exp $ */
2
3/*
4 * ++Copyright++ 1988, 1993
5 * -
6 * Copyright (c) 1988, 1993
7 * The Regents of the University of California. All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by the University of
20 * California, Berkeley and its contributors.
21 * 4. Neither the name of the University nor the names of its contributors
22 * may be used to endorse or promote products derived from this software
23 * without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
36 * -
37 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
38 *
39 * Permission to use, copy, modify, and distribute this software for any
40 * purpose with or without fee is hereby granted, provided that the above
41 * copyright notice and this permission notice appear in all copies, and that
42 * the name of Digital Equipment Corporation not be used in advertising or
43 * publicity pertaining to distribution of the document or software without
44 * specific, written prior permission.
45 *
46 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
47 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
48 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
49 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
50 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
51 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
52 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
53 * SOFTWARE.
54 * -
55 * --Copyright--
56 */
57
58#if defined(LIBC_SCCS) && !defined(lint)
59#if 0
60static char sccsid[] = "@(#)res_query.c 8.1 (Berkeley) 6/4/93";
61static char rcsid[] = "$From: res_query.c,v 8.9 1996/09/22 00:13:28 vixie Exp $";
62#else
63static char rcsid[] = "$OpenBSD: res_query.c,v 1.19 2002/06/27 09:55:49 itojun Exp $";
64#endif
65#endif /* LIBC_SCCS and not lint */
66
67#include <sys/types.h>
68#include <sys/param.h>
69#include <netinet/in.h>
70#include <arpa/inet.h>
71#include <arpa/nameser.h>
72
73#include <stdio.h>
74#include <netdb.h>
75#include <resolv.h>
76#include <ctype.h>
77#include <errno.h>
78#include <stdlib.h>
79#include <string.h>
80#include <unistd.h>
81
82#if PACKETSZ > 1024
83#define MAXPACKET PACKETSZ
84#else
85#define MAXPACKET 1024
86#endif
87
88const char *hostalias(const char *);
89int h_errno;
90extern int res_opt(int, u_char *, int, int);
91
92/*
93 * Formulate a normal query, send, and await answer.
94 * Returned answer is placed in supplied buffer "answer".
95 * Perform preliminary check of answer, returning success only
96 * if no error is indicated and the answer count is nonzero.
97 * Return the size of the response on success, -1 on error.
98 * Error number is left in h_errno.
99 *
100 * Caller must parse answer and determine whether it answers the question.
101 */
102int
103res_query(name, class, type, answer, anslen)
104 const char *name; /* domain name */
105 int class, type; /* class and type of query */
106 u_char *answer; /* buffer to put answer */
107 int anslen; /* size of answer buffer */
108{
109 u_char buf[MAXPACKET];
110 register HEADER *hp = (HEADER *) answer;
111 int n;
112
113 hp->rcode = NOERROR; /* default */
114
115 if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
116 h_errno = NETDB_INTERNAL;
117 return (-1);
118 }
119#ifdef DEBUG
120 if (_res.options & RES_DEBUG)
121 printf(";; res_query(%s, %d, %d)\n", name, class, type);
122#endif
123
124 n = res_mkquery(QUERY, name, class, type, NULL, 0, NULL,
125 buf, sizeof(buf));
126 if (n > 0 && ((_res.options & RES_USE_EDNS0) ||
127 (_res.options & RES_USE_DNSSEC))) {
128 n = res_opt(n, buf, sizeof(buf), anslen);
129 }
130
131 if (n <= 0) {
132#ifdef DEBUG
133 if (_res.options & RES_DEBUG)
134 printf(";; res_query: mkquery failed\n");
135#endif
136 h_errno = NO_RECOVERY;
137 return (n);
138 }
139 n = res_send(buf, n, answer, anslen);
140 if (n < 0) {
141#ifdef DEBUG
142 if (_res.options & RES_DEBUG)
143 printf(";; res_query: send error\n");
144#endif
145 h_errno = TRY_AGAIN;
146 return (n);
147 }
148
149 if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
150#ifdef DEBUG
151 if (_res.options & RES_DEBUG)
152 printf(";; rcode = %u, ancount=%u\n", hp->rcode,
153 ntohs(hp->ancount));
154#endif
155 switch (hp->rcode) {
156 case NXDOMAIN:
157 h_errno = HOST_NOT_FOUND;
158 break;
159 case SERVFAIL:
160 h_errno = TRY_AGAIN;
161 break;
162 case NOERROR:
163 h_errno = NO_DATA;
164 break;
165 case FORMERR:
166 case NOTIMP:
167 case REFUSED:
168 default:
169 h_errno = NO_RECOVERY;
170 break;
171 }
172 return (-1);
173 }
174 return (n);
175}
176
177/*
178 * Formulate a normal query, send, and retrieve answer in supplied buffer.
179 * Return the size of the response on success, -1 on error.
180 * If enabled, implement search rules until answer or unrecoverable failure
181 * is detected. Error code, if any, is left in h_errno.
182 */
183int
184res_search(name, class, type, answer, anslen)
185 const char *name; /* domain name */
186 int class, type; /* class and type of query */
187 u_char *answer; /* buffer to put answer */
188 int anslen; /* size of answer */
189{
190 register const char *cp, * const *domain;
191 HEADER *hp = (HEADER *) answer;
192 u_int dots;
193 int trailing_dot, ret, saved_herrno;
194 int got_nodata = 0, got_servfail = 0, tried_as_is = 0;
195
196 if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
197 h_errno = NETDB_INTERNAL;
198 return (-1);
199 }
200 errno = 0;
201 h_errno = HOST_NOT_FOUND; /* default, if we never query */
202 dots = 0;
203 for (cp = name; *cp; cp++)
204 dots += (*cp == '.');
205 trailing_dot = 0;
206 if (cp > name && *--cp == '.')
207 trailing_dot++;
208
209 /*
210 * if there aren't any dots, it could be a user-level alias
211 */
212 if (!dots && (cp = __hostalias(name)) != NULL)
213 return (res_query(cp, class, type, answer, anslen));
214
215 /*
216 * If there are dots in the name already, let's just give it a try
217 * 'as is'. The threshold can be set with the "ndots" option.
218 */
219 saved_herrno = -1;
220 if (dots >= _res.ndots) {
221 ret = res_querydomain(name, NULL, class, type, answer, anslen);
222 if (ret > 0)
223 return (ret);
224 saved_herrno = h_errno;
225 tried_as_is++;
226 }
227
228 /*
229 * We do at least one level of search if
230 * - there is no dot and RES_DEFNAME is set, or
231 * - there is at least one dot, there is no trailing dot,
232 * and RES_DNSRCH is set.
233 */
234 if ((!dots && (_res.options & RES_DEFNAMES)) ||
235 (dots && !trailing_dot && (_res.options & RES_DNSRCH))) {
236 int done = 0;
237
238 for (domain = (const char * const *)_res.dnsrch;
239 *domain && !done;
240 domain++) {
241
242 ret = res_querydomain(name, *domain, class, type,
243 answer, anslen);
244 if (ret > 0)
245 return (ret);
246
247 /*
248 * If no server present, give up.
249 * If name isn't found in this domain,
250 * keep trying higher domains in the search list
251 * (if that's enabled).
252 * On a NO_DATA error, keep trying, otherwise
253 * a wildcard entry of another type could keep us
254 * from finding this entry higher in the domain.
255 * If we get some other error (negative answer or
256 * server failure), then stop searching up,
257 * but try the input name below in case it's
258 * fully-qualified.
259 */
260 if (errno == ECONNREFUSED) {
261 h_errno = TRY_AGAIN;
262 return (-1);
263 }
264
265 switch (h_errno) {
266 case NO_DATA:
267 got_nodata++;
268 /* FALLTHROUGH */
269 case HOST_NOT_FOUND:
270 /* keep trying */
271 break;
272 case TRY_AGAIN:
273 if (hp->rcode == SERVFAIL) {
274 /* try next search element, if any */
275 got_servfail++;
276 break;
277 }
278 /* FALLTHROUGH */
279 default:
280 /* anything else implies that we're done */
281 done++;
282 }
283
284 /* if we got here for some reason other than DNSRCH,
285 * we only wanted one iteration of the loop, so stop.
286 */
287 if (!(_res.options & RES_DNSRCH))
288 done++;
289 }
290 }
291
292 /* if we have not already tried the name "as is", do that now.
293 * note that we do this regardless of how many dots were in the
294 * name or whether it ends with a dot.
295 */
296 if (!tried_as_is) {
297 ret = res_querydomain(name, NULL, class, type, answer, anslen);
298 if (ret > 0)
299 return (ret);
300 }
301
302 /* if we got here, we didn't satisfy the search.
303 * if we did an initial full query, return that query's h_errno
304 * (note that we wouldn't be here if that query had succeeded).
305 * else if we ever got a nodata, send that back as the reason.
306 * else send back meaningless h_errno, that being the one from
307 * the last DNSRCH we did.
308 */
309 if (saved_herrno != -1)
310 h_errno = saved_herrno;
311 else if (got_nodata)
312 h_errno = NO_DATA;
313 else if (got_servfail)
314 h_errno = TRY_AGAIN;
315 return (-1);
316}
317
318/*
319 * Perform a call on res_query on the concatenation of name and domain,
320 * removing a trailing dot from name if domain is NULL.
321 */
322int
323res_querydomain(name, domain, class, type, answer, anslen)
324 const char *name, *domain;
325 int class, type; /* class and type of query */
326 u_char *answer; /* buffer to put answer */
327 int anslen; /* size of answer */
328{
329 char nbuf[MAXDNAME*2+1+1];
330 const char *longname = nbuf;
331 int n;
332
333 if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
334 h_errno = NETDB_INTERNAL;
335 return (-1);
336 }
337#ifdef DEBUG
338 if (_res.options & RES_DEBUG)
339 printf(";; res_querydomain(%s, %s, %d, %d)\n",
340 name, domain?domain:"<Nil>", class, type);
341#endif
342 if (domain == NULL) {
343 /*
344 * Check for trailing '.';
345 * copy without '.' if present.
346 */
347 n = strlen(name) - 1;
348 if (n != (0 - 1) && name[n] == '.' && n < sizeof(nbuf) - 1) {
349 bcopy(name, nbuf, n);
350 nbuf[n] = '\0';
351 } else
352 longname = name;
353 } else
354 snprintf(nbuf, sizeof nbuf, "%.*s.%.*s",
355 MAXDNAME, name, MAXDNAME, domain);
356
357 return (res_query(longname, class, type, answer, anslen));
358}
359
360const char *
361hostalias(name)
362 register const char *name;
363{
364 register char *cp1, *cp2;
365 FILE *fp;
366 char *file;
367 char buf[BUFSIZ];
368 static char abuf[MAXDNAME];
369 size_t len;
370
371 if (_res.options & RES_NOALIASES)
372 return (NULL);
373 file = getenv("HOSTALIASES");
374 if (issetugid() != 0 || file == NULL || (fp = fopen(file, "r")) == NULL)
375 return (NULL);
376 setbuf(fp, NULL);
377 while ((cp1 = fgetln(fp, &len)) != NULL) {
378 if (cp1[len-1] == '\n')
379 len--;
380 if (len >= sizeof(buf) || len == 0)
381 continue;
382 (void)memcpy(buf, cp1, len);
383 buf[len] = '\0';
384
385 for (cp1 = buf; *cp1 && !isspace(*cp1); ++cp1)
386 ;
387 if (!*cp1)
388 break;
389 *cp1 = '\0';
390 if (!strcasecmp(buf, name)) {
391 while (isspace(*++cp1))
392 ;
393 if (!*cp1)
394 break;
395 for (cp2 = cp1 + 1; *cp2 && !isspace(*cp2); ++cp2)
396 ;
397 *cp2 = '\0';
398 strlcpy(abuf, cp1, sizeof(abuf));
399 fclose(fp);
400 return (abuf);
401 }
402 }
403 fclose(fp);
404 return (NULL);
405}
diff --git a/src/lib/libc/net/res_random.c b/src/lib/libc/net/res_random.c
new file mode 100644
index 0000000000..c739e4a952
--- /dev/null
+++ b/src/lib/libc/net/res_random.c
@@ -0,0 +1,229 @@
1/* $OpenBSD: res_random.c,v 1.12 2002/06/27 10:14:02 itojun Exp $ */
2
3/*
4 * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de>
5 * All rights reserved.
6 *
7 * Theo de Raadt <deraadt@openbsd.org> came up with the idea of using
8 * such a mathematical system to generate more random (yet non-repeating)
9 * ids to solve the resolver/named problem. But Niels designed the
10 * actual system based on the constraints.
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 Niels Provos.
23 * 4. The name of the author may not be used to endorse or promote products
24 * derived from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
27 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
28 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
29 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
30 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
31 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
35 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 */
37
38/*
39 * seed = random 15bit
40 * n = prime, g0 = generator to n,
41 * j = random so that gcd(j,n-1) == 1
42 * g = g0^j mod n will be a generator again.
43 *
44 * X[0] = random seed.
45 * X[n] = a*X[n-1]+b mod m is a Linear Congruential Generator
46 * with a = 7^(even random) mod m,
47 * b = random with gcd(b,m) == 1
48 * m = 31104 and a maximal period of m-1.
49 *
50 * The transaction id is determined by:
51 * id[n] = seed xor (g^X[n] mod n)
52 *
53 * Effectivly the id is restricted to the lower 15 bits, thus
54 * yielding two different cycles by toggling the msb on and off.
55 * This avoids reuse issues caused by reseeding.
56 *
57 * The 16 bit space is very small and brute force attempts are
58 * entirly feasible, we skip a random number of transaction ids
59 * so that an attacker will not get sequential ids.
60 */
61
62#include <sys/types.h>
63#include <netinet/in.h>
64#include <sys/time.h>
65#include <resolv.h>
66
67#include <unistd.h>
68#include <stdlib.h>
69#include <string.h>
70
71#define RU_OUT 180 /* Time after wich will be reseeded */
72#define RU_MAX 30000 /* Uniq cycle, avoid blackjack prediction */
73#define RU_GEN 2 /* Starting generator */
74#define RU_N 32749 /* RU_N-1 = 2*2*3*2729 */
75#define RU_AGEN 7 /* determine ru_a as RU_AGEN^(2*rand) */
76#define RU_M 31104 /* RU_M = 2^7*3^5 - don't change */
77
78#define PFAC_N 3
79const static u_int16_t pfacts[PFAC_N] = {
80 2,
81 3,
82 2729
83};
84
85static u_int16_t ru_x;
86static u_int16_t ru_seed, ru_seed2;
87static u_int16_t ru_a, ru_b;
88static u_int16_t ru_g;
89static u_int16_t ru_counter = 0;
90static u_int16_t ru_msb = 0;
91static long ru_reseed;
92static u_int32_t tmp; /* Storage for unused random */
93static struct timeval tv;
94
95static u_int16_t pmod(u_int16_t, u_int16_t, u_int16_t);
96static void res_initid(void);
97
98/*
99 * Do a fast modular exponation, returned value will be in the range
100 * of 0 - (mod-1)
101 */
102
103static u_int16_t
104pmod(u_int16_t gen, u_int16_t exp, u_int16_t mod)
105{
106 u_int16_t s, t, u;
107
108 s = 1;
109 t = gen;
110 u = exp;
111
112 while (u) {
113 if (u & 1)
114 s = (s*t) % mod;
115 u >>= 1;
116 t = (t*t) % mod;
117 }
118 return (s);
119}
120
121/*
122 * Initializes the seed and chooses a suitable generator. Also toggles
123 * the msb flag. The msb flag is used to generate two distinct
124 * cycles of random numbers and thus avoiding reuse of ids.
125 *
126 * This function is called from res_randomid() when needed, an
127 * application does not have to worry about it.
128 */
129static void
130res_initid()
131{
132 u_int16_t j, i;
133 int noprime = 1;
134
135 tmp = arc4random();
136 ru_x = (tmp & 0xFFFF) % RU_M;
137
138 /* 15 bits of random seed */
139 ru_seed = (tmp >> 16) & 0x7FFF;
140 tmp = arc4random();
141 ru_seed2 = tmp & 0x7FFF;
142
143 tmp = arc4random();
144
145 /* Determine the LCG we use */
146 ru_b = (tmp & 0xfffe) | 1;
147 ru_a = pmod(RU_AGEN, (tmp >> 16) & 0xfffe, RU_M);
148 while (ru_b % 3 == 0)
149 ru_b += 2;
150
151 tmp = arc4random();
152 j = tmp % RU_N;
153 tmp = tmp >> 16;
154
155 /*
156 * Do a fast gcd(j,RU_N-1), so we can find a j with
157 * gcd(j, RU_N-1) == 1, giving a new generator for
158 * RU_GEN^j mod RU_N
159 */
160
161 while (noprime) {
162 for (i=0; i<PFAC_N; i++)
163 if (j%pfacts[i] == 0)
164 break;
165
166 if (i>=PFAC_N)
167 noprime = 0;
168 else
169 j = (j+1) % RU_N;
170 }
171
172 ru_g = pmod(RU_GEN,j,RU_N);
173 ru_counter = 0;
174
175 gettimeofday(&tv, NULL);
176 ru_reseed = tv.tv_sec + RU_OUT;
177 ru_msb = ru_msb == 0x8000 ? 0 : 0x8000;
178}
179
180u_int
181res_randomid()
182{
183 int i, n;
184
185 gettimeofday(&tv, NULL);
186 if (ru_counter >= RU_MAX || tv.tv_sec > ru_reseed)
187 res_initid();
188
189 if (!tmp)
190 tmp = arc4random();
191
192 /* Skip a random number of ids */
193 n = tmp & 0x7; tmp = tmp >> 3;
194 if (ru_counter + n >= RU_MAX)
195 res_initid();
196
197 for (i=0; i<=n; i++)
198 /* Linear Congruential Generator */
199 ru_x = (ru_a*ru_x + ru_b) % RU_M;
200
201 ru_counter += i;
202
203 return (ru_seed ^ pmod(ru_g,ru_seed2 ^ ru_x,RU_N)) | ru_msb;
204}
205
206#if 0
207void
208main(int argc, char **argv)
209{
210 int i, n;
211 u_int16_t wert;
212
213 res_initid();
214
215 printf("Generator: %u\n", ru_g);
216 printf("Seed: %u\n", ru_seed);
217 printf("Reseed at %ld\n", ru_reseed);
218 printf("Ru_X: %u\n", ru_x);
219 printf("Ru_A: %u\n", ru_a);
220 printf("Ru_B: %u\n", ru_b);
221
222 n = atoi(argv[1]);
223 for (i=0;i<n;i++) {
224 wert = res_randomid();
225 printf("%06d\n", wert);
226 }
227}
228#endif
229
diff --git a/src/lib/libc/net/res_send.c b/src/lib/libc/net/res_send.c
new file mode 100644
index 0000000000..b043e7c9fb
--- /dev/null
+++ b/src/lib/libc/net/res_send.c
@@ -0,0 +1,893 @@
1/* $OpenBSD: res_send.c,v 1.12 2002/09/06 18:35:12 deraadt Exp $ */
2
3/*
4 * ++Copyright++ 1985, 1989, 1993
5 * -
6 * Copyright (c) 1985, 1989, 1993
7 * The Regents of the University of California. All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by the University of
20 * California, Berkeley and its contributors.
21 * 4. Neither the name of the University nor the names of its contributors
22 * may be used to endorse or promote products derived from this software
23 * without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
36 * -
37 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
38 *
39 * Permission to use, copy, modify, and distribute this software for any
40 * purpose with or without fee is hereby granted, provided that the above
41 * copyright notice and this permission notice appear in all copies, and that
42 * the name of Digital Equipment Corporation not be used in advertising or
43 * publicity pertaining to distribution of the document or software without
44 * specific, written prior permission.
45 *
46 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
47 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
48 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
49 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
50 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
51 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
52 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
53 * SOFTWARE.
54 * -
55 * --Copyright--
56 */
57
58#ifndef INET6
59#define INET6
60#endif
61
62#if defined(LIBC_SCCS) && !defined(lint)
63#if 0
64static char sccsid[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93";
65static char rcsid[] = "$From: res_send.c,v 8.12 1996/10/08 04:51:06 vixie Exp $";
66#else
67static char rcsid[] = "$OpenBSD: res_send.c,v 1.12 2002/09/06 18:35:12 deraadt Exp $";
68#endif
69#endif /* LIBC_SCCS and not lint */
70
71 /* change this to "0"
72 * if you talk to a lot
73 * of multi-homed SunOS
74 * ("broken") name servers.
75 */
76#define CHECK_SRVR_ADDR 1 /* XXX - should be in options.h */
77
78/*
79 * Send query to name server and wait for reply.
80 */
81
82#include <sys/types.h>
83#include <sys/param.h>
84#include <sys/time.h>
85#include <sys/socket.h>
86#include <sys/uio.h>
87#include <netinet/in.h>
88#include <arpa/nameser.h>
89#include <arpa/inet.h>
90
91#include <stdio.h>
92#include <netdb.h>
93#include <errno.h>
94#include <resolv.h>
95#include <stdlib.h>
96#include <string.h>
97#include <unistd.h>
98
99static int s = -1; /* socket used for communications */
100static int connected = 0; /* is the socket connected */
101static int vc = 0; /* is the socket a virtual ciruit? */
102static int af = 0; /* address family of socket */
103
104#ifndef FD_SET
105/* XXX - should be in portability.h */
106#define NFDBITS 32
107#define FD_SETSIZE 32
108#define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
109#define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
110#define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
111#define FD_ZERO(p) bzero((char *)(p), sizeof(*(p)))
112#endif
113
114#define CAN_RECONNECT 1
115
116#ifndef DEBUG
117# define Dprint(cond, args) /*empty*/
118# define DprintQ(cond, args, query, size) /*empty*/
119# define Aerror(file, string, error, address) /*empty*/
120# define Perror(file, string, error) /*empty*/
121#else
122# define Dprint(cond, args) if (cond) {fprintf args;} else {}
123# define DprintQ(cond, args, query, size) if (cond) {\
124 fprintf args;\
125 __fp_nquery(query, size, stdout);\
126 } else {}
127static char abuf[NI_MAXHOST];
128static char pbuf[NI_MAXSERV];
129static void Aerror(FILE *, char *, int, struct sockaddr *);
130static void Perror(FILE *, char *, int);
131
132 static void
133 Aerror(file, string, error, address)
134 FILE *file;
135 char *string;
136 int error;
137 struct sockaddr *address;
138 {
139 int save = errno;
140
141 if (_res.options & RES_DEBUG) {
142 if (getnameinfo(address, address->sa_len, abuf, sizeof(abuf),
143 pbuf, sizeof(pbuf),
144 NI_NUMERICHOST|NI_NUMERICSERV|NI_WITHSCOPEID) != 0) {
145 strncpy(abuf, "?", sizeof(abuf));
146 strncpy(pbuf, "?", sizeof(pbuf));
147 }
148 fprintf(file, "res_send: %s ([%s].%s): %s\n",
149 string, abuf, pbuf, strerror(error));
150 }
151 errno = save;
152 }
153 static void
154 Perror(file, string, error)
155 FILE *file;
156 char *string;
157 int error;
158 {
159 int save = errno;
160
161 if (_res.options & RES_DEBUG) {
162 fprintf(file, "res_send: %s: %s\n",
163 string, strerror(error));
164 }
165 errno = save;
166 }
167#endif
168
169static res_send_qhook Qhook = NULL;
170static res_send_rhook Rhook = NULL;
171
172void
173res_send_setqhook(hook)
174 res_send_qhook hook;
175{
176
177 Qhook = hook;
178}
179
180void
181res_send_setrhook(hook)
182 res_send_rhook hook;
183{
184
185 Rhook = hook;
186}
187
188#ifdef INET6
189static struct sockaddr * get_nsaddr(size_t);
190
191/*
192 * pick appropriate nsaddr_list for use. see res_init() for initialization.
193 */
194static struct sockaddr *
195get_nsaddr(n)
196 size_t n;
197{
198
199 if (!_res.nsaddr_list[n].sin_family) {
200 /*
201 * - _res_ext.nsaddr_list[n] holds an address that is larger
202 * than struct sockaddr, and
203 * - user code did not update _res.nsaddr_list[n].
204 */
205 return (struct sockaddr *)&_res_ext.nsaddr_list[n];
206 } else {
207 /*
208 * - user code updated _res.nsaddr_list[n], or
209 * - _res.nsaddr_list[n] has the same content as
210 * _res_ext.nsaddr_list[n].
211 */
212 return (struct sockaddr *)&_res.nsaddr_list[n];
213 }
214}
215#else
216#define get_nsaddr(n) ((struct sockaddr *)&_res.nsaddr_list[(n)])
217#endif
218
219/* int
220 * res_isourserver(ina)
221 * looks up "ina" in _res.ns_addr_list[]
222 * returns:
223 * 0 : not found
224 * >0 : found
225 * author:
226 * paul vixie, 29may94
227 */
228int
229res_isourserver(inp)
230 const struct sockaddr_in *inp;
231{
232#ifdef INET6
233 const struct sockaddr_in6 *in6p = (const struct sockaddr_in6 *)inp;
234 const struct sockaddr_in6 *srv6;
235#endif
236 const struct sockaddr_in *srv;
237 int ns, ret;
238
239 ret = 0;
240 switch (inp->sin_family) {
241#ifdef INET6
242 case AF_INET6:
243 for (ns = 0; ns < _res.nscount; ns++) {
244 srv6 = (struct sockaddr_in6 *)get_nsaddr(ns);
245 if (srv6->sin6_family == in6p->sin6_family &&
246 srv6->sin6_port == in6p->sin6_port &&
247 srv6->sin6_scope_id == in6p->sin6_scope_id &&
248 (IN6_IS_ADDR_UNSPECIFIED(&srv6->sin6_addr) ||
249 IN6_ARE_ADDR_EQUAL(&srv6->sin6_addr,
250 &in6p->sin6_addr))) {
251 ret++;
252 break;
253 }
254 }
255 break;
256#endif
257 case AF_INET:
258 for (ns = 0; ns < _res.nscount; ns++) {
259 srv = (struct sockaddr_in *)get_nsaddr(ns);
260 if (srv->sin_family == inp->sin_family &&
261 srv->sin_port == inp->sin_port &&
262 (srv->sin_addr.s_addr == INADDR_ANY ||
263 srv->sin_addr.s_addr == inp->sin_addr.s_addr)) {
264 ret++;
265 break;
266 }
267 }
268 break;
269 }
270 return (ret);
271}
272
273/* int
274 * res_nameinquery(name, type, class, buf, eom)
275 * look for (name,type,class) in the query section of packet (buf,eom)
276 * returns:
277 * -1 : format error
278 * 0 : not found
279 * >0 : found
280 * author:
281 * paul vixie, 29may94
282 */
283int
284res_nameinquery(name, type, class, buf, eom)
285 const char *name;
286 register int type, class;
287 const u_char *buf, *eom;
288{
289 register const u_char *cp = buf + HFIXEDSZ;
290 int qdcount = ntohs(((HEADER*)buf)->qdcount);
291
292 while (qdcount-- > 0) {
293 char tname[MAXDNAME+1];
294 register int n, ttype, tclass;
295
296 n = dn_expand(buf, eom, cp, tname, sizeof tname);
297 if (n < 0)
298 return (-1);
299 cp += n;
300 ttype = _getshort(cp); cp += INT16SZ;
301 tclass = _getshort(cp); cp += INT16SZ;
302 if (ttype == type &&
303 tclass == class &&
304 strcasecmp(tname, name) == 0)
305 return (1);
306 }
307 return (0);
308}
309
310/* int
311 * res_queriesmatch(buf1, eom1, buf2, eom2)
312 * is there a 1:1 mapping of (name,type,class)
313 * in (buf1,eom1) and (buf2,eom2)?
314 * returns:
315 * -1 : format error
316 * 0 : not a 1:1 mapping
317 * >0 : is a 1:1 mapping
318 * author:
319 * paul vixie, 29may94
320 */
321int
322res_queriesmatch(buf1, eom1, buf2, eom2)
323 const u_char *buf1, *eom1;
324 const u_char *buf2, *eom2;
325{
326 register const u_char *cp = buf1 + HFIXEDSZ;
327 int qdcount = ntohs(((HEADER*)buf1)->qdcount);
328
329 if (qdcount != ntohs(((HEADER*)buf2)->qdcount))
330 return (0);
331 while (qdcount-- > 0) {
332 char tname[MAXDNAME+1];
333 register int n, ttype, tclass;
334
335 n = dn_expand(buf1, eom1, cp, tname, sizeof tname);
336 if (n < 0)
337 return (-1);
338 cp += n;
339 ttype = _getshort(cp); cp += INT16SZ;
340 tclass = _getshort(cp); cp += INT16SZ;
341 if (!res_nameinquery(tname, ttype, tclass, buf2, eom2))
342 return (0);
343 }
344 return (1);
345}
346
347int
348res_send(buf, buflen, ans, anssiz)
349 const u_char *buf;
350 int buflen;
351 u_char *ans;
352 int anssiz;
353{
354 HEADER *hp = (HEADER *) buf;
355 HEADER *anhp = (HEADER *) ans;
356 int gotsomewhere, connreset, terrno, try, v_circuit, resplen, ns;
357 register int n;
358 u_int badns; /* XXX NSMAX can't exceed #/bits in this var */
359
360 if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
361 /* errno should have been set by res_init() in this case. */
362 return (-1);
363 }
364 DprintQ((_res.options & RES_DEBUG) || (_res.pfcode & RES_PRF_QUERY),
365 (stdout, ";; res_send()\n"), buf, buflen);
366 v_circuit = (_res.options & RES_USEVC) || buflen > PACKETSZ;
367 gotsomewhere = 0;
368 connreset = 0;
369 terrno = ETIMEDOUT;
370 badns = 0;
371
372 /*
373 * Send request, RETRY times, or until successful
374 */
375 for (try = 0; try < _res.retry; try++) {
376 for (ns = 0; ns < _res.nscount; ns++) {
377 struct sockaddr *nsap = get_nsaddr(ns);
378 socklen_t salen;
379
380 if (nsap->sa_len)
381 salen = nsap->sa_len;
382#ifdef INET6
383 else if (nsap->sa_family == AF_INET6)
384 salen = sizeof(struct sockaddr_in6);
385#endif
386 else if (nsap->sa_family == AF_INET)
387 salen = sizeof(struct sockaddr_in);
388 else
389 salen = 0; /*unknown, die on connect*/
390
391 same_ns:
392 if (badns & (1 << ns)) {
393 res_close();
394 goto next_ns;
395 }
396
397 if (Qhook) {
398 int done = 0, loops = 0;
399
400 do {
401 res_sendhookact act;
402
403 act = (*Qhook)((struct sockaddr_in **)&nsap,
404 &buf, &buflen,
405 ans, anssiz, &resplen);
406 switch (act) {
407 case res_goahead:
408 done = 1;
409 break;
410 case res_nextns:
411 res_close();
412 goto next_ns;
413 case res_done:
414 return (resplen);
415 case res_modified:
416 /* give the hook another try */
417 if (++loops < 42) /*doug adams*/
418 break;
419 /*FALLTHROUGH*/
420 case res_error:
421 /*FALLTHROUGH*/
422 default:
423 return (-1);
424 }
425 } while (!done);
426 }
427
428 Dprint((_res.options & RES_DEBUG) &&
429 getnameinfo(nsap, salen, abuf, sizeof(abuf),
430 NULL, 0, NI_NUMERICHOST | NI_WITHSCOPEID) == 0,
431 (stdout, ";; Querying server (# %d) address = %s\n",
432 ns + 1, abuf));
433
434 if (v_circuit) {
435 int truncated;
436 struct iovec iov[2];
437 u_short len;
438 u_char *cp;
439
440 /*
441 * Use virtual circuit;
442 * at most one attempt per server.
443 */
444 try = _res.retry;
445 truncated = 0;
446 if ((s < 0) || (!vc) || (af != nsap->sa_family)) {
447 if (s >= 0)
448 res_close();
449
450 af = nsap->sa_family;
451 s = socket(af, SOCK_STREAM, 0);
452 if (s < 0) {
453 terrno = errno;
454 Perror(stderr, "socket(vc)", errno);
455#if 0
456 return (-1);
457#else
458 badns |= (1 << ns);
459 res_close();
460 goto next_ns;
461#endif
462 }
463 errno = 0;
464 if (connect(s, nsap, salen) < 0) {
465 terrno = errno;
466 Aerror(stderr, "connect/vc",
467 errno, nsap);
468 badns |= (1 << ns);
469 res_close();
470 goto next_ns;
471 }
472 vc = 1;
473 }
474 /*
475 * Send length & message
476 */
477 putshort((u_short)buflen, (u_char*)&len);
478 iov[0].iov_base = (caddr_t)&len;
479 iov[0].iov_len = INT16SZ;
480 iov[1].iov_base = (caddr_t)buf;
481 iov[1].iov_len = buflen;
482 if (writev(s, iov, 2) != (INT16SZ + buflen)) {
483 terrno = errno;
484 Perror(stderr, "write failed", errno);
485 badns |= (1 << ns);
486 res_close();
487 goto next_ns;
488 }
489 /*
490 * Receive length & response
491 */
492read_len:
493 cp = ans;
494 len = INT16SZ;
495 while ((n = read(s, (char *)cp, (int)len)) > 0) {
496 cp += n;
497 if ((len -= n) <= 0)
498 break;
499 }
500 if (n <= 0) {
501 terrno = errno;
502 Perror(stderr, "read failed", errno);
503 res_close();
504 /*
505 * A long running process might get its TCP
506 * connection reset if the remote server was
507 * restarted. Requery the server instead of
508 * trying a new one. When there is only one
509 * server, this means that a query might work
510 * instead of failing. We only allow one reset
511 * per query to prevent looping.
512 */
513 if (terrno == ECONNRESET && !connreset) {
514 connreset = 1;
515 res_close();
516 goto same_ns;
517 }
518 res_close();
519 goto next_ns;
520 }
521 resplen = _getshort(ans);
522 if (resplen > anssiz) {
523 Dprint(_res.options & RES_DEBUG,
524 (stdout, ";; response truncated\n")
525 );
526 truncated = 1;
527 len = anssiz;
528 } else
529 len = resplen;
530 cp = ans;
531 while (len != 0 &&
532 (n = read(s, (char *)cp, (int)len)) > 0) {
533 cp += n;
534 len -= n;
535 }
536 if (n <= 0) {
537 terrno = errno;
538 Perror(stderr, "read(vc)", errno);
539 res_close();
540 goto next_ns;
541 }
542 if (truncated) {
543 /*
544 * Flush rest of answer
545 * so connection stays in synch.
546 */
547 anhp->tc = 1;
548 len = resplen - anssiz;
549 while (len != 0) {
550 char junk[PACKETSZ];
551
552 n = (len > sizeof(junk)
553 ? sizeof(junk)
554 : len);
555 if ((n = read(s, junk, n)) > 0)
556 len -= n;
557 else
558 break;
559 }
560 }
561 /*
562 * The calling applicating has bailed out of
563 * a previous call and failed to arrange to have
564 * the circuit closed or the server has got
565 * itself confused. Anyway drop the packet and
566 * wait for the correct one.
567 */
568 if (hp->id != anhp->id) {
569 DprintQ((_res.options & RES_DEBUG) ||
570 (_res.pfcode & RES_PRF_REPLY),
571 (stdout, ";; old answer (unexpected):\n"),
572 ans, (resplen>anssiz)?anssiz:resplen);
573 goto read_len;
574 }
575 } else {
576 /*
577 * Use datagrams.
578 */
579 struct timeval timeout;
580 fd_set *dsmaskp;
581 struct sockaddr_storage from;
582 socklen_t fromlen;
583
584 if ((s < 0) || vc || (af != nsap->sa_family)) {
585 if (vc)
586 res_close();
587 af = nsap->sa_family;
588 s = socket(af, SOCK_DGRAM, 0);
589 if (s < 0) {
590#if !CAN_RECONNECT
591 bad_dg_sock:
592#endif
593 terrno = errno;
594 Perror(stderr, "socket(dg)", errno);
595#if 0
596 return (-1);
597#else
598 badns |= (1 << ns);
599 res_close();
600 goto next_ns;
601#endif
602 }
603#ifdef IPV6_MINMTU
604 if (af == AF_INET6) {
605 const int yes = 1;
606 (void)setsockopt(s, IPPROTO_IPV6,
607 IPV6_USE_MIN_MTU, &yes,
608 sizeof(yes));
609 }
610#endif
611 connected = 0;
612 }
613 /*
614 * On a 4.3BSD+ machine (client and server,
615 * actually), sending to a nameserver datagram
616 * port with no nameserver will cause an
617 * ICMP port unreachable message to be returned.
618 * If our datagram socket is "connected" to the
619 * server, we get an ECONNREFUSED error on the next
620 * socket operation, and select returns if the
621 * error message is received. We can thus detect
622 * the absence of a nameserver without timing out.
623 * If we have sent queries to at least two servers,
624 * however, we don't want to remain connected,
625 * as we wish to receive answers from the first
626 * server to respond.
627 */
628 if (!(_res.options & RES_INSECURE1) &&
629 (_res.nscount == 1 || (try == 0 && ns == 0))) {
630 /*
631 * Connect only if we are sure we won't
632 * receive a response from another server.
633 */
634 if (!connected) {
635 if (connect(s, nsap, salen) < 0) {
636 Aerror(stderr,
637 "connect(dg)",
638 errno, nsap);
639 badns |= (1 << ns);
640 res_close();
641 goto next_ns;
642 }
643 connected = 1;
644 }
645 if (send(s, (char*)buf, buflen, 0) != buflen) {
646 Perror(stderr, "send", errno);
647 badns |= (1 << ns);
648 res_close();
649 goto next_ns;
650 }
651 } else {
652 /*
653 * Disconnect if we want to listen
654 * for responses from more than one server.
655 */
656 if (connected) {
657#if CAN_RECONNECT
658#ifdef INET6
659 /* XXX: any errornous address */
660#endif /* INET6 */
661 struct sockaddr_in no_addr;
662
663 no_addr.sin_family = AF_INET;
664 no_addr.sin_addr.s_addr = INADDR_ANY;
665 no_addr.sin_port = 0;
666 (void) connect(s,
667 (struct sockaddr *)
668 &no_addr,
669 sizeof(no_addr));
670#else
671 int s1 = socket(af, SOCK_DGRAM,0);
672 if (s1 < 0)
673 goto bad_dg_sock;
674 (void) dup2(s1, s);
675 (void) close(s1);
676 Dprint(_res.options & RES_DEBUG,
677 (stdout, ";; new DG socket\n"))
678#endif
679#ifdef IPV6_MINMTU
680 if (af == AF_INET6) {
681 const int yes = 1;
682 (void)setsockopt(s, IPPROTO_IPV6,
683 IPV6_USE_MIN_MTU, &yes,
684 sizeof(yes));
685 }
686#endif
687 connected = 0;
688 errno = 0;
689 }
690 if (sendto(s, (char*)buf, buflen, 0,
691 nsap, salen) != buflen) {
692 Aerror(stderr, "sendto", errno, nsap);
693 badns |= (1 << ns);
694 res_close();
695 goto next_ns;
696 }
697 }
698
699 /*
700 * Wait for reply
701 */
702 timeout.tv_sec = (_res.retrans << try);
703 if (try > 0)
704 timeout.tv_sec /= _res.nscount;
705 if ((long) timeout.tv_sec <= 0)
706 timeout.tv_sec = 1;
707 timeout.tv_usec = 0;
708 wait:
709 dsmaskp = (fd_set *)calloc(howmany(s+1, NFDBITS),
710 sizeof(fd_mask));
711 if (dsmaskp == NULL) {
712 res_close();
713 goto next_ns;
714 }
715 FD_SET(s, dsmaskp);
716 n = select(s+1, dsmaskp, (fd_set *)NULL,
717 (fd_set *)NULL, &timeout);
718 free(dsmaskp);
719 if (n < 0) {
720 if (errno == EINTR)
721 goto wait;
722 Perror(stderr, "select", errno);
723 res_close();
724 goto next_ns;
725 }
726 if (n == 0) {
727 /*
728 * timeout
729 */
730 Dprint(_res.options & RES_DEBUG,
731 (stdout, ";; timeout\n"));
732 gotsomewhere = 1;
733 res_close();
734 goto next_ns;
735 }
736 errno = 0;
737 fromlen = sizeof(from);
738 resplen = recvfrom(s, (char*)ans, anssiz, 0,
739 (struct sockaddr *)&from, &fromlen);
740 if (resplen <= 0) {
741 Perror(stderr, "recvfrom", errno);
742 res_close();
743 goto next_ns;
744 }
745 gotsomewhere = 1;
746 if (hp->id != anhp->id) {
747 /*
748 * response from old query, ignore it.
749 * XXX - potential security hazard could
750 * be detected here.
751 */
752 DprintQ((_res.options & RES_DEBUG) ||
753 (_res.pfcode & RES_PRF_REPLY),
754 (stdout, ";; old answer:\n"),
755 ans, (resplen>anssiz)?anssiz:resplen);
756 goto wait;
757 }
758#if CHECK_SRVR_ADDR
759 if (!(_res.options & RES_INSECURE1) &&
760 !res_isourserver((struct sockaddr_in *)&from)) {
761 /*
762 * response from wrong server? ignore it.
763 * XXX - potential security hazard could
764 * be detected here.
765 */
766 DprintQ((_res.options & RES_DEBUG) ||
767 (_res.pfcode & RES_PRF_REPLY),
768 (stdout, ";; not our server:\n"),
769 ans, (resplen>anssiz)?anssiz:resplen);
770 goto wait;
771 }
772#endif
773 if (!(_res.options & RES_INSECURE2) &&
774 !res_queriesmatch(buf, buf + buflen,
775 ans, ans + anssiz)) {
776 /*
777 * response contains wrong query? ignore it.
778 * XXX - potential security hazard could
779 * be detected here.
780 */
781 DprintQ((_res.options & RES_DEBUG) ||
782 (_res.pfcode & RES_PRF_REPLY),
783 (stdout, ";; wrong query name:\n"),
784 ans, (resplen>anssiz)?anssiz:resplen);
785 goto wait;
786 }
787 if (anhp->rcode == SERVFAIL ||
788 anhp->rcode == NOTIMP ||
789 anhp->rcode == REFUSED) {
790 DprintQ(_res.options & RES_DEBUG,
791 (stdout, "server rejected query:\n"),
792 ans, (resplen>anssiz)?anssiz:resplen);
793 badns |= (1 << ns);
794 res_close();
795 /* don't retry if called from dig */
796 if (!_res.pfcode)
797 goto next_ns;
798 }
799 if (!(_res.options & RES_IGNTC) && anhp->tc) {
800 /*
801 * get rest of answer;
802 * use TCP with same server.
803 */
804 Dprint(_res.options & RES_DEBUG,
805 (stdout, ";; truncated answer\n"));
806 v_circuit = 1;
807 res_close();
808 goto same_ns;
809 }
810 } /*if vc/dg*/
811 Dprint((_res.options & RES_DEBUG) ||
812 ((_res.pfcode & RES_PRF_REPLY) &&
813 (_res.pfcode & RES_PRF_HEAD1)),
814 (stdout, ";; got answer:\n"));
815 DprintQ((_res.options & RES_DEBUG) ||
816 (_res.pfcode & RES_PRF_REPLY),
817 (stdout, "%s", ""),
818 ans, (resplen>anssiz)?anssiz:resplen);
819 /*
820 * If using virtual circuits, we assume that the first server
821 * is preferred over the rest (i.e. it is on the local
822 * machine) and only keep that one open.
823 * If we have temporarily opened a virtual circuit,
824 * or if we haven't been asked to keep a socket open,
825 * close the socket.
826 */
827 if ((v_circuit && (!(_res.options & RES_USEVC) || ns != 0)) ||
828 !(_res.options & RES_STAYOPEN)) {
829 res_close();
830 }
831 if (Rhook) {
832 int done = 0, loops = 0;
833
834 do {
835 res_sendhookact act;
836
837 act = (*Rhook)((struct sockaddr_in *)nsap,
838 buf, buflen,
839 ans, anssiz, &resplen);
840 switch (act) {
841 case res_goahead:
842 case res_done:
843 done = 1;
844 break;
845 case res_nextns:
846 res_close();
847 goto next_ns;
848 case res_modified:
849 /* give the hook another try */
850 if (++loops < 42) /*doug adams*/
851 break;
852 /*FALLTHROUGH*/
853 case res_error:
854 /*FALLTHROUGH*/
855 default:
856 return (-1);
857 }
858 } while (!done);
859
860 }
861 return (resplen);
862 next_ns: ;
863 } /*foreach ns*/
864 } /*foreach retry*/
865 res_close();
866 if (!v_circuit) {
867 if (!gotsomewhere)
868 errno = ECONNREFUSED; /* no nameservers found */
869 else
870 errno = ETIMEDOUT; /* no answer obtained */
871 } else
872 errno = terrno;
873 return (-1);
874}
875
876/*
877 * This routine is for closing the socket if a virtual circuit is used and
878 * the program wants to close it. This provides support for endhostent()
879 * which expects to close the socket.
880 *
881 * This routine is not expected to be user visible.
882 */
883void
884res_close()
885{
886 if (s >= 0) {
887 (void) close(s);
888 s = -1;
889 connected = 0;
890 vc = 0;
891 af = 0;
892 }
893}
diff --git a/src/lib/libc/net/resolver.3 b/src/lib/libc/net/resolver.3
new file mode 100644
index 0000000000..4d5402ed2d
--- /dev/null
+++ b/src/lib/libc/net/resolver.3
@@ -0,0 +1,345 @@
1.\" $OpenBSD: resolver.3,v 1.15 2001/04/03 20:09:08 aaron Exp $
2.\"
3.\" Copyright (c) 1985, 1991, 1993
4.\" The Regents of the University of California. All rights reserved.
5.\"
6.\" Redistribution and use in source and binary forms, with or without
7.\" modification, are permitted provided that the following conditions
8.\" are met:
9.\" 1. Redistributions of source code must retain the above copyright
10.\" notice, this list of conditions and the following disclaimer.
11.\" 2. Redistributions in binary form must reproduce the above copyright
12.\" notice, this list of conditions and the following disclaimer in the
13.\" documentation and/or other materials provided with the distribution.
14.\" 3. All advertising materials mentioning features or use of this software
15.\" must display the following acknowledgement:
16.\" This product includes software developed by the University of
17.\" California, Berkeley and its contributors.
18.\" 4. Neither the name of the University nor the names of its contributors
19.\" may be used to endorse or promote products derived from this software
20.\" without specific prior written permission.
21.\"
22.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32.\" SUCH DAMAGE.
33.\"
34.Dd June 4, 1993
35.Dt RESOLVER 3
36.Os
37.Sh NAME
38.Nm res_query ,
39.Nm res_search ,
40.Nm res_mkquery ,
41.Nm res_send ,
42.Nm res_init ,
43.Nm dn_comp ,
44.Nm dn_expand
45.Nd resolver routines
46.Sh SYNOPSIS
47.Fd #include <sys/types.h>
48.Fd #include <netinet/in.h>
49.Fd #include <arpa/nameser.h>
50.Fd #include <resolv.h>
51.Ft int
52.Fo res_query
53.Fa "char *dname"
54.Fa "int class"
55.Fa "int type"
56.Fa "u_char *answer"
57.Fa "int anslen"
58.Fc
59.Ft int
60.Fo res_search
61.Fa "char *dname"
62.Fa "int class"
63.Fa "int type"
64.Fa "u_char *answer"
65.Fa "int anslen"
66.Fc
67.Ft int
68.Fo res_mkquery
69.Fa "int op"
70.Fa "char *dname"
71.Fa "int class"
72.Fa "int type"
73.Fa "char *data"
74.Fa "int datalen"
75.Fa "struct rrec *newrr"
76.Fa "char *buf"
77.Fa "int buflen"
78.Fc
79.Ft int
80.Fo res_send
81.Fa "char *msg"
82.Fa "int msglen"
83.Fa "char *answer"
84.Fa "int anslen"
85.Fc
86.Ft int
87.Fn res_init "void"
88.Ft int
89.Fo dn_comp
90.Fa "char *exp_dn"
91.Fa "char *comp_dn"
92.Fa "int length"
93.Fa "char **dnptrs"
94.Fa "char **lastdnptr"
95.Fc
96.Ft int
97.Fo dn_expand
98.Fa "u_char *msg"
99.Fa "u_char *eomorig"
100.Fa "u_char *comp_dn"
101.Fa "u_char *exp_dn"
102.Fa "int length"
103.Fc
104.Sh DESCRIPTION
105These routines are used for making, sending, and interpreting
106query and reply messages with Internet domain name servers.
107.Pp
108Global configuration and state information that is used by the
109resolver routines is kept in the structure
110.Li _res .
111Most of the values have reasonable defaults and can be ignored.
112Options stored in
113.Li _res.options
114are defined in
115.Aq Pa resolv.h
116and are as follows.
117Options are stored as a simple bit mask containing the bitwise
118.Tn OR
119of the options enabled.
120.Bl -tag -width RES_USE_INET6
121.It Dv RES_INIT
122True if the initial name server address and default domain name are
123initialized (i.e.,
124.Fn res_init
125has been called).
126.It Dv RES_DEBUG
127Print debugging messages.
128.It Dv RES_AAONLY
129Accept authoritative answers only.
130With this option,
131.Fn res_send
132should continue until it finds an authoritative answer or finds an error.
133Currently this is not implemented.
134.It Dv RES_USEVC
135Use
136.Tn TCP
137connections for queries instead of
138.Tn UDP
139datagrams.
140.It Dv RES_STAYOPEN
141Used with
142.Dv RES_USEVC
143to keep the
144.Tn TCP
145connection open between queries.
146This is useful only in programs that regularly do many queries.
147.Tn UDP
148should be the normal mode used.
149.It Dv RES_IGNTC
150Unused currently (ignore truncation errors, i.e., don't retry with
151.Tn TCP ) .
152.It Dv RES_RECURSE
153Set the recursion-desired bit in queries.
154This is the default.
155.Pf ( Fn res_send
156does not do iterative queries and expects the name server
157to handle recursion.)
158.It Dv RES_DEFNAMES
159If set,
160.Fn res_search
161will append the default domain name to single-component names
162(those that do not contain a dot).
163This option is enabled by default.
164.It Dv RES_DNSRCH
165If this option is set,
166.Fn res_search
167will search for host names in the current domain and in parent domains; see
168.Xr hostname 7 .
169This is used by the standard host lookup routine
170.Xr gethostbyname 3 .
171This option is enabled by default.
172.It Dv RES_USE_INET6
173Enables support for IPv6-only applications.
174This causes IPv4 addresses to be returned as an IPv4 mapped address.
175For example, 10.1.1.1 will be returned as ::ffff:10.1.1.1.
176The option is not meaningful on
177.Ox .
178.El
179.Pp
180The
181.Fn res_init
182routine reads the configuration file (if any; see
183.Xr resolv.conf 5 )
184to get the default domain name, search list, and the Internet address
185of the local name server(s).
186If no server is configured, the host running
187the resolver is tried.
188The current domain name is defined by the hostname
189if not specified in the configuration file;
190it can be overridden by the environment variable
191.Ev LOCALDOMAIN .
192This environment variable may contain several blank-separated
193tokens if you wish to override the
194.Fa search list
195on a per-process basis.
196This is similar to the
197.Fa search
198command in the configuration file.
199Another environment variable
200.Ev RES_OPTIONS
201can be set to override certain internal resolver options which
202are otherwise set by changing fields in the
203.Fa _res
204structure or are inherited from the configuration file's
205.Fa options
206command.
207The syntax of the
208.Ev RES_OPTIONS
209environment variable is explained in
210.Xr resolv.conf 5 .
211Initialization normally occurs on the first call
212to one of the following routines.
213.Pp
214The
215.Fn res_query
216function provides an interface to the server query mechanism.
217It constructs a query, sends it to the local server,
218awaits a response, and makes preliminary checks on the reply.
219The query requests information of the specified
220.Fa type
221and
222.Fa class
223for the specified fully qualified domain name
224.Fa dname .
225The reply message is left in the
226.Fa answer
227buffer with length
228.Fa anslen
229supplied by the caller.
230.Pp
231The
232.Fn res_search
233routine makes a query and awaits a response like
234.Fn res_query ,
235but in addition, it implements the default and search rules controlled by the
236.Dv RES_DEFNAMES
237and
238.Dv RES_DNSRCH
239options.
240It returns the first successful reply.
241.Pp
242The remaining routines are lower-level routines used by
243.Fn res_query .
244The
245.Fn res_mkquery
246function constructs a standard query message and places it in
247.Fa buf .
248It returns the size of the query, or \-1 if the query is larger than
249.Fa buflen .
250The query type
251.Fa op
252is usually
253.Dv QUERY ,
254but can be any of the query types defined in
255.Aq Pa arpa/nameser.h .
256The domain name for the query is given by
257.Fa dname .
258.Fa newrr
259is currently unused but is intended for making update messages.
260.Pp
261The
262.Fn res_send
263routine sends a pre-formatted query and returns an answer.
264It will call
265.Fn res_init
266if
267.Dv RES_INIT
268is not set, send the query to the local name server, and
269handle timeouts and retries.
270The length of the reply message is returned, or \-1 if there were errors.
271.Pp
272The
273.Fn dn_comp
274function compresses the domain name
275.Fa exp_dn
276and stores it in
277.Fa comp_dn .
278The size of the compressed name is returned or \-1 if there were errors.
279The size of the array pointed to by
280.Fa comp_dn
281is given by
282.Fa length .
283The compression uses an array of pointers
284.Fa dnptrs
285to previously compressed names in the current message.
286The first pointer points
287to the beginning of the message and the list ends with
288.Dv NULL .
289The limit to the array is specified by
290.Fa lastdnptr .
291A side effect of
292.Fn dn_comp
293is to update the list of pointers for labels inserted into the message
294as the name is compressed.
295If
296.Em dnptr
297is
298.Dv NULL ,
299names are not compressed.
300If
301.Fa lastdnptr
302is
303.Dv NULL ,
304the list of labels is not updated.
305.Pp
306The
307.Fn dn_expand
308entry expands the compressed domain name
309.Fa comp_dn
310to a full domain name
311The compressed name is contained in a query or reply message;
312.Fa msg
313is a pointer to the beginning of the message.
314The uncompressed name is placed in the buffer indicated by
315.Fa exp_dn
316which is of size
317.Fa length .
318The size of compressed name is returned or \-1 if there was an error.
319.Sh FILES
320.Bl -tag -width Pa
321/etc/resolv.conf
322configuration file
323see
324.Xr resolv.conf 5 .
325.El
326.Sh SEE ALSO
327.Xr gethostbyname 3 ,
328.Xr resolv.conf 5 ,
329.Xr hostname 7 ,
330.Xr named 8
331.Pp
332.%T RFC1032 ,
333.%T RFC1033 ,
334.%T RFC1034 ,
335.%T RFC1035 ,
336.%T RFC1535 ,
337.%T RFC974
338.Rs
339.%T "Name Server Operations Guide for BIND"
340.Re
341.Sh HISTORY
342The
343.Nm
344function appeared in
345.Bx 4.3 .
diff --git a/src/lib/libc/net/rresvport.c b/src/lib/libc/net/rresvport.c
new file mode 100644
index 0000000000..c807adfb83
--- /dev/null
+++ b/src/lib/libc/net/rresvport.c
@@ -0,0 +1,118 @@
1/*
2 * Copyright (c) 1995, 1996, 1998 Theo de Raadt. All rights reserved.
3 * Copyright (c) 1983, 1993, 1994
4 * The Regents of the University of California. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed by the University of
17 * California, Berkeley and its contributors.
18 * This product includes software developed by Theo de Raadt.
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
36#if defined(LIBC_SCCS) && !defined(lint)
37static char *rcsid = "$OpenBSD: rresvport.c,v 1.5 2000/01/26 03:43:20 deraadt Exp $";
38#endif /* LIBC_SCCS and not lint */
39
40#include <sys/param.h>
41#include <sys/socket.h>
42#include <sys/stat.h>
43
44#include <netinet/in.h>
45#include <arpa/inet.h>
46
47#include <signal.h>
48#include <fcntl.h>
49#include <netdb.h>
50#include <unistd.h>
51#include <pwd.h>
52#include <errno.h>
53#include <stdio.h>
54#include <ctype.h>
55#include <string.h>
56#include <syslog.h>
57#include <stdlib.h>
58#include <netgroup.h>
59
60int
61rresvport(alport)
62 int *alport;
63{
64 return rresvport_af(alport, AF_INET);
65}
66
67
68int
69rresvport_af(alport, af)
70 int *alport;
71 int af;
72{
73 struct sockaddr_storage ss;
74 struct sockaddr *sa;
75 u_int16_t *portp;
76 int s;
77
78 bzero(&ss, sizeof ss);
79 sa = (struct sockaddr *)&ss;
80
81 switch (af) {
82 case AF_INET:
83 sa->sa_len = sizeof(struct sockaddr_in);
84 portp = &((struct sockaddr_in *)sa)->sin_port;
85 break;
86 case AF_INET6:
87 sa->sa_len = sizeof(struct sockaddr_in6);
88 portp = &((struct sockaddr_in6 *)sa)->sin6_port;
89 break;
90 default:
91 errno = EPFNOSUPPORT;
92 return (-1);
93 }
94 sa->sa_family = af;
95
96 s = socket(af, SOCK_STREAM, 0);
97 if (s < 0)
98 return (-1);
99
100 *portp = htons(*alport);
101 if (*alport < IPPORT_RESERVED - 1) {
102 if (bind(s, sa, sa->sa_len) >= 0)
103 return (s);
104 if (errno != EADDRINUSE) {
105 (void)close(s);
106 return (-1);
107 }
108 }
109
110 *portp = 0;
111 sa->sa_family = af;
112 if (bindresvport_sa(s, sa) == -1) {
113 (void)close(s);
114 return (-1);
115 }
116 *alport = ntohs(*portp);
117 return (s);
118}
diff --git a/src/lib/libc/net/rthdr.c b/src/lib/libc/net/rthdr.c
new file mode 100644
index 0000000000..7a87b322d1
--- /dev/null
+++ b/src/lib/libc/net/rthdr.c
@@ -0,0 +1,310 @@
1/* $OpenBSD: rthdr.c,v 1.3 2002/06/27 10:14:02 itojun Exp $ */
2
3/*
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32#include <sys/param.h>
33#include <sys/types.h>
34#include <sys/socket.h>
35
36#include <netinet/in.h>
37#include <netinet/ip6.h>
38
39#include <string.h>
40#include <stdio.h>
41
42size_t
43inet6_rthdr_space(type, seg)
44 int type, seg;
45{
46 switch(type) {
47 case IPV6_RTHDR_TYPE_0:
48 if (seg < 1 || seg > 23)
49 return(0);
50 return(CMSG_SPACE(sizeof(struct in6_addr) * (seg - 1)
51 + sizeof(struct ip6_rthdr0)));
52 default:
53#ifdef DEBUG
54 fprintf(stderr, "inet6_rthdr_space: unknown type(%d)\n", type);
55#endif
56 return(0);
57 }
58}
59
60struct cmsghdr *
61inet6_rthdr_init(bp, type)
62 void *bp;
63 int type;
64{
65 register struct cmsghdr *ch = (struct cmsghdr *)bp;
66 register struct ip6_rthdr *rthdr;
67
68 rthdr = (struct ip6_rthdr *)CMSG_DATA(ch);
69
70 ch->cmsg_level = IPPROTO_IPV6;
71 ch->cmsg_type = IPV6_RTHDR;
72
73 switch(type) {
74 case IPV6_RTHDR_TYPE_0:
75 ch->cmsg_len = CMSG_LEN(sizeof(struct ip6_rthdr0) - sizeof(struct in6_addr));
76 bzero(rthdr, sizeof(struct ip6_rthdr0));
77 rthdr->ip6r_type = IPV6_RTHDR_TYPE_0;
78 return(ch);
79 default:
80#ifdef DEBUG
81 fprintf(stderr, "inet6_rthdr_init: unknown type(%d)\n", type);
82#endif
83 return(NULL);
84 }
85}
86
87int
88inet6_rthdr_add(cmsg, addr, flags)
89 struct cmsghdr *cmsg;
90 const struct in6_addr *addr;
91 u_int flags;
92{
93 register struct ip6_rthdr *rthdr;
94
95 rthdr = (struct ip6_rthdr *)CMSG_DATA(cmsg);
96
97 switch(rthdr->ip6r_type) {
98 case IPV6_RTHDR_TYPE_0:
99 {
100 struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr;
101 if (flags != IPV6_RTHDR_LOOSE && flags != IPV6_RTHDR_STRICT) {
102#ifdef DEBUG
103 fprintf(stderr, "inet6_rthdr_add: unsupported flag(%u)\n", flags);
104#endif
105 return(-1);
106 }
107 if (rt0->ip6r0_segleft == 23) {
108#ifdef DEBUG
109 fprintf(stderr, "inet6_rthdr_add: segment overflow\n");
110#endif
111 return(-1);
112 }
113 if (flags == IPV6_RTHDR_STRICT) {
114 int c, b;
115 c = rt0->ip6r0_segleft / 8;
116 b = rt0->ip6r0_segleft % 8;
117 rt0->ip6r0_slmap[c] |= (1 << (7 - b));
118 }
119 rt0->ip6r0_segleft++;
120 bcopy(addr, (caddr_t)rt0 + ((rt0->ip6r0_len + 1) << 3),
121 sizeof(struct in6_addr));
122 rt0->ip6r0_len += sizeof(struct in6_addr) >> 3;
123 cmsg->cmsg_len = CMSG_LEN((rt0->ip6r0_len + 1) << 3);
124 break;
125 }
126 default:
127#ifdef DEBUG
128 fprintf(stderr, "inet6_rthdr_add: unknown type(%u)\n",
129 rthdr->ip6r_type);
130#endif
131 return(-1);
132 }
133
134 return(0);
135}
136
137int
138inet6_rthdr_lasthop(cmsg, flags)
139 struct cmsghdr *cmsg;
140 unsigned int flags;
141{
142 register struct ip6_rthdr *rthdr;
143
144 rthdr = (struct ip6_rthdr *)CMSG_DATA(cmsg);
145
146 switch(rthdr->ip6r_type) {
147 case IPV6_RTHDR_TYPE_0:
148 {
149 struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr;
150 if (flags != IPV6_RTHDR_LOOSE && flags != IPV6_RTHDR_STRICT) {
151#ifdef DEBUG
152 fprintf(stderr, "inet6_rthdr_lasthop: unsupported flag(%u)\n", flags);
153#endif
154 return(-1);
155 }
156 if (rt0->ip6r0_segleft > 23) {
157#ifdef DEBUG
158 fprintf(stderr, "inet6_rthdr_add: segment overflow\n");
159#endif
160 return(-1);
161 }
162 if (flags == IPV6_RTHDR_STRICT) {
163 int c, b;
164 c = rt0->ip6r0_segleft / 8;
165 b = rt0->ip6r0_segleft % 8;
166 rt0->ip6r0_slmap[c] |= (1 << (7 - b));
167 }
168 break;
169 }
170 default:
171#ifdef DEBUG
172 fprintf(stderr, "inet6_rthdr_lasthop: unknown type(%u)\n",
173 rthdr->ip6r_type);
174#endif
175 return(-1);
176 }
177
178 return(0);
179}
180
181#if 0
182int
183inet6_rthdr_reverse(in, out)
184 const struct cmsghdr *in;
185 struct cmsghdr *out;
186{
187#ifdef DEBUG
188 fprintf(stderr, "inet6_rthdr_reverse: not implemented yet\n");
189#endif
190 return -1;
191}
192#endif
193
194int
195inet6_rthdr_segments(cmsg)
196 const struct cmsghdr *cmsg;
197{
198 register struct ip6_rthdr *rthdr;
199
200 rthdr = (struct ip6_rthdr *)CMSG_DATA(cmsg);
201
202 switch(rthdr->ip6r_type) {
203 case IPV6_RTHDR_TYPE_0:
204 {
205 struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr;
206
207 if (rt0->ip6r0_len % 2 || 46 < rt0->ip6r0_len) {
208#ifdef DEBUG
209 fprintf(stderr, "inet6_rthdr_segments: invalid size(%u)\n",
210 rt0->ip6r0_len);
211#endif
212 return -1;
213 }
214
215 return (rt0->ip6r0_len * 8) / sizeof(struct in6_addr);
216 }
217
218 default:
219#ifdef DEBUG
220 fprintf(stderr, "inet6_rthdr_segments: unknown type(%u)\n",
221 rthdr->ip6r_type);
222#endif
223 return -1;
224 }
225}
226
227struct in6_addr *
228inet6_rthdr_getaddr(cmsg, index)
229 struct cmsghdr *cmsg;
230 int index;
231{
232 register struct ip6_rthdr *rthdr;
233
234 rthdr = (struct ip6_rthdr *)CMSG_DATA(cmsg);
235
236 switch(rthdr->ip6r_type) {
237 case IPV6_RTHDR_TYPE_0:
238 {
239 struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr;
240 int naddr;
241
242 if (rt0->ip6r0_len % 2 || 46 < rt0->ip6r0_len) {
243#ifdef DEBUG
244 fprintf(stderr, "inet6_rthdr_getaddr: invalid size(%u)\n",
245 rt0->ip6r0_len);
246#endif
247 return NULL;
248 }
249 naddr = (rt0->ip6r0_len * 8) / sizeof(struct in6_addr);
250 if (index <= 0 || naddr < index) {
251#ifdef DEBUG
252 fprintf(stderr, "inet6_rthdr_getaddr: invalid index(%d)\n", index);
253#endif
254 return NULL;
255 }
256 return &rt0->ip6r0_addr[index - 1];
257 }
258
259 default:
260#ifdef DEBUG
261 fprintf(stderr, "inet6_rthdr_getaddr: unknown type(%u)\n",
262 rthdr->ip6r_type);
263#endif
264 return NULL;
265 }
266}
267
268int
269inet6_rthdr_getflags(cmsg, index)
270 const struct cmsghdr *cmsg;
271 int index;
272{
273 register struct ip6_rthdr *rthdr;
274
275 rthdr = (struct ip6_rthdr *)CMSG_DATA(cmsg);
276
277 switch(rthdr->ip6r_type) {
278 case IPV6_RTHDR_TYPE_0:
279 {
280 struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr;
281 int naddr;
282
283 if (rt0->ip6r0_len % 2 || 46 < rt0->ip6r0_len) {
284#ifdef DEBUG
285 fprintf(stderr, "inet6_rthdr_getflags: invalid size(%u)\n",
286 rt0->ip6r0_len);
287#endif
288 return -1;
289 }
290 naddr = (rt0->ip6r0_len * 8) / sizeof(struct in6_addr);
291 if (index < 0 || naddr < index) {
292#ifdef DEBUG
293 fprintf(stderr, "inet6_rthdr_getflags: invalid index(%d)\n", index);
294#endif
295 return -1;
296 }
297 if (rt0->ip6r0_slmap[index / 8] & (0x80 >> (index % 8)))
298 return IPV6_RTHDR_STRICT;
299 else
300 return IPV6_RTHDR_LOOSE;
301 }
302
303 default:
304#ifdef DEBUG
305 fprintf(stderr, "inet6_rthdr_getflags: unknown type(%u)\n",
306 rthdr->ip6r_type);
307#endif
308 return -1;
309 }
310}
diff --git a/src/lib/libc/net/send.c b/src/lib/libc/net/send.c
new file mode 100644
index 0000000000..8495931ca3
--- /dev/null
+++ b/src/lib/libc/net/send.c
@@ -0,0 +1,50 @@
1/*
2 * Copyright (c) 1988, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#if defined(LIBC_SCCS) && !defined(lint)
35static char rcsid[] = "$OpenBSD: send.c,v 1.2 1996/08/19 08:29:52 tholo Exp $";
36#endif /* LIBC_SCCS and not lint */
37
38#include <sys/types.h>
39#include <sys/socket.h>
40
41#include <stddef.h>
42
43ssize_t
44send(s, msg, len, flags)
45 int s, flags;
46 size_t len;
47 const void *msg;
48{
49 return (sendto(s, msg, len, flags, NULL, 0));
50}
diff --git a/src/lib/libc/net/sethostent.c b/src/lib/libc/net/sethostent.c
new file mode 100644
index 0000000000..5392a2f11b
--- /dev/null
+++ b/src/lib/libc/net/sethostent.c
@@ -0,0 +1,60 @@
1/*
2 * Copyright (c) 1985, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#if defined(LIBC_SCCS) && !defined(lint)
35static char rcsid[] = "$OpenBSD: sethostent.c,v 1.4 1997/03/15 21:53:50 pefo Exp $";
36#endif /* LIBC_SCCS and not lint */
37
38#include <sys/param.h>
39#include <netinet/in.h>
40#include <arpa/nameser.h>
41#include <netdb.h>
42#include <resolv.h>
43
44void
45sethostent(stayopen)
46 int stayopen;
47{
48
49 if ((_res.options & RES_INIT) == 0 && res_init() == -1)
50 return;
51 if (stayopen)
52 _res.options |= RES_STAYOPEN | RES_USEVC;
53}
54
55void
56endhostent()
57{
58 _res.options &= ~(RES_STAYOPEN | RES_USEVC);
59 res_close();
60}
diff --git a/src/lib/libc/net/vars6.c b/src/lib/libc/net/vars6.c
new file mode 100644
index 0000000000..6d0f069ef6
--- /dev/null
+++ b/src/lib/libc/net/vars6.c
@@ -0,0 +1,42 @@
1/* $OpenBSD: vars6.c,v 1.1 1999/12/11 08:09:11 itojun Exp $ */
2
3/*
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32#include <sys/types.h>
33#include <netinet/in.h>
34
35/*
36 * Definitions of some costant IPv6 addresses.
37 */
38const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
39const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
40const struct in6_addr in6addr_nodelocal_allnodes = IN6ADDR_NODELOCAL_ALLNODES_INIT;
41const struct in6_addr in6addr_linklocal_allnodes = IN6ADDR_LINKLOCAL_ALLNODES_INIT;
42