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.3206
-rw-r--r--src/lib/libc/net/ethers.3119
-rw-r--r--src/lib/libc/net/ethers.c261
-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.3577
-rw-r--r--src/lib/libc/net/getaddrinfo.c1885
-rw-r--r--src/lib/libc/net/gethostbyname.3297
-rw-r--r--src/lib/libc/net/gethostnamadr.c1148
-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.3348
-rw-r--r--src/lib/libc/net/getnameinfo.c372
-rw-r--r--src/lib/libc/net/getnetbyaddr.c52
-rw-r--r--src/lib/libc/net/getnetbyname.c58
-rw-r--r--src/lib/libc/net/getnetent.3140
-rw-r--r--src/lib/libc/net/getnetent.c125
-rw-r--r--src/lib/libc/net/getnetnamadr.c400
-rw-r--r--src/lib/libc/net/getproto.c51
-rw-r--r--src/lib/libc/net/getprotoent.3130
-rw-r--r--src/lib/libc/net/getprotoent.c123
-rw-r--r--src/lib/libc/net/getprotoname.c58
-rw-r--r--src/lib/libc/net/getrrsetbyname.3165
-rw-r--r--src/lib/libc/net/getrrsetbyname.c512
-rw-r--r--src/lib/libc/net/getservbyname.c83
-rw-r--r--src/lib/libc/net/getservbyport.c56
-rw-r--r--src/lib/libc/net/getservent.3137
-rw-r--r--src/lib/libc/net/getservent.c125
-rw-r--r--src/lib/libc/net/herror.c117
-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.3136
-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.3355
-rw-r--r--src/lib/libc/net/inet6_option_space.3444
-rw-r--r--src/lib/libc/net/inet6_rthdr_space.3317
-rw-r--r--src/lib/libc/net/inet_addr.c183
-rw-r--r--src/lib/libc/net/inet_lnaof.c55
-rw-r--r--src/lib/libc/net/inet_makeaddr.c58
-rw-r--r--src/lib/libc/net/inet_net.3181
-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.c54
-rw-r--r--src/lib/libc/net/inet_network.c88
-rw-r--r--src/lib/libc/net/inet_ntoa.c55
-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.3123
-rw-r--r--src/lib/libc/net/ipx_addr.c224
-rw-r--r--src/lib/libc/net/ipx_ntoa.c49
-rw-r--r--src/lib/libc/net/iso_addr.3107
-rw-r--r--src/lib/libc/net/iso_addr.c115
-rw-r--r--src/lib/libc/net/link_addr.3127
-rw-r--r--src/lib/libc/net/linkaddr.c154
-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.3127
-rw-r--r--src/lib/libc/net/ns_addr.c223
-rw-r--r--src/lib/libc/net/ns_ntoa.c106
-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.3266
-rw-r--r--src/lib/libc/net/rcmd.c728
-rw-r--r--src/lib/libc/net/rcmdsh.396
-rw-r--r--src/lib/libc/net/rcmdsh.c192
-rw-r--r--src/lib/libc/net/recv.c46
-rw-r--r--src/lib/libc/net/res_comp.c499
-rw-r--r--src/lib/libc/net/res_data.c113
-rw-r--r--src/lib/libc/net/res_debug.c1561
-rw-r--r--src/lib/libc/net/res_init.c650
-rw-r--r--src/lib/libc/net/res_mkquery.c242
-rw-r--r--src/lib/libc/net/res_query.c407
-rw-r--r--src/lib/libc/net/res_random.c229
-rw-r--r--src/lib/libc/net/res_send.c898
-rw-r--r--src/lib/libc/net/resolver.3341
-rw-r--r--src/lib/libc/net/rresvport.c113
-rw-r--r--src/lib/libc/net/rthdr.c228
-rw-r--r--src/lib/libc/net/send.c46
-rw-r--r--src/lib/libc/net/sethostent.c61
-rw-r--r--src/lib/libc/net/vars6.c42
87 files changed, 20494 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..54123455c6
--- /dev/null
+++ b/src/lib/libc/net/byteorder.3
@@ -0,0 +1,206 @@
1.\" $OpenBSD: byteorder.3,v 1.13 2003/09/26 17:06:50 fgsch 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. Neither the name of the University nor the names of its contributors
15.\" may be used to endorse or promote products derived from this software
16.\" without specific prior written permission.
17.\"
18.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28.\" SUCH DAMAGE.
29.\"
30.Dd June 4, 1993
31.Dt BYTEORDER 3
32.Os
33.Sh NAME
34.Nm htonl ,
35.Nm htons ,
36.Nm ntohl ,
37.Nm ntohs ,
38.Nm htobe64 ,
39.Nm htobe32 ,
40.Nm htobe16 ,
41.Nm betoh64 ,
42.Nm betoh32 ,
43.Nm betoh16 ,
44.Nm htole64 ,
45.Nm htole32 ,
46.Nm htole16 ,
47.Nm letoh64 ,
48.Nm letoh32 ,
49.Nm letoh16 ,
50.Nm swap64 ,
51.Nm swap32 ,
52.Nm swap16
53.Nd convert values between different byte orderings
54.Sh SYNOPSIS
55.Fd #include <sys/types.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_int64_t
65.Fn htobe64 "u_int64_t host64"
66.Ft u_int32_t
67.Fn htobe32 "u_int32_t host32"
68.Ft u_int16_t
69.Fn htobe16 "u_int16_t host16"
70.Ft u_int64_t
71.Fn betoh64 "u_int64_t big64"
72.Ft u_int32_t
73.Fn betoh32 "u_int32_t big32"
74.Ft u_int16_t
75.Fn betoh16 "u_int16_t big16"
76.Ft u_int64_t
77.Fn htole64 "u_int64_t host64"
78.Ft u_int32_t
79.Fn htole32 "u_int32_t host32"
80.Ft u_int16_t
81.Fn htole16 "u_int16_t host16"
82.Ft u_int64_t
83.Fn letoh64 "u_int64_t little64"
84.Ft u_int32_t
85.Fn letoh32 "u_int32_t little32"
86.Ft u_int16_t
87.Fn letoh16 "u_int16_t little16"
88.Ft u_int64_t
89.Fn swap64 "u_int32_t val64"
90.Ft u_int32_t
91.Fn swap32 "u_int32_t val32"
92.Ft u_int16_t
93.Fn swap16 "u_int16_t val16"
94.Sh DESCRIPTION
95These routines convert 16, 32 and 64-bit quantities between different
96byte orderings.
97The
98.Dq swap
99functions reverse the byte ordering of
100the given quantity, the others converts either from/to the native
101byte order used by the host to/from either little- or big-endian (a.k.a
102network) order.
103.Pp
104Apart from the swap functions, the names can be described by this form:
105{src-order}to{dst-order}{size}.
106Both {src-order} and {dst-order} can take the following forms:
107.Pp
108.Bl -tag -width "be " -offset indent -compact
109.It h
110Host order.
111.It n
112Network order (big-endian).
113.It be
114Big-endian (most significant byte first).
115.It le
116Little-endian (least significant byte first).
117.El
118.Pp
119One of the specified orderings must be
120.Sq h .
121{size} will take these forms:
122.Pp
123.Bl -tag -width "32 " -offset indent -compact
124.It l
125Long (32-bit, used in conjunction with forms involving
126.Sq n ) .
127.It s
128Short (16-bit, used in conjunction with forms involving
129.Sq n ) .
130.It 16
13116-bit.
132.It 32
13332-bit.
134.It 64
13564-bit.
136.El
137.Pp
138The swap functions are of the form: swap{size}.
139.Pp
140Names involving
141.Sq n
142convert quantities between network
143byte order and host byte order.
144The last letter
145.Pf ( Sq s
146or
147.Sq l )
148is a mnemonic
149for the traditional names for such quantities,
150.Li short
151and
152.Li long ,
153respectively.
154Today, the C concept of
155.Li short
156and
157.Li long
158integers need not coincide with this traditional misunderstanding.
159On machines which have a byte order which is the same as the network
160order, routines are defined as null macros.
161.Pp
162The functions involving either
163.Dq be ,
164.Dq le ,
165or
166.Dq swap
167use the numbers
16816, 32 and 64 for specifying the bitwidth of the quantities they operate on.
169Currently all supported architectures are either big- or little-endian
170so either the
171.Dq be
172or
173.Dq le
174variants are implemented as null macros.
175.Pp
176The routines mentioned above which have either {src-order} or {dst-order}
177set to
178.Sq n
179are most often used in
180conjunction with Internet addresses and ports as returned by
181.Xr gethostbyname 3
182and
183.Xr getservent 3 .
184.Sh SEE ALSO
185.Xr gethostbyname 3 ,
186.Xr getservent 3
187.Sh STANDARDS
188The
189.Fn htonl ,
190.Fn htons ,
191.Fn ntohl ,
192and
193.Fn ntohs
194functions conform to
195.St -p1003.1 .
196The other functions are extensions that should not be used when portability
197is required.
198.Sh HISTORY
199The
200.Nm byteorder
201functions appeared in
202.Bx 4.2 .
203.Sh BUGS
204On the vax, alpha, i386, and some mips architectures,
205bytes are handled backwards from most everyone else in the world.
206This 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..899022a622
--- /dev/null
+++ b/src/lib/libc/net/ethers.c
@@ -0,0 +1,261 @@
1/* $OpenBSD: ethers.c,v 1.16 2003/06/17 21:56:24 millert Exp $ */
2
3/*
4 * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
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 THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19/*
20 * ethers(3) a la Sun.
21 * Originally Written by Roland McGrath <roland@frob.com> 10/14/93.
22 * Substantially modified by Todd C. Miller <Todd.Miller@courtesan.com>
23 */
24
25#if defined(LIBC_SCCS) && !defined(lint)
26static char rcsid[] = "$OpenBSD: ethers.c,v 1.16 2003/06/17 21:56:24 millert Exp $";
27#endif /* LIBC_SCCS and not lint */
28
29#include <sys/types.h>
30#include <sys/socket.h>
31#include <net/if.h>
32#include <netinet/in.h>
33#include <netinet/if_ether.h>
34#include <sys/param.h>
35#include <paths.h>
36#include <errno.h>
37#include <stdio.h>
38#include <stdlib.h>
39#include <string.h>
40#include <ctype.h>
41#ifdef YP
42#include <rpcsvc/ypclnt.h>
43#endif
44
45#ifndef _PATH_ETHERS
46#define _PATH_ETHERS "/etc/ethers"
47#endif
48
49static char * _ether_aton(char *, struct ether_addr *);
50
51char *
52ether_ntoa(e)
53 struct ether_addr *e;
54{
55 static char a[] = "xx:xx:xx:xx:xx:xx";
56
57 if (e->ether_addr_octet[0] > 0xFF || e->ether_addr_octet[1] > 0xFF ||
58 e->ether_addr_octet[2] > 0xFF || e->ether_addr_octet[3] > 0xFF ||
59 e->ether_addr_octet[4] > 0xFF || e->ether_addr_octet[5] > 0xFF) {
60 errno = EINVAL;
61 return (NULL);
62 }
63
64 (void)snprintf(a, sizeof a, "%02x:%02x:%02x:%02x:%02x:%02x",
65 e->ether_addr_octet[0], e->ether_addr_octet[1],
66 e->ether_addr_octet[2], e->ether_addr_octet[3],
67 e->ether_addr_octet[4], e->ether_addr_octet[5]);
68
69 return (a);
70}
71
72static char *
73_ether_aton(s, e)
74 char *s;
75 struct ether_addr *e;
76{
77 int i;
78 long l;
79 char *pp;
80
81 while (isspace(*s))
82 s++;
83
84 /* expect 6 hex octets separated by ':' or space/NUL if last octet */
85 for (i = 0; i < 6; i++) {
86 l = strtol(s, &pp, 16);
87 if (pp == s || l > 0xFF || l < 0)
88 return (NULL);
89 if (!(*pp == ':' || (i == 5 && (isspace(*pp) || *pp == '\0'))))
90 return (NULL);
91 e->ether_addr_octet[i] = (u_char)l;
92 s = pp + 1;
93 }
94
95 /* return character after the octets ala strtol(3) */
96 return (pp);
97}
98
99struct ether_addr *
100ether_aton(s)
101 char *s;
102{
103 static struct ether_addr n;
104
105 return (_ether_aton(s, &n) ? &n : NULL);
106}
107
108int
109ether_ntohost(hostname, e)
110 char *hostname;
111 struct ether_addr *e;
112{
113 FILE *f;
114 char buf[BUFSIZ+1], *p;
115 size_t len;
116 struct ether_addr try;
117#ifdef YP
118 char trybuf[sizeof("xx:xx:xx:xx:xx:xx")];
119 int trylen;
120#endif
121
122 if (e->ether_addr_octet[0] > 0xFF || e->ether_addr_octet[1] > 0xFF ||
123 e->ether_addr_octet[2] > 0xFF || e->ether_addr_octet[3] > 0xFF ||
124 e->ether_addr_octet[4] > 0xFF || e->ether_addr_octet[5] > 0xFF) {
125 errno = EINVAL;
126 return (-1);
127 }
128
129#ifdef YP
130 snprintf(trybuf, sizeof trybuf, "%x:%x:%x:%x:%x:%x",
131 e->ether_addr_octet[0], e->ether_addr_octet[1],
132 e->ether_addr_octet[2], e->ether_addr_octet[3],
133 e->ether_addr_octet[4], e->ether_addr_octet[5]);
134 trylen = strlen(trybuf);
135#endif
136
137 f = fopen(_PATH_ETHERS, "r");
138 if (f == NULL)
139 return (-1);
140 while ((p = fgetln(f, &len)) != NULL) {
141 if (p[len-1] == '\n')
142 len--;
143 if (len > sizeof(buf) - 2)
144 continue;
145 (void)memcpy(buf, p, len);
146 buf[len] = '\n'; /* code assumes newlines later on */
147 buf[len+1] = '\0';
148#ifdef YP
149 /* A + in the file means try YP now. */
150 if (!strncmp(buf, "+\n", sizeof(buf))) {
151 char *ypbuf, *ypdom;
152 int ypbuflen;
153
154 if (yp_get_default_domain(&ypdom))
155 continue;
156 if (yp_match(ypdom, "ethers.byaddr", trybuf,
157 trylen, &ypbuf, &ypbuflen))
158 continue;
159 if (ether_line(ypbuf, &try, hostname) == 0) {
160 free(ypbuf);
161 (void)fclose(f);
162 return (0);
163 }
164 free(ypbuf);
165 continue;
166 }
167#endif
168 if (ether_line(buf, &try, hostname) == 0 &&
169 memcmp((void *)&try, (void *)e, sizeof(try)) == 0) {
170 (void)fclose(f);
171 return (0);
172 }
173 }
174 (void)fclose(f);
175 errno = ENOENT;
176 return (-1);
177}
178
179int
180ether_hostton(hostname, e)
181 char *hostname;
182 struct ether_addr *e;
183{
184 FILE *f;
185 char buf[BUFSIZ+1], *p;
186 char try[MAXHOSTNAMELEN];
187 size_t len;
188#ifdef YP
189 int hostlen = strlen(hostname);
190#endif
191
192 f = fopen(_PATH_ETHERS, "r");
193 if (f==NULL)
194 return (-1);
195
196 while ((p = fgetln(f, &len)) != NULL) {
197 if (p[len-1] == '\n')
198 len--;
199 if (len > sizeof(buf) - 2)
200 continue;
201 memcpy(buf, p, len);
202 buf[len] = '\n'; /* code assumes newlines later on */
203 buf[len+1] = '\0';
204#ifdef YP
205 /* A + in the file means try YP now. */
206 if (!strncmp(buf, "+\n", sizeof(buf))) {
207 char *ypbuf, *ypdom;
208 int ypbuflen;
209
210 if (yp_get_default_domain(&ypdom))
211 continue;
212 if (yp_match(ypdom, "ethers.byname", hostname, hostlen,
213 &ypbuf, &ypbuflen))
214 continue;
215 if (ether_line(ypbuf, e, try) == 0) {
216 free(ypbuf);
217 (void)fclose(f);
218 return (0);
219 }
220 free(ypbuf);
221 continue;
222 }
223#endif
224 if (ether_line(buf, e, try) == 0 && strcmp(hostname, try) == 0) {
225 (void)fclose(f);
226 return (0);
227 }
228 }
229 (void)fclose(f);
230 errno = ENOENT;
231 return (-1);
232}
233
234int
235ether_line(line, e, hostname)
236 char *line;
237 struct ether_addr *e;
238 char *hostname;
239{
240 char *p;
241 size_t n;
242
243 /* Parse "xx:xx:xx:xx:xx:xx" */
244 if ((p = _ether_aton(line, e)) == NULL || (*p != ' ' && *p != '\t'))
245 goto bad;
246
247 /* Now get the hostname */
248 while (isspace(*p))
249 p++;
250 if (*p == '\0')
251 goto bad;
252 n = strcspn(p, " \t\n");
253 if (n >= MAXHOSTNAMELEN)
254 goto bad;
255 strlcpy(hostname, p, n + 1);
256 return (0);
257
258bad:
259 errno = EINVAL;
260 return (-1);
261}
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..a9004e3207
--- /dev/null
+++ b/src/lib/libc/net/getaddrinfo.3
@@ -0,0 +1,577 @@
1.\" $OpenBSD: getaddrinfo.3,v 1.25 2003/08/08 09:26:02 jmc 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. Neither the name of the University 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 REGENTS 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 REGENTS 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.\" From: @(#)gethostbyname.3 8.4 (Berkeley) 5/25/95
32.\"
33.Dd May 25, 1995
34.Dt GETADDRINFO 3
35.Os
36.\"
37.Sh NAME
38.Nm getaddrinfo ,
39.Nm freeaddrinfo ,
40.Nm gai_strerror
41.Nd nodename-to-address translation in protocol-independent manner
42.\"
43.Sh SYNOPSIS
44.Fd #include <sys/types.h>
45.Fd #include <sys/socket.h>
46.Fd #include <netdb.h>
47.Ft int
48.Fn getaddrinfo "const char *nodename" "const char *servname" \
49"const struct addrinfo *hints" "struct addrinfo **res"
50.Ft void
51.Fn freeaddrinfo "struct addrinfo *ai"
52.Ft "char *"
53.Fn gai_strerror "int ecode"
54.\"
55.Sh DESCRIPTION
56The
57.Fn getaddrinfo
58function is defined for protocol-independent nodename-to-address translation.
59It performs the functionality of
60.Xr gethostbyname 3
61and
62.Xr getservbyname 3 ,
63but in a more sophisticated manner.
64.Pp
65The
66.Li addrinfo
67structure is defined as a result of including the
68.Aq Pa netdb.h
69header:
70.Bd -literal
71struct addrinfo {
72 int ai_flags; /* input flags */
73 int ai_family; /* protocol family for socket */
74 int ai_socktype; /* socket type */
75 int ai_protocol; /* protocol for socket */
76 socklen_t ai_addrlen; /* length of socket-address */
77 struct sockaddr *ai_addr; /* socket-address for socket */
78 char *ai_canonname; /* canonical name for service location */
79 struct addrinfo *ai_next; /* pointer to next in list */
80};
81.Ed
82.Pp
83The
84.Fa nodename
85and
86.Fa servname
87arguments are pointers to NUL-terminated strings or
88.Dv NULL .
89One or both of these two arguments must be a non-null pointer.
90In the normal client scenario, both the
91.Fa nodename
92and
93.Fa servname
94are specified.
95In the normal server scenario, only the
96.Fa servname
97is specified.
98A non-null
99.Fa nodename
100string can be either a node name or a numeric host address string
101(i.e., a dotted-decimal IPv4 address or an IPv6 hex address).
102A non-null
103.Fa servname
104string can be either a service name or a decimal port number.
105.Pp
106The caller can optionally pass an
107.Li addrinfo
108structure, pointed to by the third argument,
109to provide hints concerning the type of socket that the caller supports.
110In this
111.Fa hints
112structure all members other than
113.Fa ai_flags ,
114.Fa ai_family ,
115.Fa ai_socktype ,
116and
117.Fa ai_protocol
118must be zero or a null pointer.
119A value of
120.Dv PF_UNSPEC
121for
122.Fa ai_family
123means the caller will accept any protocol family.
124A value of 0 for
125.Fa ai_socktype
126means the caller will accept any socket type.
127A value of 0 for
128.Fa ai_protocol
129means the caller will accept any protocol.
130For example, if the caller handles only TCP and not UDP, then the
131.Fa ai_socktype
132member of the hints structure should be set to
133.Dv SOCK_STREAM
134when
135.Fn getaddrinfo
136is called.
137If the caller handles only IPv4 and not IPv6, then the
138.Fa ai_family
139member of the
140.Fa hints
141structure should be set to
142.Dv PF_INET
143when
144.Fn getaddrinfo
145is called.
146If the third argument to
147.Fn getaddrinfo
148is a null pointer, this is the same as if the caller had filled in an
149.Li addrinfo
150structure initialized to zero with
151.Fa ai_family
152set to
153.Dv PF_UNSPEC .
154.Pp
155Upon successful return a pointer to a linked list of one or more
156.Li addrinfo
157structures is returned through the final argument.
158The caller can process each
159.Li addrinfo
160structure in this list by following the
161.Fa ai_next
162pointer, until a null pointer is encountered.
163In each returned
164.Li addrinfo
165structure the three members
166.Fa ai_family ,
167.Fa ai_socktype ,
168and
169.Fa ai_protocol
170are the corresponding arguments for a call to the
171.Fn socket
172function.
173In each
174.Li addrinfo
175structure the
176.Fa ai_addr
177member points to a filled-in socket address structure whose length is
178specified by the
179.Fa ai_addrlen
180member.
181.Pp
182If the
183.Dv AI_PASSIVE
184bit is set in the
185.Fa ai_flags
186member of the
187.Fa hints
188structure, then the caller plans to use the returned socket address
189structure in a call to
190.Fn bind .
191In this case, if the
192.Fa nodename
193argument is a null pointer, then the IP address portion of the socket
194address structure will be set to
195.Dv INADDR_ANY
196for an IPv4 address or
197.Dv IN6ADDR_ANY_INIT
198for an IPv6 address.
199.Pp
200If the
201.Dv AI_PASSIVE
202bit is not set in the
203.Fa ai_flags
204member of the
205.Fa hints
206structure, then the returned socket address structure will be ready for a
207call to
208.Fn connect
209.Pq for a connection-oriented protocol
210or either
211.Fn connect ,
212.Fn sendto ,
213or
214.Fn sendmsg
215.Pq for a connectionless protocol .
216In this case, if the
217.Fa nodename
218argument is a null pointer, then the IP address portion of the
219socket address structure will be set to the loopback address.
220.Pp
221If the
222.Dv AI_CANONNAME
223bit is set in the
224.Fa ai_flags
225member of the
226.Fa hints
227structure, then upon successful return the
228.Fa ai_canonname
229member of the first
230.Li addrinfo
231structure in the linked list will point to a NUL-terminated string
232containing the canonical name of the specified
233.Fa nodename .
234.Pp
235If the
236.Dv AI_NUMERICHOST
237bit is set in the
238.Fa ai_flags
239member of the
240.Fa hints
241structure, then a non-null
242.Fa nodename
243string must be a numeric host address string.
244Otherwise an error of
245.Dv EAI_NONAME
246is returned.
247This flag prevents any type of name resolution service (e.g., the DNS)
248from being called.
249.Pp
250The arguments to
251.Fn getaddrinfo
252must sufficiently be consistent and unambiguous.
253Here are pitfall cases you may encounter:
254.Bl -bullet
255.It
256.Fn getaddrinfo
257will raise an error if members of the
258.Fa hints
259structure are not consistent.
260For example, for internet address families,
261.Fn getaddrinfo
262will raise an error if you specify
263.Dv SOCK_STREAM
264to
265.Fa ai_socktype
266while you specify
267.Dv IPPROTO_UDP
268to
269.Fa ai_protocol .
270.It
271If you specify a
272.Fa servname
273which is defined only for certain
274.Fa ai_socktype ,
275.Fn getaddrinfo
276will raise an error because the arguments are not consistent.
277For example,
278.Fn getaddrinfo
279will raise an error if you ask for
280.Dq Li tftp
281service on
282.Dv SOCK_STREAM .
283.It
284For internet address families, if you specify
285.Fa servname
286while you set
287.Fa ai_socktype
288to
289.Dv SOCK_RAW ,
290.Fn getaddrinfo
291will raise an error, because service names are not defined for the internet
292.Dv SOCK_RAW
293space.
294.It
295If you specify a numeric
296.Fa servname ,
297while leaving
298.Fa ai_socktype
299and
300.Fa ai_protocol
301unspecified,
302.Fn getaddrinfo
303will raise an error.
304This is because the numeric
305.Fa servname
306does not identify any socket type, and
307.Fn getaddrinfo
308is not allowed to glob the argument in such case.
309.El
310.Pp
311All of the information returned by
312.Fn getaddrinfo
313is dynamically allocated:
314the
315.Li addrinfo
316structures, the socket address structures, and canonical node name
317strings pointed to by the addrinfo structures.
318To return this information to the system the function
319.Fn freeaddrinfo
320is called.
321The
322.Fa addrinfo
323structure pointed to by the
324.Fa ai argument
325is freed, along with any dynamic storage pointed to by the structure.
326This operation is repeated until a
327.Dv NULL
328.Fa ai_next
329pointer is encountered.
330.Pp
331To aid applications in printing error messages based on the
332.Dv EAI_xxx
333codes returned by
334.Fn getaddrinfo ,
335.Fn gai_strerror
336is defined.
337The argument is one of the
338.Dv EAI_xxx
339values defined earlier and the return value points to a string describing
340the error.
341If the argument is not one of the
342.Dv EAI_xxx
343values, the function still returns a pointer to a string whose contents
344indicate an unknown error.
345.\"
346.Ss Extension for scoped IPv6 address
347The implementation allows experimental numeric IPv6 address notation with
348scope identifier.
349By appending the percent character and scope identifier to addresses,
350you can fill the
351.Li sin6_scope_id
352field for addresses.
353This would make management of scoped address easier,
354and allows cut-and-paste input of scoped address.
355.Pp
356At this moment the code supports only link-local addresses with the format.
357Scope identifier is hardcoded to the name of the hardware interface associated
358with the link.
359.Po
360such as
361.Li ne0
362.Pc .
363An example is
364.Dq Li fe80::1%ne0 ,
365which means
366.Do
367.Li fe80::1
368on the link associated with the
369.Li ne0
370interface
371.Dc .
372.Pp
373The implementation is still very experimental and non-standard.
374The current implementation assumes a one-to-one relationship between
375the interface and link, which is not necessarily true from the specification.
376.\"
377.Sh EXAMPLES
378The following code tries to connect to
379.Dq Li www.kame.net
380service
381.Dq Li http .
382via stream socket.
383It loops through all the addresses available, regardless of address family.
384If the destination resolves to an IPv4 address, it will use
385.Dv AF_INET
386socket.
387Similarly, if it resolves to IPv6,
388.Dv AF_INET6
389socket is used.
390Observe that there is no hardcoded reference to a particular address family.
391The code works even if
392.Nm getaddrinfo
393returns addresses that are not IPv4/v6.
394.Bd -literal -offset indent
395struct addrinfo hints, *res, *res0;
396int error;
397int s;
398const char *cause = NULL;
399
400memset(&hints, 0, sizeof(hints));
401hints.ai_family = PF_UNSPEC;
402hints.ai_socktype = SOCK_STREAM;
403error = getaddrinfo("www.kame.net", "http", &hints, &res0);
404if (error) {
405 errx(1, "%s", gai_strerror(error));
406 /*NOTREACHED*/
407}
408s = -1;
409for (res = res0; res; res = res->ai_next) {
410 s = socket(res->ai_family, res->ai_socktype,
411 res->ai_protocol);
412 if (s < 0) {
413 cause = "socket";
414 continue;
415 }
416
417 if (connect(s, res->ai_addr, res->ai_addrlen) < 0) {
418 cause = "connect";
419 close(s);
420 s = -1;
421 continue;
422 }
423
424 break; /* okay we got one */
425}
426if (s < 0) {
427 err(1, cause);
428 /*NOTREACHED*/
429}
430freeaddrinfo(res0);
431.Ed
432.Pp
433The following example tries to open a wildcard listening socket onto service
434.Dq Li http ,
435for all the address families available.
436.Bd -literal -offset indent
437struct addrinfo hints, *res, *res0;
438int error;
439int s[MAXSOCK];
440int nsock;
441const char *cause = NULL;
442
443memset(&hints, 0, sizeof(hints));
444hints.ai_family = PF_UNSPEC;
445hints.ai_socktype = SOCK_STREAM;
446hints.ai_flags = AI_PASSIVE;
447error = getaddrinfo(NULL, "http", &hints, &res0);
448if (error) {
449 errx(1, "%s", gai_strerror(error));
450 /*NOTREACHED*/
451}
452nsock = 0;
453for (res = res0; res && nsock < MAXSOCK; res = res->ai_next) {
454 s[nsock] = socket(res->ai_family, res->ai_socktype,
455 res->ai_protocol);
456 if (s[nsock] < 0) {
457 cause = "socket";
458 continue;
459 }
460
461 if (bind(s[nsock], res->ai_addr, res->ai_addrlen) < 0) {
462 cause = "bind";
463 close(s[nsock]);
464 continue;
465 }
466 (void) listen(s[nsock], 5);
467
468 nsock++;
469}
470if (nsock == 0) {
471 err(1, cause);
472 /*NOTREACHED*/
473}
474freeaddrinfo(res0);
475.Ed
476.\"
477.Sh DIAGNOSTICS
478Error return status from
479.Fn getaddrinfo
480is zero on success and non-zero on errors.
481Non-zero error codes are defined in
482.Aq Pa netdb.h ,
483and as follows:
484.Pp
485.Bl -tag -width EAI_ADDRFAMILY -compact
486.It Dv EAI_ADDRFAMILY
487Address family for
488.Fa nodename
489not supported.
490.It Dv EAI_AGAIN
491Temporary failure in name resolution.
492.It Dv EAI_BADFLAGS
493Invalid value for
494.Fa ai_flags .
495.It Dv EAI_FAIL
496Non-recoverable failure in name resolution.
497.It Dv EAI_FAMILY
498.Fa ai_family
499not supported.
500.It Dv EAI_MEMORY
501Memory allocation failure.
502.It Dv EAI_NODATA
503No address associated with
504.Fa nodename .
505.It Dv EAI_NONAME
506.Fa nodename
507nor
508.Fa servname
509provided, or not known.
510.It Dv EAI_SERVICE
511.Fa servname
512not supported for
513.Fa ai_socktype .
514.It Dv EAI_SOCKTYPE
515.Fa ai_socktype
516not supported.
517.It Dv EAI_SYSTEM
518System error returned in
519.Va errno .
520.El
521.Pp
522If called with proper argument,
523.Fn gai_strerror
524returns a pointer to a string describing the given error code.
525If the argument is not one of the
526.Dv EAI_xxx
527values, the function still returns a pointer to a string whose contents
528indicate an unknown error.
529.\"
530.Sh SEE ALSO
531.Xr gethostbyname 3 ,
532.Xr getnameinfo 3 ,
533.Xr getservbyname 3 ,
534.Xr hosts 5 ,
535.Xr resolv.conf 5 ,
536.Xr services 5 ,
537.Xr hostname 7 ,
538.Xr named 8
539.Rs
540.%A R. Gilligan
541.%A S. Thomson
542.%A J. Bound
543.%A W. Stevens
544.%T Basic Socket Interface Extensions for IPv6
545.%R RFC 2553
546.%D March 1999
547.Re
548.Rs
549.%A Tatsuya Jinmei
550.%A Atsushi Onoe
551.%T "An Extension of Format for IPv6 Scoped Addresses"
552.%R internet draft
553.%N draft-ietf-ipngwg-scopedaddr-format-02.txt
554.%O work in progress material
555.Re
556.Rs
557.%A Craig Metz
558.%T Protocol Independence Using the Sockets API
559.%B "Proceedings of the freenix track: 2000 USENIX annual technical conference"
560.%D June 2000
561.Re
562.\"
563.Sh STANDARDS
564The
565.Fn getaddrinfo
566function is defined in IEEE POSIX 1003.1g draft specification,
567and documented in
568.Dq Basic Socket Interface Extensions for IPv6
569.Pq RFC 2553 .
570.\"
571.Sh HISTORY
572The implementation first appeared in WIDE Hydrangea IPv6 protocol stack kit.
573.\"
574.Sh BUGS
575The current implementation is not thread-safe.
576.Pp
577The text was shamelessly copied from RFC 2553.
diff --git a/src/lib/libc/net/getaddrinfo.c b/src/lib/libc/net/getaddrinfo.c
new file mode 100644
index 0000000000..eb7bd7b3b1
--- /dev/null
+++ b/src/lib/libc/net/getaddrinfo.c
@@ -0,0 +1,1885 @@
1/* $OpenBSD: getaddrinfo.c,v 1.48 2003/07/21 23:17:53 marc 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 **, const char *);
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,
422 &cur->ai_next);
423
424 if (error)
425 goto free;
426
427 while (cur && cur->ai_next)
428 cur = cur->ai_next;
429 }
430
431 /*
432 * XXX
433 * If numreic representation of AF1 can be interpreted as FQDN
434 * representation of AF2, we need to think again about the code below.
435 */
436 if (sentinel.ai_next)
437 goto good;
438
439 if (hostname == NULL)
440 ERR(EAI_NODATA);
441 if (pai->ai_flags & AI_NUMERICHOST)
442 ERR(EAI_NONAME);
443
444 /*
445 * hostname as alphabetical name.
446 * we would like to prefer AF_INET6 than AF_INET, so we'll make a
447 * outer loop by AFs.
448 */
449 for (ex = explore; ex->e_af >= 0; ex++) {
450 *pai = ai0;
451
452 /* require exact match for family field */
453 if (pai->ai_family != ex->e_af)
454 continue;
455
456 if (!MATCH(pai->ai_socktype, ex->e_socktype,
457 WILD_SOCKTYPE(ex))) {
458 continue;
459 }
460 if (!MATCH(pai->ai_protocol, ex->e_protocol,
461 WILD_PROTOCOL(ex))) {
462 continue;
463 }
464
465 if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
466 pai->ai_socktype = ex->e_socktype;
467 if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
468 pai->ai_protocol = ex->e_protocol;
469
470 error = explore_fqdn(pai, hostname, servname,
471 &cur->ai_next);
472
473 while (cur && cur->ai_next)
474 cur = cur->ai_next;
475 }
476
477 /* XXX */
478 if (sentinel.ai_next)
479 error = 0;
480
481 if (error)
482 goto free;
483 if (error == 0) {
484 if (sentinel.ai_next) {
485 good:
486 *res = sentinel.ai_next;
487 return SUCCESS;
488 } else
489 error = EAI_FAIL;
490 }
491 free:
492 bad:
493 if (sentinel.ai_next)
494 freeaddrinfo(sentinel.ai_next);
495 *res = NULL;
496 return error;
497}
498
499/*
500 * FQDN hostname, DNS lookup
501 */
502
503static int
504explore_fqdn(pai, hostname, servname, res)
505 const struct addrinfo *pai;
506 const char *hostname;
507 const char *servname;
508 struct addrinfo **res;
509{
510 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
511 struct addrinfo *result;
512 struct addrinfo *cur;
513 int error = 0;
514 char lookups[MAXDNSLUS];
515 int i;
516 _THREAD_PRIVATE_MUTEX(_explore_mutex);
517
518 result = NULL;
519
520#if 0
521 /*
522 * If AI_ADDRCONFIG is specified, check if we are expected to
523 * return the address family or not.
524 * XXX does not handle PF_UNSPEC case, should filter final result
525 */
526 if ((pai->ai_flags & AI_ADDRCONFIG) != 0 && !addrconfig(pai)) {
527 return 0;
528 }
529#endif
530
531 /*
532 * if the servname does not match socktype/protocol, ignore it.
533 */
534 if (get_portmatch(pai, servname) != 0) {
535 return 0;
536 }
537
538 if ((_resp->options & RES_INIT) == 0 && res_init() == -1)
539 strlcpy(lookups, "f", sizeof lookups);
540 else {
541 bcopy(_resp->lookups, lookups, sizeof lookups);
542 if (lookups[0] == '\0')
543 strlcpy(lookups, "bf", sizeof lookups);
544 }
545
546 /*
547 * The yp/dns/files getaddrinfo functions are not thread safe.
548 * Protect them with a mutex.
549 */
550 _THREAD_PRIVATE_MUTEX_LOCK(_explore_mutex);
551 for (i = 0; i < MAXDNSLUS && result == NULL && lookups[i]; i++) {
552 switch (lookups[i]) {
553#ifdef YP
554 case 'y':
555 result = _yp_getaddrinfo(hostname, pai);
556 break;
557#endif
558 case 'b':
559 result = _dns_getaddrinfo(hostname, pai);
560 break;
561 case 'f':
562 result = _files_getaddrinfo(hostname, pai);
563 break;
564 }
565 }
566 _THREAD_PRIVATE_MUTEX_UNLOCK(_explore_mutex);
567 if (result) {
568 for (cur = result; cur; cur = cur->ai_next) {
569 GET_PORT(cur, servname);
570 /* canonname should be filled already */
571 }
572 *res = result;
573 return 0;
574 } else {
575 /* translate error code */
576 switch (h_errno) {
577 case NETDB_SUCCESS:
578 error = EAI_FAIL; /*XXX strange */
579 break;
580 case HOST_NOT_FOUND:
581 error = EAI_NODATA;
582 break;
583 case TRY_AGAIN:
584 error = EAI_AGAIN;
585 break;
586 case NO_RECOVERY:
587 error = EAI_FAIL;
588 break;
589 case NO_DATA:
590#if NO_ADDRESS != NO_DATA
591 case NO_ADDRESS:
592#endif
593 error = EAI_NODATA;
594 break;
595 default: /* unknown ones */
596 error = EAI_FAIL;
597 break;
598 }
599 }
600
601free:
602 if (result)
603 freeaddrinfo(result);
604 return error;
605}
606
607/*
608 * hostname == NULL.
609 * passive socket -> anyaddr (0.0.0.0 or ::)
610 * non-passive socket -> localhost (127.0.0.1 or ::1)
611 */
612static int
613explore_null(pai, servname, res)
614 const struct addrinfo *pai;
615 const char *servname;
616 struct addrinfo **res;
617{
618 int s;
619 const struct afd *afd;
620 struct addrinfo *cur;
621 struct addrinfo sentinel;
622 int error;
623
624 *res = NULL;
625 sentinel.ai_next = NULL;
626 cur = &sentinel;
627
628 /*
629 * filter out AFs that are not supported by the kernel
630 * XXX errno?
631 */
632 s = socket(pai->ai_family, SOCK_DGRAM, 0);
633 if (s < 0) {
634 if (errno != EMFILE)
635 return 0;
636 } else
637 close(s);
638
639 /*
640 * if the servname does not match socktype/protocol, ignore it.
641 */
642 if (get_portmatch(pai, servname) != 0)
643 return 0;
644
645 afd = find_afd(pai->ai_family);
646 if (afd == NULL)
647 return 0;
648
649 if (pai->ai_flags & AI_PASSIVE) {
650 GET_AI(cur->ai_next, afd, afd->a_addrany);
651 /* xxx meaningless?
652 * GET_CANONNAME(cur->ai_next, "anyaddr");
653 */
654 GET_PORT(cur->ai_next, servname);
655 } else {
656 GET_AI(cur->ai_next, afd, afd->a_loopback);
657 /* xxx meaningless?
658 * GET_CANONNAME(cur->ai_next, "localhost");
659 */
660 GET_PORT(cur->ai_next, servname);
661 }
662 cur = cur->ai_next;
663
664 *res = sentinel.ai_next;
665 return 0;
666
667free:
668 if (sentinel.ai_next)
669 freeaddrinfo(sentinel.ai_next);
670 return error;
671}
672
673/*
674 * numeric hostname
675 */
676static int
677explore_numeric(pai, hostname, servname, res, canonname)
678 const struct addrinfo *pai;
679 const char *hostname;
680 const char *servname;
681 struct addrinfo **res;
682 const char *canonname;
683{
684 const struct afd *afd;
685 struct addrinfo *cur;
686 struct addrinfo sentinel;
687 int error;
688 char pton[PTON_MAX];
689
690 *res = NULL;
691 sentinel.ai_next = NULL;
692 cur = &sentinel;
693
694 /*
695 * if the servname does not match socktype/protocol, ignore it.
696 */
697 if (get_portmatch(pai, servname) != 0)
698 return 0;
699
700 afd = find_afd(pai->ai_family);
701 if (afd == NULL)
702 return 0;
703
704 switch (afd->a_af) {
705#if 0 /*X/Open spec*/
706 case AF_INET:
707 if (inet_aton(hostname, (struct in_addr *)pton) == 1) {
708 if (pai->ai_family == afd->a_af ||
709 pai->ai_family == PF_UNSPEC /*?*/) {
710 GET_AI(cur->ai_next, afd, pton);
711 GET_PORT(cur->ai_next, servname);
712 if ((pai->ai_flags & AI_CANONNAME)) {
713 /*
714 * Set the numeric address itself as
715 * the canonical name, based on a
716 * clarification in rfc2553bis-03.
717 */
718 GET_CANONNAME(cur->ai_next, canonname);
719 }
720 while (cur && cur->ai_next)
721 cur = cur->ai_next;
722 } else
723 ERR(EAI_FAMILY); /*xxx*/
724 }
725 break;
726#endif
727 default:
728 if (inet_pton(afd->a_af, hostname, pton) == 1) {
729 if (pai->ai_family == afd->a_af ||
730 pai->ai_family == PF_UNSPEC /*?*/) {
731 GET_AI(cur->ai_next, afd, pton);
732 GET_PORT(cur->ai_next, servname);
733 if ((pai->ai_flags & AI_CANONNAME)) {
734 /*
735 * Set the numeric address itself as
736 * the canonical name, based on a
737 * clarification in rfc2553bis-03.
738 */
739 GET_CANONNAME(cur->ai_next, canonname);
740 }
741 while (cur && cur->ai_next)
742 cur = cur->ai_next;
743 } else
744 ERR(EAI_FAMILY); /*xxx*/
745 }
746 break;
747 }
748
749 *res = sentinel.ai_next;
750 return 0;
751
752free:
753bad:
754 if (sentinel.ai_next)
755 freeaddrinfo(sentinel.ai_next);
756 return error;
757}
758
759/*
760 * numeric hostname with scope
761 */
762static int
763explore_numeric_scope(pai, hostname, servname, res)
764 const struct addrinfo *pai;
765 const char *hostname;
766 const char *servname;
767 struct addrinfo **res;
768{
769#if !defined(SCOPE_DELIMITER) || !defined(INET6)
770 return explore_numeric(pai, hostname, servname, res, hostname);
771#else
772 const struct afd *afd;
773 struct addrinfo *cur;
774 int error;
775 char *cp, *hostname2 = NULL, *scope, *addr;
776 struct sockaddr_in6 *sin6;
777
778 /*
779 * if the servname does not match socktype/protocol, ignore it.
780 */
781 if (get_portmatch(pai, servname) != 0)
782 return 0;
783
784 afd = find_afd(pai->ai_family);
785 if (afd == NULL)
786 return 0;
787
788 if (!afd->a_scoped)
789 return explore_numeric(pai, hostname, servname, res, hostname);
790
791 cp = strchr(hostname, SCOPE_DELIMITER);
792 if (cp == NULL)
793 return explore_numeric(pai, hostname, servname, res, hostname);
794
795 /*
796 * Handle special case of <scoped_address><delimiter><scope id>
797 */
798 hostname2 = strdup(hostname);
799 if (hostname2 == NULL)
800 return EAI_MEMORY;
801 /* terminate at the delimiter */
802 hostname2[cp - hostname] = '\0';
803 addr = hostname2;
804 scope = cp + 1;
805
806 error = explore_numeric(pai, addr, servname, res, hostname);
807 if (error == 0) {
808 u_int32_t scopeid;
809
810 for (cur = *res; cur; cur = cur->ai_next) {
811 if (cur->ai_family != AF_INET6)
812 continue;
813 sin6 = (struct sockaddr_in6 *)(void *)cur->ai_addr;
814 if (ip6_str2scopeid(scope, sin6, &scopeid) == -1) {
815 free(hostname2);
816 return(EAI_NODATA); /* XXX: is return OK? */
817 }
818 sin6->sin6_scope_id = scopeid;
819 }
820 }
821
822 free(hostname2);
823
824 return error;
825#endif
826}
827
828static int
829get_canonname(pai, ai, str)
830 const struct addrinfo *pai;
831 struct addrinfo *ai;
832 const char *str;
833{
834 if ((pai->ai_flags & AI_CANONNAME) != 0) {
835 ai->ai_canonname = strdup(str);
836 if (ai->ai_canonname == NULL)
837 return EAI_MEMORY;
838 }
839 return 0;
840}
841
842static struct addrinfo *
843get_ai(pai, afd, addr)
844 const struct addrinfo *pai;
845 const struct afd *afd;
846 const char *addr;
847{
848 char *p;
849 struct addrinfo *ai;
850
851 ai = (struct addrinfo *)malloc(sizeof(struct addrinfo)
852 + (afd->a_socklen));
853 if (ai == NULL)
854 return NULL;
855
856 memcpy(ai, pai, sizeof(struct addrinfo));
857 ai->ai_addr = (struct sockaddr *)(void *)(ai + 1);
858 memset(ai->ai_addr, 0, (size_t)afd->a_socklen);
859 ai->ai_addr->sa_len = afd->a_socklen;
860 ai->ai_addrlen = afd->a_socklen;
861 ai->ai_addr->sa_family = ai->ai_family = afd->a_af;
862 p = (char *)(void *)(ai->ai_addr);
863 memcpy(p + afd->a_off, addr, (size_t)afd->a_addrlen);
864 return ai;
865}
866
867static int
868get_portmatch(ai, servname)
869 const struct addrinfo *ai;
870 const char *servname;
871{
872
873 /* get_port does not touch first argument. when matchonly == 1. */
874 /* LINTED const cast */
875 return get_port((struct addrinfo *)ai, servname, 1);
876}
877
878static int
879get_port(ai, servname, matchonly)
880 struct addrinfo *ai;
881 const char *servname;
882 int matchonly;
883{
884 const char *proto;
885 struct servent *sp;
886 int port;
887 int allownumeric;
888 /* mutex is defined in getnameinfo.c */
889 extern pthread_mutex_t __THREAD_MUTEX_NAME(serv_mutex);
890
891 if (servname == NULL)
892 return 0;
893 switch (ai->ai_family) {
894 case AF_INET:
895#ifdef AF_INET6
896 case AF_INET6:
897#endif
898 break;
899 default:
900 return 0;
901 }
902
903 switch (ai->ai_socktype) {
904 case SOCK_RAW:
905 return EAI_SERVICE;
906 case SOCK_DGRAM:
907 case SOCK_STREAM:
908 allownumeric = 1;
909 break;
910 case ANY:
911 allownumeric = 0;
912 break;
913 default:
914 return EAI_SOCKTYPE;
915 }
916
917 if (str_isnumber(servname)) {
918 if (!allownumeric)
919 return EAI_SERVICE;
920 port = atoi(servname);
921 if (port < 0 || port > 65535)
922 return EAI_SERVICE;
923 port = htons(port);
924 } else {
925 switch (ai->ai_socktype) {
926 case SOCK_DGRAM:
927 proto = "udp";
928 break;
929 case SOCK_STREAM:
930 proto = "tcp";
931 break;
932 default:
933 proto = NULL;
934 break;
935 }
936
937 _THREAD_PRIVATE_MUTEX_LOCK(serv_mutex);
938 sp = getservbyname(servname, proto);
939 _THREAD_PRIVATE_MUTEX_UNLOCK(serv_mutex);
940 if (sp == NULL)
941 return EAI_SERVICE;
942 port = sp->s_port;
943 }
944
945 if (!matchonly) {
946 switch (ai->ai_family) {
947 case AF_INET:
948 ((struct sockaddr_in *)(void *)
949 ai->ai_addr)->sin_port = port;
950 break;
951#ifdef INET6
952 case AF_INET6:
953 ((struct sockaddr_in6 *)(void *)
954 ai->ai_addr)->sin6_port = port;
955 break;
956#endif
957 }
958 }
959
960 return 0;
961}
962
963static const struct afd *
964find_afd(af)
965 int af;
966{
967 const struct afd *afd;
968
969 if (af == PF_UNSPEC)
970 return NULL;
971 for (afd = afdl; afd->a_af; afd++) {
972 if (afd->a_af == af)
973 return afd;
974 }
975 return NULL;
976}
977
978#if 0
979/*
980 * post-2553: AI_ADDRCONFIG check. if we use getipnodeby* as backend, backend
981 * will take care of it.
982 * the semantics of AI_ADDRCONFIG is not defined well. we are not sure
983 * if the code is right or not.
984 */
985static int
986addrconfig(pai)
987 const struct addrinfo *pai;
988{
989 int s;
990
991 /* XXX errno */
992 s = socket(pai->ai_family, SOCK_DGRAM, 0);
993 if (s < 0)
994 return 0;
995 close(s);
996 return 1;
997}
998#endif
999
1000#ifdef INET6
1001/* convert a string to a scope identifier. XXX: IPv6 specific */
1002static int
1003ip6_str2scopeid(scope, sin6, scopeid)
1004 char *scope;
1005 struct sockaddr_in6 *sin6;
1006 u_int32_t *scopeid;
1007{
1008 u_long lscopeid;
1009 struct in6_addr *a6 = &sin6->sin6_addr;
1010 char *ep;
1011
1012 /* empty scopeid portion is invalid */
1013 if (*scope == '\0')
1014 return -1;
1015
1016 if (IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6)) {
1017 /*
1018 * We currently assume a one-to-one mapping between links
1019 * and interfaces, so we simply use interface indices for
1020 * like-local scopes.
1021 */
1022 *scopeid = if_nametoindex(scope);
1023 if (*scopeid == 0)
1024 goto trynumeric;
1025 return 0;
1026 }
1027
1028 /* still unclear about literal, allow numeric only - placeholder */
1029 if (IN6_IS_ADDR_SITELOCAL(a6) || IN6_IS_ADDR_MC_SITELOCAL(a6))
1030 goto trynumeric;
1031 if (IN6_IS_ADDR_MC_ORGLOCAL(a6))
1032 goto trynumeric;
1033 else
1034 goto trynumeric; /* global */
1035
1036 /* try to convert to a numeric id as a last resort */
1037 trynumeric:
1038 errno = 0;
1039 lscopeid = strtoul(scope, &ep, 10);
1040 *scopeid = (u_int32_t)(lscopeid & 0xffffffffUL);
1041 if (errno == 0 && ep && *ep == '\0' && *scopeid == lscopeid)
1042 return 0;
1043 else
1044 return -1;
1045}
1046#endif
1047
1048/* code duplicate with gethnamaddr.c */
1049
1050static const char AskedForGot[] =
1051 "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
1052static FILE *hostf = NULL;
1053
1054static struct addrinfo *
1055getanswer(answer, anslen, qname, qtype, pai)
1056 const querybuf *answer;
1057 int anslen;
1058 const char *qname;
1059 int qtype;
1060 const struct addrinfo *pai;
1061{
1062 struct addrinfo sentinel, *cur;
1063 struct addrinfo ai;
1064 const struct afd *afd;
1065 char *canonname;
1066 const HEADER *hp;
1067 const u_char *cp;
1068 int n;
1069 const u_char *eom;
1070 char *bp, *ep;
1071 int type, class, ancount, qdcount;
1072 int haveanswer, had_error;
1073 char tbuf[MAXDNAME];
1074 int (*name_ok)(const char *);
1075 char hostbuf[8*1024];
1076
1077 memset(&sentinel, 0, sizeof(sentinel));
1078 cur = &sentinel;
1079
1080 canonname = NULL;
1081 eom = answer->buf + anslen;
1082 switch (qtype) {
1083 case T_A:
1084 case T_AAAA:
1085 case T_ANY: /*use T_ANY only for T_A/T_AAAA lookup*/
1086 name_ok = res_hnok;
1087 break;
1088 default:
1089 return (NULL); /* XXX should be abort() -- but that is illegal */
1090 }
1091 /*
1092 * find first satisfactory answer
1093 */
1094 hp = &answer->hdr;
1095 ancount = ntohs(hp->ancount);
1096 qdcount = ntohs(hp->qdcount);
1097 bp = hostbuf;
1098 ep = hostbuf + sizeof hostbuf;
1099 cp = answer->buf + HFIXEDSZ;
1100 if (qdcount != 1) {
1101 h_errno = NO_RECOVERY;
1102 return (NULL);
1103 }
1104 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
1105 if ((n < 0) || !(*name_ok)(bp)) {
1106 h_errno = NO_RECOVERY;
1107 return (NULL);
1108 }
1109 cp += n + QFIXEDSZ;
1110 if (qtype == T_A || qtype == T_AAAA || qtype == T_ANY) {
1111 /* res_send() has already verified that the query name is the
1112 * same as the one we sent; this just gets the expanded name
1113 * (i.e., with the succeeding search-domain tacked on).
1114 */
1115 n = strlen(bp) + 1; /* for the \0 */
1116 if (n >= MAXHOSTNAMELEN) {
1117 h_errno = NO_RECOVERY;
1118 return (NULL);
1119 }
1120 canonname = bp;
1121 bp += n;
1122 /* The qname can be abbreviated, but h_name is now absolute. */
1123 qname = canonname;
1124 }
1125 haveanswer = 0;
1126 had_error = 0;
1127 while (ancount-- > 0 && cp < eom && !had_error) {
1128 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
1129 if ((n < 0) || !(*name_ok)(bp)) {
1130 had_error++;
1131 continue;
1132 }
1133 cp += n; /* name */
1134 type = _getshort(cp);
1135 cp += INT16SZ; /* type */
1136 class = _getshort(cp);
1137 cp += INT16SZ + INT32SZ; /* class, TTL */
1138 n = _getshort(cp);
1139 cp += INT16SZ; /* len */
1140 if (class != C_IN) {
1141 /* XXX - debug? syslog? */
1142 cp += n;
1143 continue; /* XXX - had_error++ ? */
1144 }
1145 if ((qtype == T_A || qtype == T_AAAA || qtype == T_ANY) &&
1146 type == T_CNAME) {
1147 n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
1148 if ((n < 0) || !(*name_ok)(tbuf)) {
1149 had_error++;
1150 continue;
1151 }
1152 cp += n;
1153 /* Get canonical name. */
1154 n = strlen(tbuf) + 1; /* for the \0 */
1155 if (n > ep - bp || n >= MAXHOSTNAMELEN) {
1156 had_error++;
1157 continue;
1158 }
1159 strlcpy(bp, tbuf, ep - bp);
1160 canonname = bp;
1161 bp += n;
1162 continue;
1163 }
1164 if (qtype == T_ANY) {
1165 if (!(type == T_A || type == T_AAAA)) {
1166 cp += n;
1167 continue;
1168 }
1169 } else if (type != qtype) {
1170 if (type != T_KEY && type != T_SIG)
1171 syslog(LOG_NOTICE|LOG_AUTH,
1172 "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
1173 qname, p_class(C_IN), p_type(qtype),
1174 p_type(type));
1175 cp += n;
1176 continue; /* XXX - had_error++ ? */
1177 }
1178 switch (type) {
1179 case T_A:
1180 case T_AAAA:
1181 if (strcasecmp(canonname, bp) != 0) {
1182 syslog(LOG_NOTICE|LOG_AUTH,
1183 AskedForGot, canonname, bp);
1184 cp += n;
1185 continue; /* XXX - had_error++ ? */
1186 }
1187 if (type == T_A && n != INADDRSZ) {
1188 cp += n;
1189 continue;
1190 }
1191 if (type == T_AAAA && n != IN6ADDRSZ) {
1192 cp += n;
1193 continue;
1194 }
1195 if (type == T_AAAA) {
1196 struct in6_addr in6;
1197 memcpy(&in6, cp, IN6ADDRSZ);
1198 if (IN6_IS_ADDR_V4MAPPED(&in6)) {
1199 cp += n;
1200 continue;
1201 }
1202 }
1203 if (!haveanswer) {
1204 int nn;
1205
1206 canonname = bp;
1207 nn = strlen(bp) + 1; /* for the \0 */
1208 bp += nn;
1209 }
1210
1211 /* don't overwrite pai */
1212 ai = *pai;
1213 ai.ai_family = (type == T_A) ? AF_INET : AF_INET6;
1214 afd = find_afd(ai.ai_family);
1215 if (afd == NULL) {
1216 cp += n;
1217 continue;
1218 }
1219 cur->ai_next = get_ai(&ai, afd, (const char *)cp);
1220 if (cur->ai_next == NULL)
1221 had_error++;
1222 while (cur && cur->ai_next)
1223 cur = cur->ai_next;
1224 cp += n;
1225 break;
1226 default:
1227 abort(); /* XXX abort illegal in library */
1228 }
1229 if (!had_error)
1230 haveanswer++;
1231 }
1232 if (haveanswer) {
1233 if (!canonname)
1234 (void)get_canonname(pai, sentinel.ai_next, qname);
1235 else
1236 (void)get_canonname(pai, sentinel.ai_next, canonname);
1237 h_errno = NETDB_SUCCESS;
1238 return sentinel.ai_next;
1239 }
1240
1241 h_errno = NO_RECOVERY;
1242 return NULL;
1243}
1244
1245/*ARGSUSED*/
1246static struct addrinfo *
1247_dns_getaddrinfo(name, pai)
1248 const char *name;
1249 const struct addrinfo *pai;
1250{
1251 struct addrinfo *ai;
1252 querybuf *buf, *buf2;
1253 struct addrinfo sentinel, *cur;
1254 struct res_target q, q2;
1255
1256 memset(&q, 0, sizeof(q2));
1257 memset(&q2, 0, sizeof(q2));
1258 memset(&sentinel, 0, sizeof(sentinel));
1259 cur = &sentinel;
1260
1261 buf = malloc(sizeof(*buf));
1262 if (buf == NULL) {
1263 h_errno = NETDB_INTERNAL;
1264 return NULL;
1265 }
1266 buf2 = malloc(sizeof(*buf2));
1267 if (buf2 == NULL) {
1268 free(buf);
1269 h_errno = NETDB_INTERNAL;
1270 return NULL;
1271 }
1272
1273 switch (pai->ai_family) {
1274 case AF_UNSPEC:
1275 /* prefer IPv6 */
1276 q.qclass = C_IN;
1277 q.qtype = T_AAAA;
1278 q.answer = buf->buf;
1279 q.anslen = sizeof(buf->buf);
1280 q.next = &q2;
1281 q2.qclass = C_IN;
1282 q2.qtype = T_A;
1283 q2.answer = buf2->buf;
1284 q2.anslen = sizeof(buf2->buf);
1285 break;
1286 case AF_INET:
1287 q.qclass = C_IN;
1288 q.qtype = T_A;
1289 q.answer = buf->buf;
1290 q.anslen = sizeof(buf->buf);
1291 break;
1292 case AF_INET6:
1293 q.qclass = C_IN;
1294 q.qtype = T_AAAA;
1295 q.answer = buf->buf;
1296 q.anslen = sizeof(buf->buf);
1297 break;
1298 default:
1299 free(buf);
1300 free(buf2);
1301 return NULL;
1302 }
1303 if (res_searchN(name, &q) < 0) {
1304 free(buf);
1305 free(buf2);
1306 return NULL;
1307 }
1308 ai = getanswer(buf, q.n, q.name, q.qtype, pai);
1309 if (ai) {
1310 cur->ai_next = ai;
1311 while (cur && cur->ai_next)
1312 cur = cur->ai_next;
1313 }
1314 if (q.next) {
1315 ai = getanswer(buf2, q2.n, q2.name, q2.qtype, pai);
1316 if (ai)
1317 cur->ai_next = ai;
1318 }
1319 free(buf);
1320 free(buf2);
1321 return sentinel.ai_next;
1322}
1323
1324static FILE *hostf;
1325
1326static void
1327_sethtent()
1328{
1329 if (!hostf)
1330 hostf = fopen(_PATH_HOSTS, "r" );
1331 else
1332 rewind(hostf);
1333}
1334
1335static void
1336_endhtent()
1337{
1338 if (hostf) {
1339 (void) fclose(hostf);
1340 hostf = NULL;
1341 }
1342}
1343
1344static struct addrinfo *
1345_gethtent(name, pai)
1346 const char *name;
1347 const struct addrinfo *pai;
1348{
1349 char *p;
1350 char *cp, *tname, *cname;
1351 struct addrinfo hints, *res0, *res;
1352 int error;
1353 const char *addr;
1354 char hostbuf[8*1024];
1355
1356 if (!hostf && !(hostf = fopen(_PATH_HOSTS, "r" )))
1357 return (NULL);
1358 again:
1359 if (!(p = fgets(hostbuf, sizeof hostbuf, hostf)))
1360 return (NULL);
1361 if (*p == '#')
1362 goto again;
1363 if (!(cp = strpbrk(p, "#\n")))
1364 goto again;
1365 *cp = '\0';
1366 if (!(cp = strpbrk(p, " \t")))
1367 goto again;
1368 *cp++ = '\0';
1369 addr = p;
1370 /* if this is not something we're looking for, skip it. */
1371 cname = NULL;
1372 while (cp && *cp) {
1373 if (*cp == ' ' || *cp == '\t') {
1374 cp++;
1375 continue;
1376 }
1377 if (!cname)
1378 cname = cp;
1379 tname = cp;
1380 if ((cp = strpbrk(cp, " \t")) != NULL)
1381 *cp++ = '\0';
1382 if (strcasecmp(name, tname) == 0)
1383 goto found;
1384 }
1385 goto again;
1386
1387found:
1388 hints = *pai;
1389 hints.ai_flags = AI_NUMERICHOST;
1390 error = getaddrinfo(addr, NULL, &hints, &res0);
1391 if (error)
1392 goto again;
1393 for (res = res0; res; res = res->ai_next) {
1394 /* cover it up */
1395 res->ai_flags = pai->ai_flags;
1396
1397 if (pai->ai_flags & AI_CANONNAME) {
1398 if (get_canonname(pai, res, cname) != 0) {
1399 freeaddrinfo(res0);
1400 goto again;
1401 }
1402 }
1403 }
1404 return res0;
1405}
1406
1407/*ARGSUSED*/
1408static struct addrinfo *
1409_files_getaddrinfo(name, pai)
1410 const char *name;
1411 const struct addrinfo *pai;
1412{
1413 struct addrinfo sentinel, *cur;
1414 struct addrinfo *p;
1415
1416 memset(&sentinel, 0, sizeof(sentinel));
1417 cur = &sentinel;
1418
1419 _sethtent();
1420 while ((p = _gethtent(name, pai)) != NULL) {
1421 cur->ai_next = p;
1422 while (cur && cur->ai_next)
1423 cur = cur->ai_next;
1424 }
1425 _endhtent();
1426
1427 return sentinel.ai_next;
1428}
1429
1430#ifdef YP
1431static char *__ypdomain;
1432
1433/*ARGSUSED*/
1434static struct addrinfo *
1435_yphostent(line, pai)
1436 char *line;
1437 const struct addrinfo *pai;
1438{
1439 struct addrinfo sentinel, *cur;
1440 struct addrinfo hints, *res, *res0;
1441 int error;
1442 char *p = line;
1443 const char *addr, *canonname;
1444 char *nextline;
1445 char *cp;
1446
1447 addr = canonname = NULL;
1448
1449 memset(&sentinel, 0, sizeof(sentinel));
1450 cur = &sentinel;
1451
1452nextline:
1453 /* terminate line */
1454 cp = strchr(p, '\n');
1455 if (cp) {
1456 *cp++ = '\0';
1457 nextline = cp;
1458 } else
1459 nextline = NULL;
1460
1461 cp = strpbrk(p, " \t");
1462 if (cp == NULL) {
1463 if (canonname == NULL)
1464 return (NULL);
1465 else
1466 goto done;
1467 }
1468 *cp++ = '\0';
1469
1470 addr = p;
1471
1472 while (cp && *cp) {
1473 if (*cp == ' ' || *cp == '\t') {
1474 cp++;
1475 continue;
1476 }
1477 if (!canonname)
1478 canonname = cp;
1479 if ((cp = strpbrk(cp, " \t")) != NULL)
1480 *cp++ = '\0';
1481 }
1482
1483 hints = *pai;
1484 hints.ai_flags = AI_NUMERICHOST;
1485 error = getaddrinfo(addr, NULL, &hints, &res0);
1486 if (error == 0) {
1487 for (res = res0; res; res = res->ai_next) {
1488 /* cover it up */
1489 res->ai_flags = pai->ai_flags;
1490
1491 if (pai->ai_flags & AI_CANONNAME)
1492 (void)get_canonname(pai, res, canonname);
1493 }
1494 } else
1495 res0 = NULL;
1496 if (res0) {
1497 cur->ai_next = res0;
1498 while (cur && cur->ai_next)
1499 cur = cur->ai_next;
1500 }
1501
1502 if (nextline) {
1503 p = nextline;
1504 goto nextline;
1505 }
1506
1507done:
1508 return sentinel.ai_next;
1509}
1510
1511/*ARGSUSED*/
1512static struct addrinfo *
1513_yp_getaddrinfo(name, pai)
1514 const char *name;
1515 const struct addrinfo *pai;
1516{
1517 struct addrinfo sentinel, *cur;
1518 struct addrinfo *ai = NULL;
1519 static char *__ypcurrent;
1520 int __ypcurrentlen, r;
1521
1522 memset(&sentinel, 0, sizeof(sentinel));
1523 cur = &sentinel;
1524
1525 if (!__ypdomain) {
1526 if (_yp_check(&__ypdomain) == 0)
1527 return NULL;
1528 }
1529 if (__ypcurrent)
1530 free(__ypcurrent);
1531 __ypcurrent = NULL;
1532
1533 /* hosts.byname is only for IPv4 (Solaris8) */
1534 if (pai->ai_family == PF_UNSPEC || pai->ai_family == PF_INET) {
1535 r = yp_match(__ypdomain, "hosts.byname", name,
1536 (int)strlen(name), &__ypcurrent, &__ypcurrentlen);
1537 if (r == 0) {
1538 struct addrinfo ai4;
1539
1540 ai4 = *pai;
1541 ai4.ai_family = AF_INET;
1542 ai = _yphostent(__ypcurrent, &ai4);
1543 if (ai) {
1544 cur->ai_next = ai;
1545 while (cur && cur->ai_next)
1546 cur = cur->ai_next;
1547 }
1548 }
1549 }
1550
1551 /* ipnodes.byname can hold both IPv4/v6 */
1552 r = yp_match(__ypdomain, "ipnodes.byname", name,
1553 (int)strlen(name), &__ypcurrent, &__ypcurrentlen);
1554 if (r == 0) {
1555 ai = _yphostent(__ypcurrent, pai);
1556 if (ai) {
1557 cur->ai_next = ai;
1558 while (cur && cur->ai_next)
1559 cur = cur->ai_next;
1560 }
1561 }
1562
1563 return sentinel.ai_next;
1564}
1565#endif
1566
1567
1568/* resolver logic */
1569
1570extern const char *__hostalias(const char *);
1571extern int h_errno;
1572extern int res_opt(int, u_char *, int, int);
1573
1574/*
1575 * Formulate a normal query, send, and await answer.
1576 * Returned answer is placed in supplied buffer "answer".
1577 * Perform preliminary check of answer, returning success only
1578 * if no error is indicated and the answer count is nonzero.
1579 * Return the size of the response on success, -1 on error.
1580 * Error number is left in h_errno.
1581 *
1582 * Caller must parse answer and determine whether it answers the question.
1583 */
1584static int
1585res_queryN(name, target)
1586 const char *name; /* domain name */
1587 struct res_target *target;
1588{
1589 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
1590 u_char *buf;
1591 HEADER *hp;
1592 int n;
1593 struct res_target *t;
1594 int rcode;
1595 int ancount;
1596
1597 buf = malloc(MAXPACKET);
1598 if (buf == NULL) {
1599 h_errno = NETDB_INTERNAL;
1600 return (-1);
1601 }
1602
1603 rcode = NOERROR;
1604 ancount = 0;
1605
1606 if ((_resp->options & RES_INIT) == 0 && res_init() == -1) {
1607 h_errno = NETDB_INTERNAL;
1608 free(buf);
1609 return (-1);
1610 }
1611
1612 for (t = target; t; t = t->next) {
1613 int class, type;
1614 u_char *answer;
1615 int anslen;
1616
1617 hp = (HEADER *)(void *)t->answer;
1618 hp->rcode = NOERROR; /* default */
1619
1620 /* make it easier... */
1621 class = t->qclass;
1622 type = t->qtype;
1623 answer = t->answer;
1624 anslen = t->anslen;
1625#ifdef DEBUG
1626 if (_resp->options & RES_DEBUG)
1627 printf(";; res_query(%s, %d, %d)\n", name, class, type);
1628#endif
1629
1630 n = res_mkquery(QUERY, name, class, type, NULL, 0, NULL,
1631 buf, MAXPACKET);
1632 if (n > 0 && (_resp->options & RES_USE_EDNS0) != 0)
1633 n = res_opt(n, buf, MAXPACKET, anslen);
1634 if (n <= 0) {
1635#ifdef DEBUG
1636 if (_resp->options & RES_DEBUG)
1637 printf(";; res_query: mkquery failed\n");
1638#endif
1639 h_errno = NO_RECOVERY;
1640 free(buf);
1641 return (n);
1642 }
1643 n = res_send(buf, n, answer, anslen);
1644#if 0
1645 if (n < 0) {
1646#ifdef DEBUG
1647 if (_resp->options & RES_DEBUG)
1648 printf(";; res_query: send error\n");
1649#endif
1650 h_errno = TRY_AGAIN;
1651 free(buf);
1652 return (n);
1653 }
1654#endif
1655
1656 if (n < 0 || hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
1657 rcode = hp->rcode; /* record most recent error */
1658#ifdef DEBUG
1659 if (_resp->options & RES_DEBUG)
1660 printf(";; rcode = %u, ancount=%u\n", hp->rcode,
1661 ntohs(hp->ancount));
1662#endif
1663 continue;
1664 }
1665
1666 ancount += ntohs(hp->ancount);
1667
1668 t->n = n;
1669 }
1670
1671 if (ancount == 0) {
1672 switch (rcode) {
1673 case NXDOMAIN:
1674 h_errno = HOST_NOT_FOUND;
1675 break;
1676 case SERVFAIL:
1677 h_errno = TRY_AGAIN;
1678 break;
1679 case NOERROR:
1680 h_errno = NO_DATA;
1681 break;
1682 case FORMERR:
1683 case NOTIMP:
1684 case REFUSED:
1685 default:
1686 h_errno = NO_RECOVERY;
1687 break;
1688 }
1689 free(buf);
1690 return (-1);
1691 }
1692 free(buf);
1693 return (ancount);
1694}
1695
1696/*
1697 * Formulate a normal query, send, and retrieve answer in supplied buffer.
1698 * Return the size of the response on success, -1 on error.
1699 * If enabled, implement search rules until answer or unrecoverable failure
1700 * is detected. Error code, if any, is left in h_errno.
1701 */
1702static int
1703res_searchN(name, target)
1704 const char *name; /* domain name */
1705 struct res_target *target;
1706{
1707 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
1708 const char *cp, * const *domain;
1709 HEADER *hp = (HEADER *)(void *)target->answer; /*XXX*/
1710 u_int dots;
1711 int trailing_dot, ret, saved_herrno;
1712 int got_nodata = 0, got_servfail = 0, tried_as_is = 0;
1713
1714 if ((_resp->options & RES_INIT) == 0 && res_init() == -1) {
1715 h_errno = NETDB_INTERNAL;
1716 return (-1);
1717 }
1718
1719 errno = 0;
1720 h_errno = HOST_NOT_FOUND; /* default, if we never query */
1721 dots = 0;
1722 for (cp = name; *cp; cp++)
1723 dots += (*cp == '.');
1724 trailing_dot = 0;
1725 if (cp > name && *--cp == '.')
1726 trailing_dot++;
1727
1728 /*
1729 * if there aren't any dots, it could be a user-level alias
1730 */
1731 if (!dots && (cp = __hostalias(name)) != NULL)
1732 return (res_queryN(cp, target));
1733
1734 /*
1735 * If there are dots in the name already, let's just give it a try
1736 * 'as is'. The threshold can be set with the "ndots" option.
1737 */
1738 saved_herrno = -1;
1739 if (dots >= _resp->ndots) {
1740 ret = res_querydomainN(name, NULL, target);
1741 if (ret > 0)
1742 return (ret);
1743 saved_herrno = h_errno;
1744 tried_as_is++;
1745 }
1746
1747 /*
1748 * We do at least one level of search if
1749 * - there is no dot and RES_DEFNAME is set, or
1750 * - there is at least one dot, there is no trailing dot,
1751 * and RES_DNSRCH is set.
1752 */
1753 if ((!dots && (_resp->options & RES_DEFNAMES)) ||
1754 (dots && !trailing_dot && (_resp->options & RES_DNSRCH))) {
1755 int done = 0;
1756
1757 for (domain = (const char * const *)_resp->dnsrch;
1758 *domain && !done;
1759 domain++) {
1760
1761 ret = res_querydomainN(name, *domain, target);
1762 if (ret > 0)
1763 return (ret);
1764
1765 /*
1766 * If no server present, give up.
1767 * If name isn't found in this domain,
1768 * keep trying higher domains in the search list
1769 * (if that's enabled).
1770 * On a NO_DATA error, keep trying, otherwise
1771 * a wildcard entry of another type could keep us
1772 * from finding this entry higher in the domain.
1773 * If we get some other error (negative answer or
1774 * server failure), then stop searching up,
1775 * but try the input name below in case it's
1776 * fully-qualified.
1777 */
1778 if (errno == ECONNREFUSED) {
1779 h_errno = TRY_AGAIN;
1780 return (-1);
1781 }
1782
1783 switch (h_errno) {
1784 case NO_DATA:
1785 got_nodata++;
1786 /* FALLTHROUGH */
1787 case HOST_NOT_FOUND:
1788 /* keep trying */
1789 break;
1790 case TRY_AGAIN:
1791 if (hp->rcode == SERVFAIL) {
1792 /* try next search element, if any */
1793 got_servfail++;
1794 break;
1795 }
1796 /* FALLTHROUGH */
1797 default:
1798 /* anything else implies that we're done */
1799 done++;
1800 }
1801 /*
1802 * if we got here for some reason other than DNSRCH,
1803 * we only wanted one iteration of the loop, so stop.
1804 */
1805 if (!(_resp->options & RES_DNSRCH))
1806 done++;
1807 }
1808 }
1809
1810 /*
1811 * if we have not already tried the name "as is", do that now.
1812 * note that we do this regardless of how many dots were in the
1813 * name or whether it ends with a dot.
1814 */
1815 if (!tried_as_is) {
1816 ret = res_querydomainN(name, NULL, target);
1817 if (ret > 0)
1818 return (ret);
1819 }
1820
1821 /*
1822 * if we got here, we didn't satisfy the search.
1823 * if we did an initial full query, return that query's h_errno
1824 * (note that we wouldn't be here if that query had succeeded).
1825 * else if we ever got a nodata, send that back as the reason.
1826 * else send back meaningless h_errno, that being the one from
1827 * the last DNSRCH we did.
1828 */
1829 if (saved_herrno != -1)
1830 h_errno = saved_herrno;
1831 else if (got_nodata)
1832 h_errno = NO_DATA;
1833 else if (got_servfail)
1834 h_errno = TRY_AGAIN;
1835 return (-1);
1836}
1837
1838/*
1839 * Perform a call on res_query on the concatenation of name and domain,
1840 * removing a trailing dot from name if domain is NULL.
1841 */
1842static int
1843res_querydomainN(name, domain, target)
1844 const char *name, *domain;
1845 struct res_target *target;
1846{
1847 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
1848 char nbuf[MAXDNAME];
1849 const char *longname = nbuf;
1850 size_t n, d;
1851
1852 if ((_resp->options & RES_INIT) == 0 && res_init() == -1) {
1853 h_errno = NETDB_INTERNAL;
1854 return (-1);
1855 }
1856#ifdef DEBUG
1857 if (_resp->options & RES_DEBUG)
1858 printf(";; res_querydomain(%s, %s)\n",
1859 name, domain?domain:"<Nil>");
1860#endif
1861 if (domain == NULL) {
1862 /*
1863 * Check for trailing '.';
1864 * copy without '.' if present.
1865 */
1866 n = strlen(name);
1867 if (n >= MAXDNAME) {
1868 h_errno = NO_RECOVERY;
1869 return (-1);
1870 }
1871 if (n > 0 && name[--n] == '.') {
1872 strlcpy(nbuf, name, n + 1);
1873 } else
1874 longname = name;
1875 } else {
1876 n = strlen(name);
1877 d = strlen(domain);
1878 if (n + d + 1 >= MAXDNAME) {
1879 h_errno = NO_RECOVERY;
1880 return (-1);
1881 }
1882 snprintf(nbuf, sizeof(nbuf), "%s.%s", name, domain);
1883 }
1884 return (res_queryN(longname, target));
1885}
diff --git a/src/lib/libc/net/gethostbyname.3 b/src/lib/libc/net/gethostbyname.3
new file mode 100644
index 0000000000..1a627f403b
--- /dev/null
+++ b/src/lib/libc/net/gethostbyname.3
@@ -0,0 +1,297 @@
1.\" $OpenBSD: gethostbyname.3,v 1.20 2003/06/30 16:54:53 millert 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. Neither the name of the University nor the names of its contributors
15.\" may be used to endorse or promote products derived from this software
16.\" without specific prior written permission.
17.\"
18.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28.\" SUCH DAMAGE.
29.\"
30.Dd March 13, 1997
31.Dt GETHOSTBYNAME 3
32.Os
33.Sh NAME
34.Nm gethostbyname ,
35.Nm gethostbyname2 ,
36.Nm gethostbyaddr ,
37.Nm gethostent ,
38.Nm sethostent ,
39.Nm endhostent ,
40.Nm hstrerror ,
41.Nm herror
42.Nd get network host entry
43.Sh SYNOPSIS
44.Fd #include <netdb.h>
45.Fd extern int h_errno;
46.Ft struct hostent *
47.Fn gethostbyname "const char *name"
48.Ft struct hostent *
49.Fn gethostbyname2 "const char *name" "int af"
50.Ft struct hostent *
51.Fn gethostbyaddr "const char *addr" "int len" "int af"
52.Ft struct hostent *
53.Fn gethostent void
54.Ft void
55.Fn sethostent "int stayopen"
56.Ft void
57.Fn endhostent void
58.Ft void
59.Fn herror "const char *string"
60.Ft const char *
61.Fn hstrerror "int err"
62.Sh DESCRIPTION
63The
64.Fn gethostbyname ,
65.Fn gethostbyname2
66and
67.Fn gethostbyaddr
68functions each return a pointer to an object with the following structure
69describing an internet host referenced by name or by address, respectively.
70This structure contains either information obtained from the name server (i.e.,
71.Xr resolver 3
72and
73.Xr named 8 ) ,
74broken-out fields from a line in
75.Pa /etc/hosts ,
76or database entries supplied by the
77.Xr yp 8
78system.
79.Xr resolv.conf 5
80describes how the particular database is chosen.
81.Bd -literal
82struct hostent {
83 char *h_name; /* official name of host */
84 char **h_aliases; /* alias list */
85 int h_addrtype; /* host address type */
86 int h_length; /* length of address */
87 char **h_addr_list; /* list of addresses from name server */
88};
89#define h_addr h_addr_list[0] /* address, for backward compatibility */
90.Ed
91.Pp
92The members of this structure are:
93.Bl -tag -width h_addr_list
94.It Fa h_name
95Official name of the host.
96.It Fa h_aliases
97A NULL-terminated array of alternate names for the host.
98.It Fa h_addrtype
99The type of address being returned.
100.It Fa h_length
101The length, in bytes, of the address.
102.It Fa h_addr_list
103A zero-terminated array of network addresses for the host.
104Host addresses are returned in network byte order.
105.It Fa h_addr
106The first address in
107.Fa h_addr_list ;
108this is for backward compatibility.
109.El
110.Pp
111The function
112.Fn gethostbyname
113will search for the named host in the current domain and its parents
114using the search lookup semantics detailed in
115.Xr resolv.conf 5
116and
117.Xr hostname 7 .
118.Pp
119.Fn gethostbyname2
120is an advanced form of
121.Fn gethostbyname
122which allows lookups in address families other than
123.Dv AF_INET .
124Currently, the only supported address family besides
125.Dv AF_INET
126is
127.Dv AF_INET6 .
128.Pp
129The
130.Fn gethostbyaddr
131function will search for the specified address of length
132.Fa len
133in the address family
134.Fa af .
135The only address family currently supported is
136.Dv AF_INET .
137.Pp
138The
139.Fn sethostent
140function may be used to request the use of a connected
141.Tn TCP
142socket for queries.
143If the
144.Fa stayopen
145flag is non-zero,
146this sets the option to send all queries to the name server using
147.Tn TCP
148and to retain the connection after each call to
149.Fn gethostbyname
150or
151.Fn gethostbyaddr .
152Otherwise, queries are performed using
153.Tn UDP
154datagrams.
155.Pp
156The
157.Fn endhostent
158function closes the
159.Tn TCP
160connection.
161.Pp
162The
163.Fn herror
164function prints an error message describing the failure.
165If its argument
166.Fa string
167is non-null,
168it is prepended to the message string and separated from it by a colon
169.Pq Ql \&:
170and a space.
171The error message is printed with a trailing newline.
172The contents of the error message is the same as that returned by
173.Fn hstrerror
174with argument
175.Fa h_errno .
176.Sh ENVIRONMENT
177.Bl -tag -width HOSTALIASES
178.It HOSTALIASES
179A file containing local host aliases.
180See
181.Xr hostname 7
182for more information.
183.It RES_OPTIONS
184A list of options to override the resolver's internal defaults.
185See
186.Xr resolver 3
187for more information.
188.El
189.Sh FILES
190.Bl -tag -width /etc/resolv.conf -compact
191.It Pa /etc/hosts
192.It Pa /etc/resolv.conf
193.El
194.Sh DIAGNOSTICS
195Error return status from
196.Fn gethostbyname ,
197.Fn gethostbyname2 ,
198and
199.Fn gethostbyaddr
200is indicated by return of a null pointer.
201The external integer
202.Va h_errno
203may then be checked to see whether this is a temporary failure
204or an invalid or unknown host.
205.Pp
206The variable
207.Va h_errno
208can have the following values:
209.Bl -tag -width HOST_NOT_FOUND
210.It Dv HOST_NOT_FOUND
211No such host is known.
212.It Dv TRY_AGAIN
213This is usually a temporary error
214and means that the local server did not receive
215a response from an authoritative server.
216A retry at some later time may succeed.
217.It Dv NO_RECOVERY
218Some unexpected server failure was encountered.
219This is a non-recoverable error.
220.It Dv NO_DATA
221The requested name is valid but does not have an IP address;
222this is not a temporary error.
223This means that the name is known to the name server but there is no address
224associated with this name.
225Another type of request to the name server using this domain name
226will result in an answer;
227for example, a mail-forwarder may be registered for this domain.
228.It Dv NETDB_INTERNAL
229An internal error occurred.
230This may occurs when an address family other than
231.It Dv AF_INET
232or
233.It Dv AF_INET6
234is specified or when a resource is unable to be allocated.
235the
236.It Dv NETDB_SUCCESS
237The function completed successfully.
238.El
239.Sh SEE ALSO
240.Xr getaddrinfo 3 ,
241.Xr getnameinfo 3 ,
242.Xr resolver 3 ,
243.Xr hosts 5 ,
244.Xr resolv.conf 5 ,
245.Xr hostname 7 ,
246.Xr named 8
247.Sh HISTORY
248The
249.Fn herror
250function appeared in
251.Bx 4.3 .
252The
253.Fn endhostent ,
254.Fn gethostbyaddr ,
255.Fn gethostbyname ,
256.Fn gethostent ,
257and
258.Fn sethostent
259functions appeared in
260.Bx 4.2 .
261.Sh CAVEATS
262If the search routines in
263.Xr resolv.conf 5
264decide to read the
265.Pa /etc/hosts
266file,
267.Fn gethostent
268and other functions will
269read the next line of the file,
270re-opening the file if necessary.
271.Pp
272The
273.Fn sethostent
274function opens and/or rewinds the file
275.Pa /etc/hosts .
276If the
277.Fa stayopen
278argument is non-zero, the file will not be closed after each call to
279.Fn gethostbyname ,
280.Fn gethostbyname2 ,
281or
282.Fn gethostbyaddr .
283.Pp
284The
285.Fn endhostent
286function closes the file.
287.Sh BUGS
288These functions use static data storage;
289if the data is needed for future use, it should be
290copied before any subsequent calls overwrite it.
291Only the Internet
292address formats are currently understood.
293.Pp
294YP does not support any address families other than
295.Dv AF_INET
296and uses
297the 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..ee4af36191
--- /dev/null
+++ b/src/lib/libc/net/gethostnamadr.c
@@ -0,0 +1,1148 @@
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. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 * -
29 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
30 *
31 * Permission to use, copy, modify, and distribute this software for any
32 * purpose with or without fee is hereby granted, provided that the above
33 * copyright notice and this permission notice appear in all copies, and that
34 * the name of Digital Equipment Corporation not be used in advertising or
35 * publicity pertaining to distribution of the document or software without
36 * specific, written prior permission.
37 *
38 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
39 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
40 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
41 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
42 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
43 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
44 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
45 * SOFTWARE.
46 * -
47 * --Copyright--
48 */
49
50#if defined(LIBC_SCCS) && !defined(lint)
51static const char rcsid[] = "$OpenBSD: gethostnamadr.c,v 1.59 2003/10/06 19:18:09 millert Exp $";
52#endif /* LIBC_SCCS and not lint */
53
54#include <sys/param.h>
55#include <sys/socket.h>
56#include <netinet/in.h>
57#include <arpa/inet.h>
58#include <arpa/nameser.h>
59#include <netdb.h>
60#include <resolv.h>
61#include <stdio.h>
62#include <ctype.h>
63#include <errno.h>
64#include <string.h>
65#include <syslog.h>
66#include <stdlib.h>
67#ifdef YP
68#include <rpc/rpc.h>
69#include <rpcsvc/yp.h>
70#include <rpcsvc/ypclnt.h>
71#include "ypinternal.h"
72#endif
73#include "thread_private.h"
74
75#define MULTI_PTRS_ARE_ALIASES 1 /* XXX - experimental */
76
77#define MAXALIASES 35
78#define MAXADDRS 35
79
80static char *h_addr_ptrs[MAXADDRS + 1];
81
82#ifdef YP
83static char *__ypdomain;
84#endif
85
86static struct hostent host;
87static char *host_aliases[MAXALIASES];
88static char hostbuf[BUFSIZ+1];
89static union {
90 struct in_addr _host_in_addr;
91 u_char _host_addr[16]; /* IPv4 or IPv6 */
92} _host_addr_u;
93#define host_addr _host_addr_u._host_addr
94static FILE *hostf = NULL;
95static int stayopen = 0;
96
97static void map_v4v6_address(const char *src, char *dst);
98static void map_v4v6_hostent(struct hostent *hp, char **bp, char *);
99
100#ifdef RESOLVSORT
101static void addrsort(char **, int);
102#endif
103
104int _hokchar(const char *);
105
106static const char AskedForGot[] =
107 "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
108
109#define MAXPACKET (64*1024)
110
111typedef union {
112 HEADER hdr;
113 u_char buf[MAXPACKET];
114} querybuf;
115
116typedef union {
117 int32_t al;
118 char ac;
119} align;
120
121static struct hostent *getanswer(const querybuf *, int, const char *, int);
122
123extern int h_errno;
124
125int
126_hokchar(const char *p)
127{
128 char c;
129
130 /*
131 * Many people do not obey RFC 822 and 1035. The valid
132 * characters are a-z, A-Z, 0-9, '-' and . But the others
133 * tested for below can happen, and we must be more permissive
134 * than the resolver until those idiots clean up their act.
135 * We let '/' through, but not '..'
136 */
137 while ((c = *p++)) {
138 if (('a' <= c && c <= 'z') ||
139 ('A' <= c && c <= 'Z') ||
140 ('0' <= c && c <= '9'))
141 continue;
142 if (strchr("-_/", c))
143 continue;
144 if (c == '.' && *p != '.')
145 continue;
146 return 0;
147 }
148 return 1;
149}
150
151static struct hostent *
152getanswer(const querybuf *answer, int anslen, const char *qname, int qtype)
153{
154 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
155 const HEADER *hp;
156 const u_char *cp, *eom;
157 char tbuf[MAXDNAME];
158 char *bp, **ap, **hap, *ep;
159 int type, class, ancount, qdcount, n;
160 int haveanswer, had_error, toobig = 0;
161 const char *tname;
162 int (*name_ok)(const char *);
163
164 tname = qname;
165 host.h_name = NULL;
166 eom = answer->buf + anslen;
167 switch (qtype) {
168 case T_A:
169 case T_AAAA:
170#ifdef USE_RESOLV_NAME_OK
171 name_ok = res_hnok;
172 break;
173#endif
174 case T_PTR:
175#ifdef USE_RESOLV_NAME_OK
176 name_ok = res_dnok;
177#else
178 name_ok = _hokchar;
179#endif
180 break;
181 default:
182 return (NULL);
183 }
184 /*
185 * find first satisfactory answer
186 */
187 hp = &answer->hdr;
188 ancount = ntohs(hp->ancount);
189 qdcount = ntohs(hp->qdcount);
190 bp = hostbuf;
191 ep = hostbuf + sizeof hostbuf;
192 cp = answer->buf + HFIXEDSZ;
193 if (qdcount != 1) {
194 h_errno = NO_RECOVERY;
195 return (NULL);
196 }
197 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
198 if ((n < 0) || !(*name_ok)(bp)) {
199 h_errno = NO_RECOVERY;
200 return (NULL);
201 }
202 cp += n + QFIXEDSZ;
203 if (qtype == T_A || qtype == T_AAAA) {
204 /* res_send() has already verified that the query name is the
205 * same as the one we sent; this just gets the expanded name
206 * (i.e., with the succeeding search-domain tacked on).
207 */
208 n = strlen(bp) + 1; /* for the \0 */
209 host.h_name = bp;
210 bp += n;
211 /* The qname can be abbreviated, but h_name is now absolute. */
212 qname = host.h_name;
213 }
214 ap = host_aliases;
215 *ap = NULL;
216 host.h_aliases = host_aliases;
217 hap = h_addr_ptrs;
218 *hap = NULL;
219 host.h_addr_list = h_addr_ptrs;
220 haveanswer = 0;
221 had_error = 0;
222 while (ancount-- > 0 && cp < eom && !had_error) {
223 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
224 if ((n < 0) || !(*name_ok)(bp)) {
225 had_error++;
226 continue;
227 }
228 cp += n; /* name */
229 if (cp >= eom)
230 break;
231 type = _getshort(cp);
232 cp += INT16SZ; /* type */
233 if (cp >= eom)
234 break;
235 class = _getshort(cp);
236 cp += INT16SZ + INT32SZ; /* class, TTL */
237 if (cp >= eom)
238 break;
239 n = _getshort(cp);
240 cp += INT16SZ; /* len */
241 if (cp >= eom)
242 break;
243 if (type == T_SIG) {
244 /* XXX - ignore signatures as we don't use them yet */
245 cp += n;
246 continue;
247 }
248 if (class != C_IN) {
249 /* XXX - debug? syslog? */
250 cp += n;
251 continue; /* XXX - had_error++ ? */
252 }
253 if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) {
254 if (ap >= &host_aliases[MAXALIASES-1])
255 continue;
256 n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
257 if ((n < 0) || !(*name_ok)(tbuf)) {
258 had_error++;
259 continue;
260 }
261 cp += n;
262 /* Store alias. */
263 *ap++ = bp;
264 n = strlen(bp) + 1; /* for the \0 */
265 bp += n;
266 /* Get canonical name. */
267 n = strlen(tbuf) + 1; /* for the \0 */
268 if (n > ep - bp) {
269 had_error++;
270 continue;
271 }
272 strlcpy(bp, tbuf, ep - bp);
273 host.h_name = bp;
274 bp += n;
275 continue;
276 }
277 if (qtype == T_PTR && type == T_CNAME) {
278 n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
279#ifdef USE_RESOLV_NAME_OK
280 if ((n < 0) || !res_hnok(tbuf)) {
281#else
282 if ((n < 0) || !_hokchar(tbuf)) {
283#endif
284 had_error++;
285 continue;
286 }
287 cp += n;
288 /* Get canonical name. */
289 n = strlen(tbuf) + 1; /* for the \0 */
290 if (n > ep - bp) {
291 had_error++;
292 continue;
293 }
294 strlcpy(bp, tbuf, ep - bp);
295 tname = bp;
296 bp += n;
297 continue;
298 }
299 if (type != qtype) {
300 syslog(LOG_NOTICE|LOG_AUTH,
301 "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
302 qname, p_class(C_IN), p_type(qtype),
303 p_type(type));
304 cp += n;
305 continue; /* XXX - had_error++ ? */
306 }
307 switch (type) {
308 case T_PTR:
309 if (strcasecmp(tname, bp) != 0) {
310 syslog(LOG_NOTICE|LOG_AUTH,
311 AskedForGot, qname, bp);
312 cp += n;
313 continue; /* XXX - had_error++ ? */
314 }
315 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
316#ifdef USE_RESOLV_NAME_OK
317 if ((n < 0) || !res_hnok(bp)) {
318#else
319 if ((n < 0) || !_hokchar(bp)) {
320#endif
321 had_error++;
322 break;
323 }
324#if MULTI_PTRS_ARE_ALIASES
325 cp += n;
326 if (!haveanswer)
327 host.h_name = bp;
328 else if (ap < &host_aliases[MAXALIASES-1])
329 *ap++ = bp;
330 else
331 n = -1;
332 if (n != -1) {
333 n = strlen(bp) + 1; /* for the \0 */
334 bp += n;
335 }
336 break;
337#else
338 host.h_name = bp;
339 if (_resp->options & RES_USE_INET6) {
340 n = strlen(bp) + 1; /* for the \0 */
341 bp += n;
342 map_v4v6_hostent(&host, &bp, ep);
343 }
344 h_errno = NETDB_SUCCESS;
345 return (&host);
346#endif
347 case T_A:
348 case T_AAAA:
349 if (strcasecmp(host.h_name, bp) != 0) {
350 syslog(LOG_NOTICE|LOG_AUTH,
351 AskedForGot, host.h_name, bp);
352 cp += n;
353 continue; /* XXX - had_error++ ? */
354 }
355 if (n != host.h_length) {
356 cp += n;
357 continue;
358 }
359 if (type == T_AAAA) {
360 struct in6_addr in6;
361 memcpy(&in6, cp, IN6ADDRSZ);
362 if (IN6_IS_ADDR_V4MAPPED(&in6)) {
363 cp += n;
364 continue;
365 }
366 }
367 if (!haveanswer) {
368 int nn;
369
370 host.h_name = bp;
371 nn = strlen(bp) + 1; /* for the \0 */
372 bp += nn;
373 }
374
375 bp += sizeof(align) - ((u_long)bp % sizeof(align));
376
377 if (bp + n >= &hostbuf[sizeof hostbuf]) {
378#ifdef DEBUG
379 if (_resp->options & RES_DEBUG)
380 printf("size (%d) too big\n", n);
381#endif
382 had_error++;
383 continue;
384 }
385 if (hap >= &h_addr_ptrs[MAXADDRS-1]) {
386 if (!toobig++)
387#ifdef DEBUG
388 if (_resp->options & RES_DEBUG)
389 printf("Too many addresses (%d)\n", MAXADDRS);
390#endif
391 cp += n;
392 continue;
393 }
394 bcopy(cp, *hap++ = bp, n);
395 bp += n;
396 cp += n;
397 break;
398 }
399 if (!had_error)
400 haveanswer++;
401 }
402 if (haveanswer) {
403 *ap = NULL;
404 *hap = NULL;
405# if defined(RESOLVSORT)
406 /*
407 * Note: we sort even if host can take only one address
408 * in its return structures - should give it the "best"
409 * address in that case, not some random one
410 */
411 if (_resp->nsort && haveanswer > 1 && qtype == T_A)
412 addrsort(h_addr_ptrs, haveanswer);
413# endif /*RESOLVSORT*/
414 if (!host.h_name) {
415 n = strlen(qname) + 1; /* for the \0 */
416 if (n > ep - bp)
417 goto try_again;
418 strlcpy(bp, qname, ep - bp);
419 host.h_name = bp;
420 bp += n;
421 }
422 if (_resp->options & RES_USE_INET6)
423 map_v4v6_hostent(&host, &bp, ep);
424 h_errno = NETDB_SUCCESS;
425 return (&host);
426 }
427 try_again:
428 h_errno = TRY_AGAIN;
429 return (NULL);
430}
431
432#ifdef notyet
433/*
434 * XXX This is an extremely bogus implementation.
435 *
436 * FreeBSD has this interface:
437 * int gethostbyaddr_r(const char *addr, int len, int type,
438 * struct hostent *result, struct hostent_data *buffer)
439 */
440
441struct hostent *
442gethostbyname_r(const char *name, struct hostent *hp, char *buf, int buflen,
443 int *errorp)
444{
445 struct hostent *res;
446
447 res = gethostbyname(name);
448 *errorp = h_errno;
449 if (res == NULL)
450 return NULL;
451 memcpy(hp, res, sizeof *hp); /* XXX not sufficient */
452 return hp;
453}
454
455/*
456 * XXX This is an extremely bogus implementation.
457 */
458struct hostent *
459gethostbyaddr_r(const char *addr, int len, int af, struct hostent *he,
460 char *buf, int buflen, int *errorp)
461{
462 struct hostent * res;
463
464 res = gethostbyaddr(addr, len, af);
465 *errorp = h_errno;
466 if (res == NULL)
467 return NULL;
468 memcpy(he, res, sizeof *he); /* XXX not sufficient */
469 return he;
470}
471
472/* XXX RFC2133 expects a gethostbyname2_r() -- unimplemented */
473#endif
474
475struct hostent *
476gethostbyname(const char *name)
477{
478 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
479 struct hostent *hp;
480 extern struct hostent *_gethtbyname2(const char *, int);
481
482 if ((_resp->options & RES_INIT) == 0 && res_init() == -1)
483 hp = _gethtbyname2(name, AF_INET);
484
485 else if (_resp->options & RES_USE_INET6) {
486 hp = gethostbyname2(name, AF_INET6);
487 if (hp == NULL)
488 hp = gethostbyname2(name, AF_INET);
489 }
490 else
491 hp = gethostbyname2(name, AF_INET);
492 return hp;
493}
494
495struct hostent *
496gethostbyname2(const char *name, int af)
497{
498 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
499 querybuf *buf;
500 const char *cp;
501 char *bp, *ep;
502 int n, size, type, i;
503 struct hostent *hp;
504 char lookups[MAXDNSLUS];
505 extern struct hostent *_gethtbyname2(const char *, int);
506 extern struct hostent *_yp_gethtbyname(const char *);
507
508 if ((_resp->options & RES_INIT) == 0 && res_init() == -1)
509 return (_gethtbyname2(name, af));
510
511 switch (af) {
512 case AF_INET:
513 size = INADDRSZ;
514 type = T_A;
515 break;
516 case AF_INET6:
517 size = IN6ADDRSZ;
518 type = T_AAAA;
519 break;
520 default:
521 h_errno = NETDB_INTERNAL;
522 errno = EAFNOSUPPORT;
523 return (NULL);
524 }
525
526 host.h_addrtype = af;
527 host.h_length = size;
528
529 /*
530 * if there aren't any dots, it could be a user-level alias.
531 * this is also done in res_query() since we are not the only
532 * function that looks up host names.
533 */
534 if (!strchr(name, '.') && (cp = __hostalias(name)))
535 name = cp;
536
537 /*
538 * disallow names consisting only of digits/dots, unless
539 * they end in a dot.
540 */
541 if (isdigit(name[0]))
542 for (cp = name;; ++cp) {
543 if (!*cp) {
544 if (*--cp == '.')
545 break;
546 /*
547 * All-numeric, no dot at the end.
548 * Fake up a hostent as if we'd actually
549 * done a lookup.
550 */
551 if (inet_pton(af, name, host_addr) <= 0) {
552 h_errno = HOST_NOT_FOUND;
553 return (NULL);
554 }
555 strlcpy(hostbuf, name, MAXHOSTNAMELEN);
556 bp = hostbuf + MAXHOSTNAMELEN;
557 ep = hostbuf + sizeof(hostbuf);
558 host.h_name = hostbuf;
559 host.h_aliases = host_aliases;
560 host_aliases[0] = NULL;
561 h_addr_ptrs[0] = (char *)host_addr;
562 h_addr_ptrs[1] = NULL;
563 host.h_addr_list = h_addr_ptrs;
564 if (_resp->options & RES_USE_INET6)
565 map_v4v6_hostent(&host, &bp, ep);
566 h_errno = NETDB_SUCCESS;
567 return (&host);
568 }
569 if (!isdigit(*cp) && *cp != '.')
570 break;
571 }
572 if ((isxdigit(name[0]) && strchr(name, ':') != NULL) ||
573 name[0] == ':')
574 for (cp = name;; ++cp) {
575 if (!*cp) {
576 if (*--cp == '.')
577 break;
578 /*
579 * All-IPv6-legal, no dot at the end.
580 * Fake up a hostent as if we'd actually
581 * done a lookup.
582 */
583 if (inet_pton(af, name, host_addr) <= 0) {
584 h_errno = HOST_NOT_FOUND;
585 return (NULL);
586 }
587 strlcpy(hostbuf, name, MAXHOSTNAMELEN);
588 bp = hostbuf + MAXHOSTNAMELEN;
589 ep = hostbuf + sizeof(hostbuf);
590 host.h_name = hostbuf;
591 host.h_aliases = host_aliases;
592 host_aliases[0] = NULL;
593 h_addr_ptrs[0] = (char *)host_addr;
594 h_addr_ptrs[1] = NULL;
595 host.h_addr_list = h_addr_ptrs;
596 h_errno = NETDB_SUCCESS;
597 return (&host);
598 }
599 if (!isxdigit(*cp) && *cp != ':' && *cp != '.')
600 break;
601 }
602
603 bcopy(_resp->lookups, lookups, sizeof lookups);
604 if (lookups[0] == '\0')
605 strlcpy(lookups, "bf", sizeof lookups);
606
607 hp = (struct hostent *)NULL;
608 for (i = 0; i < MAXDNSLUS && hp == NULL && lookups[i]; i++) {
609 switch (lookups[i]) {
610#ifdef YP
611 case 'y':
612 /* YP only supports AF_INET. */
613 if (af == AF_INET)
614 hp = _yp_gethtbyname(name);
615 break;
616#endif
617 case 'b':
618 buf = malloc(sizeof(*buf));
619 if (buf == NULL)
620 break;
621 if ((n = res_search(name, C_IN, type, buf->buf,
622 sizeof(buf->buf))) < 0) {
623 free(buf);
624#ifdef DEBUG
625 if (_resp->options & RES_DEBUG)
626 printf("res_search failed\n");
627#endif
628 break;
629 }
630 hp = getanswer(buf, n, name, type);
631 free(buf);
632 break;
633 case 'f':
634 hp = _gethtbyname2(name, af);
635 break;
636 }
637 }
638 /* XXX h_errno not correct in all cases... */
639 return (hp);
640}
641
642struct hostent *
643gethostbyaddr(const char *addr, int len, int af)
644{
645 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
646 const u_char *uaddr = (const u_char *)addr;
647 int n, size, i;
648 querybuf *buf;
649 struct hostent *hp;
650 char qbuf[MAXDNAME+1], *qp, *ep;
651 char lookups[MAXDNSLUS];
652 struct hostent *res;
653 extern struct hostent *_gethtbyaddr(const char *, int, int);
654 extern struct hostent *_yp_gethtbyaddr(const char *);
655
656 if ((_resp->options & RES_INIT) == 0 && res_init() == -1) {
657 res = _gethtbyaddr(addr, len, af);
658 return (res);
659 }
660
661 if (af == AF_INET6 && len == IN6ADDRSZ &&
662 (IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)uaddr) ||
663 IN6_IS_ADDR_SITELOCAL((struct in6_addr *)uaddr))) {
664 h_errno = HOST_NOT_FOUND;
665 return (NULL);
666 }
667 if (af == AF_INET6 && len == IN6ADDRSZ &&
668 (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)uaddr) ||
669 IN6_IS_ADDR_V4COMPAT((struct in6_addr *)uaddr))) {
670 /* Unmap. */
671 addr += IN6ADDRSZ - INADDRSZ;
672 uaddr += IN6ADDRSZ - INADDRSZ;
673 af = AF_INET;
674 len = INADDRSZ;
675 }
676 switch (af) {
677 case AF_INET:
678 size = INADDRSZ;
679 break;
680 case AF_INET6:
681 size = IN6ADDRSZ;
682 break;
683 default:
684 errno = EAFNOSUPPORT;
685 h_errno = NETDB_INTERNAL;
686 return (NULL);
687 }
688 if (size != len) {
689 errno = EINVAL;
690 h_errno = NETDB_INTERNAL;
691 return (NULL);
692 }
693 ep = qbuf + sizeof(qbuf);
694 switch (af) {
695 case AF_INET:
696 (void) snprintf(qbuf, sizeof qbuf, "%u.%u.%u.%u.in-addr.arpa",
697 (uaddr[3] & 0xff), (uaddr[2] & 0xff),
698 (uaddr[1] & 0xff), (uaddr[0] & 0xff));
699 break;
700 case AF_INET6:
701 qp = qbuf;
702 for (n = IN6ADDRSZ - 1; n >= 0; n--) {
703 i = snprintf(qp, ep - qp, "%x.%x.",
704 uaddr[n] & 0xf, (uaddr[n] >> 4) & 0xf);
705 if (i <= 0) {
706 errno = EINVAL;
707 h_errno = NETDB_INTERNAL;
708 return (NULL);
709 }
710 qp += i;
711 }
712 break;
713 }
714
715 bcopy(_resp->lookups, lookups, sizeof lookups);
716 if (lookups[0] == '\0')
717 strlcpy(lookups, "bf", sizeof lookups);
718
719 hp = (struct hostent *)NULL;
720 for (i = 0; i < MAXDNSLUS && hp == NULL && lookups[i]; i++) {
721 switch (lookups[i]) {
722#ifdef YP
723 case 'y':
724 /* YP only supports AF_INET. */
725 if (af == AF_INET)
726 hp = _yp_gethtbyaddr(addr);
727 break;
728#endif
729 case 'b':
730 if (af == AF_INET6)
731 strlcpy(qp, "ip6.arpa", ep - qp);
732 buf = malloc(sizeof(*buf));
733 if (!buf)
734 break;
735 n = res_query(qbuf, C_IN, T_PTR, buf->buf,
736 sizeof(buf->buf));
737 if (n < 0 && af == AF_INET6) {
738 strlcpy(qp, "ip6.int", ep - qp);
739 n = res_query(qbuf, C_IN, T_PTR,
740 buf->buf, sizeof(buf->buf));
741 }
742 if (n < 0) {
743 free(buf);
744#ifdef DEBUG
745 if (_resp->options & RES_DEBUG)
746 printf("res_query failed\n");
747#endif
748 break;
749 }
750 if (!(hp = getanswer(buf, n, qbuf, T_PTR))) {
751 free(buf);
752 break;
753 }
754 free(buf);
755 hp->h_addrtype = af;
756 hp->h_length = len;
757 bcopy(addr, host_addr, len);
758 h_addr_ptrs[0] = (char *)host_addr;
759 h_addr_ptrs[1] = NULL;
760 if (af == AF_INET && (_resp->options & RES_USE_INET6)) {
761 map_v4v6_address((char*)host_addr,
762 (char*)host_addr);
763 hp->h_addrtype = AF_INET6;
764 hp->h_length = IN6ADDRSZ;
765 }
766 h_errno = NETDB_SUCCESS;
767 break;
768 case 'f':
769 hp = _gethtbyaddr(addr, len, af);
770 break;
771 }
772 }
773 /* XXX h_errno not correct in all cases... */
774 return (hp);
775}
776
777void
778_sethtent(int f)
779{
780 if (hostf == NULL)
781 hostf = fopen(_PATH_HOSTS, "r" );
782 else
783 rewind(hostf);
784 stayopen = f;
785}
786
787void
788_endhtent(void)
789{
790 if (hostf && !stayopen) {
791 (void) fclose(hostf);
792 hostf = NULL;
793 }
794}
795
796struct hostent *
797_gethtent(void)
798{
799 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
800 char *p, *cp, **q;
801 int af;
802 size_t len;
803
804 if (!hostf && !(hostf = fopen(_PATH_HOSTS, "r" ))) {
805 h_errno = NETDB_INTERNAL;
806 return (NULL);
807 }
808 again:
809 if ((p = fgetln(hostf, &len)) == NULL) {
810 h_errno = HOST_NOT_FOUND;
811 return (NULL);
812 }
813 if (p[len-1] == '\n')
814 len--;
815 if (len >= sizeof(hostbuf) || len == 0)
816 goto again;
817 p = memcpy(hostbuf, p, len);
818 hostbuf[len] = '\0';
819 if (*p == '#')
820 goto again;
821 if ((cp = strchr(p, '#')))
822 *cp = '\0';
823 if (!(cp = strpbrk(p, " \t")))
824 goto again;
825 *cp++ = '\0';
826 if (inet_pton(AF_INET6, p, host_addr) > 0) {
827 af = AF_INET6;
828 len = IN6ADDRSZ;
829 } else if (inet_pton(AF_INET, p, host_addr) > 0) {
830 if (_resp->options & RES_USE_INET6) {
831 map_v4v6_address((char*)host_addr, (char*)host_addr);
832 af = AF_INET6;
833 len = IN6ADDRSZ;
834 } else {
835 af = AF_INET;
836 len = INADDRSZ;
837 }
838 } else {
839 goto again;
840 }
841 /* if this is not something we're looking for, skip it. */
842 if (host.h_addrtype != af)
843 goto again;
844 if (host.h_length != len)
845 goto again;
846 h_addr_ptrs[0] = (char *)host_addr;
847 h_addr_ptrs[1] = NULL;
848 host.h_addr_list = h_addr_ptrs;
849 host.h_length = len;
850 host.h_addrtype = af;
851 while (*cp == ' ' || *cp == '\t')
852 cp++;
853 host.h_name = cp;
854 q = host.h_aliases = host_aliases;
855 if ((cp = strpbrk(cp, " \t")))
856 *cp++ = '\0';
857 while (cp && *cp) {
858 if (*cp == ' ' || *cp == '\t') {
859 cp++;
860 continue;
861 }
862 if (q < &host_aliases[MAXALIASES - 1])
863 *q++ = cp;
864 if ((cp = strpbrk(cp, " \t")))
865 *cp++ = '\0';
866 }
867 *q = NULL;
868 if (_resp->options & RES_USE_INET6) {
869 char *bp = hostbuf;
870 char *ep = hostbuf + sizeof hostbuf;
871
872 map_v4v6_hostent(&host, &bp, ep);
873 }
874 h_errno = NETDB_SUCCESS;
875 return (&host);
876}
877
878struct hostent *
879_gethtbyname(const char *name)
880{
881 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
882 struct hostent *hp;
883 extern struct hostent *_gethtbyname2(const char *, int);
884
885 if (_resp->options & RES_USE_INET6) {
886 hp = _gethtbyname2(name, AF_INET6);
887 if (hp)
888 return (hp);
889 }
890 return (_gethtbyname2(name, AF_INET));
891}
892
893struct hostent *
894_gethtbyname2(const char *name, int af)
895{
896 struct hostent *p;
897 char **cp;
898
899 _sethtent(0);
900 while ((p = _gethtent())) {
901 if (p->h_addrtype != af)
902 continue;
903 if (strcasecmp(p->h_name, name) == 0)
904 break;
905 for (cp = p->h_aliases; *cp != 0; cp++)
906 if (strcasecmp(*cp, name) == 0)
907 goto found;
908 }
909 found:
910 _endhtent();
911 return (p);
912}
913
914struct hostent *
915_gethtbyaddr(const char *addr, int len, int af)
916{
917 struct hostent *p;
918
919 host.h_length = len;
920 host.h_addrtype = af;
921
922 _sethtent(0);
923 while ((p = _gethtent()))
924 if (p->h_addrtype == af && !bcmp(p->h_addr, addr, len))
925 break;
926 _endhtent();
927 return (p);
928}
929
930#ifdef YP
931struct hostent *
932_yphostent(char *line)
933{
934 static struct in_addr host_addrs[MAXADDRS];
935 char *p = line;
936 char *cp, **q;
937 char **hap;
938 struct in_addr *buf;
939 int more;
940
941 host.h_name = NULL;
942 host.h_addr_list = h_addr_ptrs;
943 host.h_length = INADDRSZ;
944 host.h_addrtype = AF_INET;
945 hap = h_addr_ptrs;
946 buf = host_addrs;
947 q = host.h_aliases = host_aliases;
948
949nextline:
950 /* check for host_addrs overflow */
951 if (buf >= &host_addrs[sizeof(host_addrs) / sizeof(host_addrs[0])])
952 goto done;
953
954 more = 0;
955 cp = strpbrk(p, " \t");
956 if (cp == NULL)
957 goto done;
958 *cp++ = '\0';
959
960 *hap++ = (char *)buf;
961 (void) inet_aton(p, buf++);
962
963 while (*cp == ' ' || *cp == '\t')
964 cp++;
965 p = cp;
966 cp = strpbrk(p, " \t\n");
967 if (cp != NULL) {
968 if (*cp == '\n')
969 more = 1;
970 *cp++ = '\0';
971 }
972 if (!host.h_name)
973 host.h_name = p;
974 else if (strcmp(host.h_name, p)==0)
975 ;
976 else if (q < &host_aliases[MAXALIASES - 1])
977 *q++ = p;
978 p = cp;
979 if (more)
980 goto nextline;
981
982 while (cp && *cp) {
983 if (*cp == ' ' || *cp == '\t') {
984 cp++;
985 continue;
986 }
987 if (*cp == '\n') {
988 cp++;
989 goto nextline;
990 }
991 if (q < &host_aliases[MAXALIASES - 1])
992 *q++ = cp;
993 cp = strpbrk(cp, " \t");
994 if (cp != NULL)
995 *cp++ = '\0';
996 }
997done:
998 if (host.h_name == NULL)
999 return (NULL);
1000 *q = NULL;
1001 *hap = NULL;
1002 return (&host);
1003}
1004
1005struct hostent *
1006_yp_gethtbyaddr(const char *addr)
1007{
1008 struct hostent *hp = (struct hostent *)NULL;
1009 static char *__ypcurrent;
1010 int __ypcurrentlen, r;
1011 char name[sizeof("xxx.xxx.xxx.xxx")];
1012
1013 if (!__ypdomain) {
1014 if (_yp_check(&__ypdomain) == 0)
1015 return (hp);
1016 }
1017 snprintf(name, sizeof name, "%u.%u.%u.%u",
1018 ((unsigned)addr[0] & 0xff), ((unsigned)addr[1] & 0xff),
1019 ((unsigned)addr[2] & 0xff), ((unsigned)addr[3] & 0xff));
1020 if (__ypcurrent)
1021 free(__ypcurrent);
1022 __ypcurrent = NULL;
1023 r = yp_match(__ypdomain, "hosts.byaddr", name,
1024 strlen(name), &__ypcurrent, &__ypcurrentlen);
1025 if (r==0)
1026 hp = _yphostent(__ypcurrent);
1027 if (hp==NULL)
1028 h_errno = HOST_NOT_FOUND;
1029 return (hp);
1030}
1031
1032struct hostent *
1033_yp_gethtbyname(const char *name)
1034{
1035 struct hostent *hp = (struct hostent *)NULL;
1036 static char *__ypcurrent;
1037 int __ypcurrentlen, r;
1038
1039 if (strlen(name) >= MAXHOSTNAMELEN)
1040 return (NULL);
1041 if (!__ypdomain) {
1042 if (_yp_check(&__ypdomain) == 0)
1043 return (hp);
1044 }
1045 if (__ypcurrent)
1046 free(__ypcurrent);
1047 __ypcurrent = NULL;
1048 r = yp_match(__ypdomain, "hosts.byname", name,
1049 strlen(name), &__ypcurrent, &__ypcurrentlen);
1050 if (r == 0)
1051 hp = _yphostent(__ypcurrent);
1052 if (hp == NULL)
1053 h_errno = HOST_NOT_FOUND;
1054 return (hp);
1055}
1056#endif
1057
1058static void
1059map_v4v6_address(const char *src, char *dst)
1060{
1061 u_char *p = (u_char *)dst;
1062 char tmp[INADDRSZ];
1063 int i;
1064
1065 /* Stash a temporary copy so our caller can update in place. */
1066 bcopy(src, tmp, INADDRSZ);
1067 /* Mark this ipv6 addr as a mapped ipv4. */
1068 for (i = 0; i < 10; i++)
1069 *p++ = 0x00;
1070 *p++ = 0xff;
1071 *p++ = 0xff;
1072 /* Retrieve the saved copy and we're done. */
1073 bcopy(tmp, (void*)p, INADDRSZ);
1074}
1075
1076static void
1077map_v4v6_hostent(struct hostent *hp, char **bpp, char *ep)
1078{
1079 char **ap;
1080
1081 if (hp->h_addrtype != AF_INET || hp->h_length != INADDRSZ)
1082 return;
1083 hp->h_addrtype = AF_INET6;
1084 hp->h_length = IN6ADDRSZ;
1085 for (ap = hp->h_addr_list; *ap; ap++) {
1086 int i = sizeof(align) - ((u_long)*bpp % sizeof(align));
1087
1088 if (ep - *bpp < (i + IN6ADDRSZ)) {
1089 /* Out of memory. Truncate address list here. XXX */
1090 *ap = NULL;
1091 return;
1092 }
1093 *bpp += i;
1094 map_v4v6_address(*ap, *bpp);
1095 *ap = *bpp;
1096 *bpp += IN6ADDRSZ;
1097 }
1098}
1099
1100struct hostent *
1101gethostent(void)
1102{
1103 return (_gethtent());
1104}
1105
1106#ifdef RESOLVSORT
1107static void
1108addrsort(char **ap, int num)
1109{
1110 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
1111 int i, j;
1112 char **p;
1113 short aval[MAXADDRS];
1114 int needsort = 0;
1115
1116 p = ap;
1117 for (i = 0; i < num; i++, p++) {
1118 for (j = 0 ; (unsigned)j < _resp->nsort; j++)
1119 if (_resp->sort_list[j].addr.s_addr ==
1120 (((struct in_addr *)(*p))->s_addr &
1121 _resp->sort_list[j].mask))
1122 break;
1123 aval[i] = j;
1124 if (needsort == 0 && i > 0 && j < aval[i-1])
1125 needsort = i;
1126 }
1127 if (!needsort)
1128 return;
1129
1130 while (needsort < num) {
1131 for (j = needsort - 1; j >= 0; j--) {
1132 if (aval[j] > aval[j+1]) {
1133 char *hp;
1134
1135 i = aval[j];
1136 aval[j] = aval[j+1];
1137 aval[j+1] = i;
1138
1139 hp = ap[j];
1140 ap[j] = ap[j+1];
1141 ap[j+1] = hp;
1142 } else
1143 break;
1144 }
1145 needsort++;
1146 }
1147}
1148#endif
diff --git a/src/lib/libc/net/getifaddrs.3 b/src/lib/libc/net/getifaddrs.3
new file mode 100644
index 0000000000..9287b3b734
--- /dev/null
+++ b/src/lib/libc/net/getifaddrs.3
@@ -0,0 +1,159 @@
1.\" $OpenBSD: getifaddrs.3,v 1.10 2003/05/30 21:37:59 jmc 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 SEE ALSO
137.Xr ioctl 2 ,
138.Xr socket 2 ,
139.Xr sysctl 3 ,
140.Xr networking 4 ,
141.Xr ifconfig 8
142.Sh HISTORY
143The
144.Fn getifaddrs
145function first appeared in BSDI BSD/OS.
146The function is supplied on
147.Ox
148since
149.Ox 2.7 .
150.Sh BUGS
151If both
152.Aq Pa net/if.h
153and
154.Aq Pa ifaddrs.h
155are being included,
156.Aq Pa net/if.h
157.Em must
158be included before
159.Aq Pa ifaddrs.h .
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..3b3a0fd290
--- /dev/null
+++ b/src/lib/libc/net/getnameinfo.3
@@ -0,0 +1,348 @@
1.\" $OpenBSD: getnameinfo.3,v 1.27 2003/08/28 10:16:38 jmc 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. Neither the name of the University 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 REGENTS 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 REGENTS 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.\" From: @(#)gethostbyname.3 8.4 (Berkeley) 5/25/95
32.\"
33.Dd May 25, 1995
34.Dt GETNAMEINFO 3
35.Os
36.\"
37.Sh NAME
38.Nm getnameinfo
39.Nd address-to-nodename translation in protocol-independent manner
40.\"
41.Sh SYNOPSIS
42.Fd #include <sys/types.h>
43.Fd #include <sys/socket.h>
44.Fd #include <netdb.h>
45.Ft int
46.Fn getnameinfo "const struct sockaddr *sa" "socklen_t salen" \
47"char *host" "size_t hostlen" "char *serv" "size_t servlen" "int flags"
48.\"
49.Sh DESCRIPTION
50The
51.Fn getnameinfo
52function is defined for protocol-independent address-to-nodename translation.
53Its functionality is a reverse conversion of
54.Xr getaddrinfo 3 ,
55and implements similar functionality to
56.Xr gethostbyaddr 3
57and
58.Xr getservbyport 3
59in a more sophisticated manner.
60.Pp
61This function looks up an IP address and port number provided by the
62caller in the DNS and system-specific database, and returns text
63strings for both in buffers provided by the caller.
64The function indicates successful completion by a zero return value;
65a non-zero return value indicates failure.
66.Pp
67The first argument,
68.Fa sa ,
69points to either a
70.Li sockaddr_in
71structure (for IPv4) or a
72.Li sockaddr_in6
73structure (for IPv6) that holds the IP address and port number.
74The
75.Fa salen
76argument gives the length of the
77.Li sockaddr_in
78or
79.Li sockaddr_in6
80structure.
81.Pp
82The function returns the nodename associated with the IP address in
83the buffer pointed to by the
84.Fa host
85argument.
86The caller provides the size of this buffer via the
87.Fa hostlen
88argument.
89The service name associated with the port number is returned in the buffer
90pointed to by
91.Fa serv ,
92and the
93.Fa servlen
94argument gives the length of this buffer.
95The caller specifies not to return either string by providing a zero
96value for the
97.Fa hostlen
98or
99.Fa servlen
100arguments.
101Otherwise, the caller must provide buffers large enough to hold the
102nodename and the service name, including the terminating null characters.
103.Pp
104Unfortunately most systems do not provide constants that specify the
105maximum size of either a fully-qualified domain name or a service name.
106Therefore to aid the application in allocating buffers for these two
107returned strings the following constants are defined in
108.Aq Pa netdb.h :
109.Bd -literal -offset
110#define NI_MAXHOST MAXHOSTNAMELEN
111#define NI_MAXSERV 32
112.Ed
113.Pp
114The first value is actually defined as the constant
115.Dv MAXDNAME
116in recent versions of BIND's
117.Aq Pa arpa/nameser.h
118header (older versions of BIND define this constant to be 256)
119and the second is a guess based on the services listed in the current
120Assigned Numbers RFC.
121.Pp
122The final argument is a
123.Fa flag
124that changes the default actions of this function.
125By default the fully-qualified domain name (FQDN) for the host is
126looked up in the DNS and returned.
127If the flag bit
128.Dv NI_NOFQDN
129is set, only the nodename portion of the FQDN is returned for local hosts.
130.Pp
131If the
132.Fa flag
133bit
134.Dv NI_NUMERICHOST
135is set, or if the host's name cannot be located in the DNS,
136the numeric form of the host's address is returned instead of its name
137.Po
138e.g., by calling
139.Fn inet_ntop
140instead of
141.Fn gethostbyaddr
142.Pc .
143If the
144.Fa flag
145bit
146.Dv NI_NAMEREQD
147is set, an error is returned if the host's name cannot be located in the DNS.
148.Pp
149If the flag bit
150.Dv NI_NUMERICSERV
151is set, the numeric form of the service address is returned
152.Pq e.g., its port number
153instead of its name.
154The two
155.Dv NI_NUMERICxxx
156flags are required to support the
157.Fl n
158flag that many commands provide.
159.Pp
160A fifth flag bit,
161.Dv NI_DGRAM ,
162specifies that the service is a datagram service, and causes
163.Fn getservbyport
164to be called with a second argument of
165.Qq udp
166instead of its default of
167.Qq tcp .
168This is required for the few ports (512-514)
169that have different services for UDP and TCP.
170.Pp
171These
172.Dv NI_xxx
173flags are defined in
174.Aq Pa netdb.h .
175.\"
176.Ss Extension for scoped IPv6 address
177The implementation allows experimental numeric IPv6 address notation with
178scope identifier.
179IPv6 link-local address will appear as a string like
180.Dq Li fe80::1%ne0 .
181Refer to
182.Xr getaddrinfo 3
183for the notation.
184.\"
185.Sh EXAMPLES
186The following code tries to get a numeric hostname, and service name,
187for given socket address.
188Observe that there is no hardcoded reference to a particular address family.
189.Bd -literal -offset indent
190struct sockaddr *sa; /* input */
191char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
192
193if (getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf), sbuf,
194 sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV)) {
195 errx(1, "could not get numeric hostname");
196 /*NOTREACHED*/
197}
198printf("host=%s, serv=%s\en", hbuf, sbuf);
199.Ed
200.Pp
201The following version checks if the socket address has reverse address mapping.
202.Bd -literal -offset indent
203struct sockaddr *sa; /* input */
204char hbuf[NI_MAXHOST];
205
206if (getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf), NULL, 0,
207 NI_NAMEREQD)) {
208 errx(1, "could not resolve hostname");
209 /*NOTREACHED*/
210}
211printf("host=%s\en", hbuf);
212.Ed
213.\"
214.Sh DIAGNOSTICS
215The function indicates successful completion by a zero return value;
216a non-zero return value indicates failure.
217Error codes are as below:
218.Bl -tag -width Er
219.It Dv EAI_AGAIN
220The name could not be resolved at this time.
221Future attempts may succeed.
222.It Dv EAI_BADFLAGS
223The flags had an invalid value.
224.It Dv EAI_FAIL
225A non-recoverable error occurred.
226.It Dv EAI_FAMILY
227The address family was not recognized or the address length was invalid
228for the specified family.
229.It Dv EAI_MEMORY
230There was a memory allocation failure.
231.It Dv EAI_NONAME
232The name does not resolve for the supplied parameters.
233.Dv NI_NAMEREQD
234is set and the host's name cannot be located,
235or both nodename and servname were null.
236.It Dv EAI_SYSTEM
237A system error occurred.
238The error code can be found in errno.
239.El
240.\"
241.Sh SEE ALSO
242.Xr getaddrinfo 3 ,
243.Xr gethostbyaddr 3 ,
244.Xr getservbyport 3 ,
245.Xr hosts 5 ,
246.Xr resolv.conf 5 ,
247.Xr services 5 ,
248.Xr hostname 7 ,
249.Xr named 8
250.Rs
251.%A R. Gilligan
252.%A S. Thomson
253.%A J. Bound
254.%A W. Stevens
255.%T Basic Socket Interface Extensions for IPv6
256.%R RFC 2553
257.%D March 1999
258.Re
259.Rs
260.%A Tatsuya Jinmei
261.%A Atsushi Onoe
262.%T "An Extension of Format for IPv6 Scoped Addresses"
263.%R internet draft
264.%N draft-ietf-ipngwg-scopedaddr-format-02.txt
265.%O work in progress material
266.Re
267.Rs
268.%A Craig Metz
269.%T Protocol Independence Using the Sockets API
270.%B "Proceedings of the freenix track: 2000 USENIX annual technical conference"
271.%D June 2000
272.Re
273.\"
274.Sh STANDARDS
275The
276.Fn getnameinfo
277function is defined in IEEE POSIX 1003.1g draft specification,
278and documented in
279.Dq Basic Socket Interface Extensions for IPv6
280.Pq RFC 2553 .
281.\"
282.Sh HISTORY
283The implementation first appeared in WIDE Hydrangea IPv6 protocol stack kit.
284.\"
285.Sh CAVEATS
286.Fn getnameinfo
287returns both numeric and FQDN notation of the address specified in
288.Fa sa .
289There is no return value that indicates if the string returned in
290.Fa host
291is a result of binary to numeric-text translation (like
292.Xr inet_ntop 3 ) ,
293or the result of DNS reverse lookup.
294Therefore, malicious parties could set up a PTR record as below:
295.Bd -literal -offset indent
2961.0.0.127.in-addr.arpa. IN PTR 10.1.1.1
297.Ed
298.Pp
299and trick the caller of
300.Fn getnameinfo
301into believing that
302.Fa sa
303is
304.Li 10.1.1.1
305when it actually is
306.Li 127.0.0.1 .
307.Pp
308To prevent such attacks, the use of
309.Dv NI_NAMEREQD
310is recommended when you use the result of
311.Fn getnameinfo
312for access control purposes:
313.Bd -literal -offset indent
314struct sockaddr *sa;
315socklen_t salen;
316char addr[NI_MAXHOST];
317struct addrinfo hints, *res;
318int error;
319
320error = getnameinfo(sa, salen, addr, sizeof(addr),
321 NULL, 0, NI_NAMEREQD);
322if (error == 0) {
323 memset(&hints, 0, sizeof(hints));
324 hints.ai_socktype = SOCK_DGRAM; /*dummy*/
325 hints.ai_flags = AI_NUMERICHOST;
326 if (getaddrinfo(addr, "0", &hints, &res) == 0) {
327 /* malicious PTR record */
328 freeaddrinfo(res);
329 printf("bogus PTR record\\n");
330 return -1;
331 }
332 /* addr is FQDN as a result of PTR lookup */
333} else {
334 /* addr is numeric string */
335 error = getnameinfo(sa, salen, addr, sizeof(addr),
336 NULL, 0, NI_NUMERICHOST);
337}
338.Ed
339.\"
340.Sh BUGS
341The current implementation is not thread-safe.
342.Pp
343The text was shamelessly copied from RFC 2553.
344.Pp
345.Ox
346intentionally uses a different
347.Dv NI_MAXHOST
348value from what RFC 2553 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..da5df507ab
--- /dev/null
+++ b/src/lib/libc/net/getnameinfo.c
@@ -0,0 +1,372 @@
1/* $OpenBSD: getnameinfo.c,v 1.27 2003/07/21 23:17:53 marc 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
62#include "thread_private.h"
63
64static const struct afd {
65 int a_af;
66 int a_addrlen;
67 int a_socklen;
68 int a_off;
69} afdl [] = {
70#ifdef INET6
71 {PF_INET6, sizeof(struct in6_addr), sizeof(struct sockaddr_in6),
72 offsetof(struct sockaddr_in6, sin6_addr)},
73#endif
74 {PF_INET, sizeof(struct in_addr), sizeof(struct sockaddr_in),
75 offsetof(struct sockaddr_in, sin_addr)},
76 {0, 0, 0},
77};
78
79struct sockinet {
80 u_char si_len;
81 u_char si_family;
82 u_short si_port;
83};
84
85#ifdef INET6
86static int ip6_parsenumeric(const struct sockaddr *, const char *, char *,
87 size_t, int);
88static int ip6_sa2str(const struct sockaddr_in6 *, char *, size_t, int);
89#endif
90
91/*
92 * this mutex is also used by get_port in getaddrinfo.c
93 */
94pthread_mutex_t __THREAD_MUTEX_NAME(serv_mutex) = PTHREAD_MUTEX_INITIALIZER;
95
96int
97getnameinfo(sa, salen, host, hostlen, serv, servlen, flags)
98 const struct sockaddr *sa;
99 socklen_t salen;
100 char *host;
101 size_t hostlen;
102 char *serv;
103 size_t servlen;
104 int flags;
105{
106 const struct afd *afd;
107 struct servent *sp;
108 struct hostent *hp;
109 u_short port;
110 int family, i;
111 const char *addr;
112 u_int32_t v4a;
113 int h_error;
114 char numserv[512];
115 char numaddr[512];
116
117 if (sa == NULL)
118 return EAI_FAIL;
119
120 if (sa->sa_len != salen)
121 return EAI_FAIL;
122
123 family = sa->sa_family;
124 for (i = 0; afdl[i].a_af; i++)
125 if (afdl[i].a_af == family) {
126 afd = &afdl[i];
127 goto found;
128 }
129 return EAI_FAMILY;
130
131 found:
132 if (salen != afd->a_socklen)
133 return EAI_FAIL;
134
135 /* network byte order */
136 port = ((const struct sockinet *)sa)->si_port;
137 addr = (const char *)sa + afd->a_off;
138
139 if (serv == NULL || servlen == 0) {
140 /*
141 * do nothing in this case.
142 * in case you are wondering if "&&" is more correct than
143 * "||" here: rfc2553bis-03 says that serv == NULL OR
144 * servlen == 0 means that the caller does not want the result.
145 */
146 } else {
147 if (flags & NI_NUMERICSERV)
148 sp = NULL;
149 else {
150 _THREAD_PRIVATE_MUTEX_LOCK(serv_mutex);
151 sp = getservbyport(port,
152 (flags & NI_DGRAM) ? "udp" : "tcp");
153 _THREAD_PRIVATE_MUTEX_UNLOCK(serv_mutex);
154 }
155 if (sp) {
156 if (strlen(sp->s_name) + 1 > servlen)
157 return EAI_MEMORY;
158 strlcpy(serv, sp->s_name, servlen);
159 } else {
160 snprintf(numserv, sizeof(numserv), "%u", ntohs(port));
161 if (strlen(numserv) + 1 > servlen)
162 return EAI_MEMORY;
163 strlcpy(serv, numserv, servlen);
164 }
165 }
166
167 switch (sa->sa_family) {
168 case AF_INET:
169 v4a = (u_int32_t)
170 ntohl(((const struct sockaddr_in *)sa)->sin_addr.s_addr);
171 if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))
172 flags |= NI_NUMERICHOST;
173 v4a >>= IN_CLASSA_NSHIFT;
174 if (v4a == 0)
175 flags |= NI_NUMERICHOST;
176 break;
177#ifdef INET6
178 case AF_INET6:
179 {
180 const struct sockaddr_in6 *sin6;
181 sin6 = (const struct sockaddr_in6 *)sa;
182 switch (sin6->sin6_addr.s6_addr[0]) {
183 case 0x00:
184 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr))
185 ;
186 else if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr))
187 ;
188 else
189 flags |= NI_NUMERICHOST;
190 break;
191 default:
192 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
193 flags |= NI_NUMERICHOST;
194 }
195 else if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
196 flags |= NI_NUMERICHOST;
197 break;
198 }
199 }
200 break;
201#endif
202 }
203 if (host == NULL || hostlen == 0) {
204 /*
205 * do nothing in this case.
206 * in case you are wondering if "&&" is more correct than
207 * "||" here: rfc2553bis-03 says that host == NULL or
208 * hostlen == 0 means that the caller does not want the result.
209 */
210 } else if (flags & NI_NUMERICHOST) {
211 int numaddrlen;
212
213 /* NUMERICHOST and NAMEREQD conflicts with each other */
214 if (flags & NI_NAMEREQD)
215 return EAI_NONAME;
216
217 switch(afd->a_af) {
218#ifdef INET6
219 case AF_INET6:
220 {
221 int error;
222
223 if ((error = ip6_parsenumeric(sa, addr, host,
224 hostlen, flags)) != 0)
225 return(error);
226 break;
227 }
228#endif
229 default:
230 if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr))
231 == NULL)
232 return EAI_SYSTEM;
233 numaddrlen = strlen(numaddr);
234 if (numaddrlen + 1 > hostlen) /* don't forget terminator */
235 return EAI_MEMORY;
236 strlcpy(host, numaddr, hostlen);
237 break;
238 }
239 } else {
240 _THREAD_PRIVATE_MUTEX_LOCK(serv_mutex);
241 hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af);
242 _THREAD_PRIVATE_MUTEX_UNLOCK(serv_mutex);
243 h_error = h_errno;
244
245 if (hp) {
246#if 0
247 /*
248 * commented out, since "for local host" is not
249 * implemented here - see RFC2553 p30
250 */
251 if (flags & NI_NOFQDN) {
252 char *p;
253 p = strchr(hp->h_name, '.');
254 if (p)
255 *p = '\0';
256 }
257#endif
258 if (strlen(hp->h_name) + 1 > hostlen) {
259 return EAI_MEMORY;
260 }
261 strlcpy(host, hp->h_name, hostlen);
262 } else {
263 if (flags & NI_NAMEREQD)
264 return EAI_NONAME;
265 switch(afd->a_af) {
266#ifdef INET6
267 case AF_INET6:
268 {
269 int error;
270
271 if ((error = ip6_parsenumeric(sa, addr, host,
272 hostlen,
273 flags)) != 0)
274 return(error);
275 break;
276 }
277#endif
278 default:
279 if (inet_ntop(afd->a_af, addr, host,
280 hostlen) == NULL)
281 return EAI_SYSTEM;
282 break;
283 }
284 }
285 }
286 return(0);
287}
288
289#ifdef INET6
290static int
291ip6_parsenumeric(sa, addr, host, hostlen, flags)
292 const struct sockaddr *sa;
293 const char *addr;
294 char *host;
295 size_t hostlen;
296 int flags;
297{
298 int numaddrlen;
299 char numaddr[512];
300
301 if (inet_ntop(AF_INET6, addr, numaddr, sizeof(numaddr)) == NULL)
302 return EAI_SYSTEM;
303
304 numaddrlen = strlen(numaddr);
305 if (numaddrlen + 1 > hostlen) /* don't forget terminator */
306 return EAI_MEMORY;
307 strlcpy(host, numaddr, hostlen);
308
309 if (((const struct sockaddr_in6 *)sa)->sin6_scope_id) {
310 char zonebuf[MAXHOSTNAMELEN];
311 int zonelen;
312
313 zonelen = ip6_sa2str(
314 (const struct sockaddr_in6 *)(const void *)sa,
315 zonebuf, sizeof(zonebuf), flags);
316 if (zonelen < 0)
317 return EAI_MEMORY;
318 if (zonelen + 1 + numaddrlen + 1 > hostlen)
319 return EAI_MEMORY;
320
321 /* construct <numeric-addr><delim><zoneid> */
322 memcpy(host + numaddrlen + 1, zonebuf,
323 (size_t)zonelen);
324 host[numaddrlen] = SCOPE_DELIMITER;
325 host[numaddrlen + 1 + zonelen] = '\0';
326 }
327
328 return 0;
329}
330
331/* ARGSUSED */
332static int
333ip6_sa2str(sa6, buf, bufsiz, flags)
334 const struct sockaddr_in6 *sa6;
335 char *buf;
336 size_t bufsiz;
337 int flags;
338{
339 unsigned int ifindex;
340 const struct in6_addr *a6;
341 int n;
342
343 ifindex = (unsigned int)sa6->sin6_scope_id;
344 a6 = &sa6->sin6_addr;
345
346#ifdef notdef
347 if ((flags & NI_NUMERICSCOPE) != 0) {
348 n = snprintf(buf, bufsiz, "%u", sa6->sin6_scope_id);
349 if (n < 0 || n >= bufsiz)
350 return -1;
351 else
352 return n;
353 }
354#endif
355
356 /* if_indextoname() does not take buffer size. not a good api... */
357 if ((IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6)) &&
358 bufsiz >= IF_NAMESIZE) {
359 char *p = if_indextoname(ifindex, buf);
360 if (p) {
361 return(strlen(p));
362 }
363 }
364
365 /* last resort */
366 n = snprintf(buf, bufsiz, "%u", sa6->sin6_scope_id);
367 if (n < 0 || n >= bufsiz)
368 return -1;
369 else
370 return n;
371}
372#endif /* INET6 */
diff --git a/src/lib/libc/net/getnetbyaddr.c b/src/lib/libc/net/getnetbyaddr.c
new file mode 100644
index 0000000000..29365d4735
--- /dev/null
+++ b/src/lib/libc/net/getnetbyaddr.c
@@ -0,0 +1,52 @@
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. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char rcsid[] = "$OpenBSD: getnetbyaddr.c,v 1.6 2003/06/02 20:18:35 millert Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <netdb.h>
35
36extern int _net_stayopen;
37
38struct netent *
39_getnetbyaddr(net, type)
40 register in_addr_t net;
41 register int type;
42{
43 register struct netent *p;
44
45 setnetent(_net_stayopen);
46 while ((p = getnetent()))
47 if (p->n_addrtype == type && p->n_net == net)
48 break;
49 if (!_net_stayopen)
50 endnetent();
51 return (p);
52}
diff --git a/src/lib/libc/net/getnetbyname.c b/src/lib/libc/net/getnetbyname.c
new file mode 100644
index 0000000000..04ab7b6332
--- /dev/null
+++ b/src/lib/libc/net/getnetbyname.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. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char rcsid[] = "$OpenBSD: getnetbyname.c,v 1.6 2003/06/02 20:18:35 millert Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <netdb.h>
35#include <string.h>
36
37extern int _net_stayopen;
38
39struct netent *
40_getnetbyname(name)
41 register const char *name;
42{
43 register struct netent *p;
44 register char **cp;
45
46 setnetent(_net_stayopen);
47 while ((p = getnetent())) {
48 if (strcasecmp(p->n_name, name) == 0)
49 break;
50 for (cp = p->n_aliases; *cp != 0; cp++)
51 if (strcasecmp(*cp, name) == 0)
52 goto found;
53 }
54found:
55 if (!_net_stayopen)
56 endnetent();
57 return (p);
58}
diff --git a/src/lib/libc/net/getnetent.3 b/src/lib/libc/net/getnetent.3
new file mode 100644
index 0000000000..7cfb22a01d
--- /dev/null
+++ b/src/lib/libc/net/getnetent.3
@@ -0,0 +1,140 @@
1.\" $OpenBSD: getnetent.3,v 1.12 2003/06/02 20:18:35 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. Neither the name of the University nor the names of its contributors
15.\" may be used to endorse or promote products derived from this software
16.\" without specific prior written permission.
17.\"
18.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28.\" SUCH DAMAGE.
29.\"
30.Dd March 13, 1997
31.Dt GETNETENT 3
32.Os
33.Sh NAME
34.Nm getnetent ,
35.Nm getnetbyaddr ,
36.Nm getnetbyname ,
37.Nm setnetent ,
38.Nm endnetent
39.Nd get network entry
40.Sh SYNOPSIS
41.Fd #include <netdb.h>
42.Ft struct netent *
43.Fn getnetent "void"
44.Ft struct netent *
45.Fn getnetbyname "char *name"
46.Ft struct netent *
47.Fn getnetbyaddr "in_addr_t net" "int type"
48.Ft void
49.Fn setnetent "int stayopen"
50.Ft void
51.Fn endnetent "void"
52.Sh DESCRIPTION
53The
54.Fn getnetent ,
55.Fn getnetbyname ,
56and
57.Fn getnetbyaddr
58functions each return a pointer to an object with the following structure
59containing the broken-out fields of a line in the network database,
60.Pa /etc/networks .
61.Bd -literal -offset indent
62struct netent {
63 char *n_name; /* official name of net */
64 char **n_aliases; /* alias list */
65 int n_addrtype; /* net number type */
66 in_addr_t n_net; /* net number */
67};
68.Ed
69.Pp
70The members of this structure are:
71.Bl -tag -width n_addrtype
72.It Fa n_name
73The official name of the network.
74.It Fa n_aliases
75A zero-terminated list of alternate names for the network.
76.It Fa n_addrtype
77The type of the network number returned; currently only
78.Dv AF_INET .
79.It Fa n_net
80The network number.
81Network numbers are returned in machine byte order.
82.El
83.Pp
84The
85.Fn getnetent
86function reads the next line of the file, opening the file if necessary.
87.Pp
88The
89.Fn setnetent
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 getnetbyname
96or
97.Fn getnetbyaddr .
98.Pp
99The
100.Fn endnetent
101function closes the file.
102.Pp
103The
104.Fn getnetbyname
105and
106.Fn getnetbyaddr
107functions search the domain name server if the system is configured to use one.
108If the search fails, or no name server is configured, they sequentially
109search from the beginning of the file until a matching net name or
110net address and type is found, or until
111.Dv EOF
112is encountered.
113Network numbers are supplied in host order.
114.Sh FILES
115.Bl -tag -width /etc/networks -compact
116.It Pa /etc/networks
117.El
118.Sh DIAGNOSTICS
119Null pointer (0) returned on
120.Dv EOF
121or error.
122.Sh SEE ALSO
123.Xr resolver 3 ,
124.Xr networks 5
125.Sh HISTORY
126The
127.Fn getnetent ,
128.Fn getnetbyaddr ,
129.Fn getnetbyname ,
130.Fn setnetent ,
131and
132.Fn endnetent
133functions appeared in
134.Bx 4.2 .
135.Sh BUGS
136The data space used by these functions is static; if future use
137requires the data, it should be copied before any subsequent calls
138to these functions overwrite it.
139Only Internet network numbers are currently understood.
140Expecting 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..4c3b38e7d8
--- /dev/null
+++ b/src/lib/libc/net/getnetent.c
@@ -0,0 +1,125 @@
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. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char rcsid[] = "$OpenBSD: getnetent.c,v 1.9 2003/06/02 20:18:35 millert Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <sys/types.h>
35#include <sys/socket.h>
36#include <netinet/in.h>
37#include <arpa/inet.h>
38#include <netdb.h>
39#include <stdio.h>
40#include <string.h>
41
42#define MAXALIASES 35
43
44static FILE *netf;
45static char line[BUFSIZ+1];
46static struct netent net;
47static char *net_aliases[MAXALIASES];
48int _net_stayopen;
49
50void
51setnetent(f)
52 int f;
53{
54 if (netf == NULL)
55 netf = fopen(_PATH_NETWORKS, "r" );
56 else
57 rewind(netf);
58 _net_stayopen |= f;
59}
60
61void
62endnetent()
63{
64 if (netf) {
65 fclose(netf);
66 netf = NULL;
67 }
68 _net_stayopen = 0;
69}
70
71struct netent *
72getnetent()
73{
74 char *p, *cp, **q;
75 size_t len;
76
77 if (netf == NULL && (netf = fopen(_PATH_NETWORKS, "r" )) == NULL)
78 return (NULL);
79again:
80 if ((p = fgetln(netf, &len)) == NULL)
81 return (NULL);
82 if (p[len-1] == '\n')
83 len--;
84 if (len >= sizeof(line) || len == 0)
85 goto again;
86 p = memcpy(line, p, len);
87 line[len] = '\0';
88 if (*p == '#')
89 goto again;
90 if ((cp = strchr(p, '#')) != NULL)
91 *cp = '\0';
92 net.n_name = p;
93 if (strlen(net.n_name) >= MAXHOSTNAMELEN-1)
94 net.n_name[MAXHOSTNAMELEN-1] = '\0';
95 cp = strpbrk(p, " \t");
96 if (cp == NULL)
97 goto again;
98 *cp++ = '\0';
99 while (*cp == ' ' || *cp == '\t')
100 cp++;
101 p = strpbrk(cp, " \t");
102 if (p != NULL)
103 *p++ = '\0';
104 net.n_net = inet_network(cp);
105 net.n_addrtype = AF_INET;
106 q = net.n_aliases = net_aliases;
107 if (p != NULL)
108 cp = p;
109 while (cp && *cp) {
110 if (*cp == ' ' || *cp == '\t') {
111 cp++;
112 continue;
113 }
114 if (q < &net_aliases[MAXALIASES - 1]) {
115 *q++ = cp;
116 if (strlen(cp) >= MAXHOSTNAMELEN-1)
117 cp[MAXHOSTNAMELEN-1] = '\0';
118 }
119 cp = strpbrk(cp, " \t");
120 if (cp != NULL)
121 *cp++ = '\0';
122 }
123 *q = NULL;
124 return (&net);
125}
diff --git a/src/lib/libc/net/getnetnamadr.c b/src/lib/libc/net/getnetnamadr.c
new file mode 100644
index 0000000000..149216ffd8
--- /dev/null
+++ b/src/lib/libc/net/getnetnamadr.c
@@ -0,0 +1,400 @@
1/* $OpenBSD: getnetnamadr.c,v 1.23 2003/06/03 21:09:00 deraadt 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 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS
16 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT,
19 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27/* Copyright (c) 1993 Carlos Leandro and Rui Salgueiro
28 * Dep. Matematica Universidade de Coimbra, Portugal, Europe
29 *
30 * Permission to use, copy, modify, and distribute this software for any
31 * purpose with or without fee is hereby granted, provided that the above
32 * copyright notice and this permission notice appear in all copies.
33 */
34/*
35 * Copyright (c) 1983, 1993
36 * The Regents of the University of California. All rights reserved.
37 *
38 * Redistribution and use in source and binary forms, with or without
39 * modification, are permitted provided that the following conditions
40 * are met:
41 * 1. Redistributions of source code must retain the above copyright
42 * notice, this list of conditions and the following disclaimer.
43 * 2. Redistributions in binary form must reproduce the above copyright
44 * notice, this list of conditions and the following disclaimer in the
45 * documentation and/or other materials provided with the distribution.
46 * 3. Neither the name of the University nor the names of its contributors
47 * may be used to endorse or promote products derived from this software
48 * without specific prior written permission.
49 *
50 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
51 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
53 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
54 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
55 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
56 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
57 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
58 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
59 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
60 * SUCH DAMAGE.
61 */
62
63#if defined(LIBC_SCCS) && !defined(lint)
64#if 0
65static char sccsid[] = "@(#)getnetbyaddr.c 8.1 (Berkeley) 6/4/93";
66static char sccsid_[] = "from getnetnamadr.c 1.4 (Coimbra) 93/06/03";
67static char rcsid[] = "$From: getnetnamadr.c,v 8.7 1996/08/05 08:31:35 vixie Exp $";
68#else
69static char rcsid[] = "$OpenBSD: getnetnamadr.c,v 1.23 2003/06/03 21:09:00 deraadt Exp $";
70#endif
71#endif /* LIBC_SCCS and not lint */
72
73#include <sys/types.h>
74#include <sys/param.h>
75#include <sys/socket.h>
76#include <netinet/in.h>
77#include <arpa/inet.h>
78#include <arpa/nameser.h>
79
80#include <stdio.h>
81#include <netdb.h>
82#include <resolv.h>
83#include <ctype.h>
84#include <errno.h>
85#include <string.h>
86#include <stdlib.h>
87
88#include "thread_private.h"
89
90extern int h_errno;
91
92struct netent *_getnetbyaddr(in_addr_t net, int type);
93struct netent *_getnetbyname(const char *name);
94
95int _hokchar(const char *);
96
97#define BYADDR 0
98#define BYNAME 1
99#define MAXALIASES 35
100
101#define MAXPACKET (64*1024)
102
103typedef union {
104 HEADER hdr;
105 u_char buf[MAXPACKET];
106} querybuf;
107
108typedef union {
109 long al;
110 char ac;
111} align;
112
113static struct netent *
114getnetanswer(answer, anslen, net_i)
115 querybuf *answer;
116 int anslen;
117 int net_i;
118{
119
120 register HEADER *hp;
121 register u_char *cp;
122 register int n;
123 u_char *eom;
124 int type, class, ancount, qdcount, haveanswer, i, nchar;
125 char aux1[MAXHOSTNAMELEN], aux2[MAXHOSTNAMELEN], ans[MAXHOSTNAMELEN];
126 char *in, *st, *pauxt, *bp, **ap, *ep;
127 char *paux1 = &aux1[0], *paux2 = &aux2[0];
128 static struct netent net_entry;
129 static char *net_aliases[MAXALIASES], netbuf[BUFSIZ+1];
130
131 /*
132 * find first satisfactory answer
133 *
134 * answer --> +------------+ ( MESSAGE )
135 * | Header |
136 * +------------+
137 * | Question | the question for the name server
138 * +------------+
139 * | Answer | RRs answering the question
140 * +------------+
141 * | Authority | RRs pointing toward an authority
142 * | Additional | RRs holding additional information
143 * +------------+
144 */
145 eom = answer->buf + anslen;
146 hp = &answer->hdr;
147 ancount = ntohs(hp->ancount); /* #/records in the answer section */
148 qdcount = ntohs(hp->qdcount); /* #/entries in the question section */
149 bp = netbuf;
150 ep = netbuf + sizeof(netbuf);
151 cp = answer->buf + HFIXEDSZ;
152 if (!qdcount) {
153 if (hp->aa)
154 h_errno = HOST_NOT_FOUND;
155 else
156 h_errno = TRY_AGAIN;
157 return (NULL);
158 }
159 while (qdcount-- > 0) {
160 n = __dn_skipname(cp, eom);
161 if (n < 0 || (cp + n + QFIXEDSZ) > eom) {
162 h_errno = NO_RECOVERY;
163 return(NULL);
164 }
165 cp += n + QFIXEDSZ;
166 }
167 ap = net_aliases;
168 *ap = NULL;
169 net_entry.n_aliases = net_aliases;
170 haveanswer = 0;
171 while (--ancount >= 0 && cp < eom) {
172 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
173#ifdef USE_RESOLV_NAME_OK
174 if ((n < 0) || !res_dnok(bp))
175#else
176 if ((n < 0) || !_hokchar(bp))
177#endif
178 break;
179 cp += n;
180 ans[0] = '\0';
181 strlcpy(&ans[0], bp, sizeof ans);
182 GETSHORT(type, cp);
183 GETSHORT(class, cp);
184 cp += INT32SZ; /* TTL */
185 GETSHORT(n, cp);
186 if (class == C_IN && type == T_PTR) {
187 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
188#ifdef USE_RESOLV_NAME_OK
189 if ((n < 0) || !res_hnok(bp))
190#else
191 if ((n < 0) || !_hokchar(bp))
192#endif
193 {
194 cp += n;
195 return (NULL);
196 }
197 cp += n;
198 if ((ap + 2) < &net_aliases[MAXALIASES]) {
199 *ap++ = bp;
200 bp += strlen(bp) + 1;
201 net_entry.n_addrtype =
202 (class == C_IN) ? AF_INET : AF_UNSPEC;
203 haveanswer++;
204 }
205 }
206 }
207 if (haveanswer) {
208 *ap = NULL;
209 switch (net_i) {
210 case BYADDR:
211 net_entry.n_name = *net_entry.n_aliases;
212 net_entry.n_net = 0L;
213 break;
214 case BYNAME:
215 ap = net_entry.n_aliases;
216 next_alias:
217 in = *ap++;
218 if (in == NULL) {
219 h_errno = HOST_NOT_FOUND;
220 return (NULL);
221 }
222 net_entry.n_name = ans;
223 aux2[0] = '\0';
224 for (i = 0; i < 4; i++) {
225 for (st = in, nchar = 0;
226 isdigit((unsigned char)*st);
227 st++, nchar++)
228 ;
229 if (*st != '.' || nchar == 0 || nchar > 3)
230 goto next_alias;
231 if (i != 0)
232 nchar++;
233 strlcpy(paux1, in, nchar+1);
234 strlcat(paux1, paux2, MAXHOSTNAMELEN);
235 pauxt = paux2;
236 paux2 = paux1;
237 paux1 = pauxt;
238 in = ++st;
239 }
240 if (strcasecmp(in, "IN-ADDR.ARPA") != 0)
241 goto next_alias;
242 net_entry.n_net = inet_network(paux2);
243 break;
244 }
245 net_entry.n_aliases++;
246 return (&net_entry);
247 }
248 h_errno = TRY_AGAIN;
249 return (NULL);
250}
251
252struct netent *
253getnetbyaddr(net, net_type)
254 register in_addr_t net;
255 register int net_type;
256{
257 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
258 unsigned int netbr[4];
259 int nn, anslen;
260 querybuf *buf;
261 char qbuf[MAXDNAME];
262 in_addr_t net2;
263 struct netent *net_entry = NULL;
264 char lookups[MAXDNSLUS];
265 int i;
266
267 if ((_resp->options & RES_INIT) == 0 && res_init() == -1)
268 return(_getnetbyaddr(net, net_type));
269
270 bcopy(_resp->lookups, lookups, sizeof lookups);
271 if (lookups[0] == '\0')
272 strlcpy(lookups, "bf", sizeof lookups);
273
274 for (i = 0; i < MAXDNSLUS && lookups[i]; i++) {
275 switch (lookups[i]) {
276#ifdef YP
277 case 'y':
278 /* There is no YP support. */
279 break;
280#endif /* YP */
281 case 'b':
282 if (net_type != AF_INET)
283 break; /* DNS only supports AF_INET? */
284
285 for (nn = 4, net2 = net; net2; net2 >>= 8)
286 netbr[--nn] = net2 & 0xff;
287 switch (nn) {
288 case 3: /* Class A */
289 snprintf(qbuf, sizeof(qbuf),
290 "0.0.0.%u.in-addr.arpa", netbr[3]);
291 break;
292 case 2: /* Class B */
293 snprintf(qbuf, sizeof(qbuf),
294 "0.0.%u.%u.in-addr.arpa",
295 netbr[3], netbr[2]);
296 break;
297 case 1: /* Class C */
298 snprintf(qbuf, sizeof(qbuf),
299 "0.%u.%u.%u.in-addr.arpa",
300 netbr[3], netbr[2], netbr[1]);
301 break;
302 case 0: /* Class D - E */
303 snprintf(qbuf, sizeof(qbuf),
304 "%u.%u.%u.%u.in-addr.arpa",
305 netbr[3], netbr[2], netbr[1], netbr[0]);
306 break;
307 }
308 buf = malloc(sizeof(*buf));
309 if (buf == NULL)
310 break;
311 anslen = res_query(qbuf, C_IN, T_PTR, buf->buf,
312 sizeof(buf->buf));
313 if (anslen < 0) {
314 free(buf);
315#ifdef DEBUG
316 if (_resp->options & RES_DEBUG)
317 printf("res_query failed\n");
318#endif
319 break;
320 }
321 net_entry = getnetanswer(buf, anslen, BYADDR);
322 free(buf);
323 if (net_entry != NULL) {
324 unsigned u_net = net; /* maybe net should be unsigned ? */
325
326 /* Strip trailing zeros */
327 while ((u_net & 0xff) == 0 && u_net != 0)
328 u_net >>= 8;
329 net_entry->n_net = u_net;
330 return (net_entry);
331 }
332 break;
333 case 'f':
334 net_entry = _getnetbyaddr(net, net_type);
335 if (net_entry != NULL)
336 return (net_entry);
337 }
338 }
339
340 /* Nothing matched. */
341 return (NULL);
342}
343
344struct netent *
345getnetbyname(net)
346 register const char *net;
347{
348 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
349 int anslen;
350 querybuf *buf;
351 char qbuf[MAXDNAME];
352 struct netent *net_entry = NULL;
353 char lookups[MAXDNSLUS];
354 int i;
355
356 if ((_resp->options & RES_INIT) == 0 && res_init() == -1)
357 return (_getnetbyname(net));
358
359 bcopy(_resp->lookups, lookups, sizeof lookups);
360 if (lookups[0] == '\0')
361 strlcpy(lookups, "bf", sizeof lookups);
362
363 for (i = 0; i < MAXDNSLUS && lookups[i]; i++) {
364 switch (lookups[i]) {
365#ifdef YP
366 case 'y':
367 /* There is no YP support. */
368 break;
369#endif /* YP */
370 case 'b':
371 strlcpy(qbuf, net, sizeof qbuf);
372 buf = malloc(sizeof(*buf));
373 if (buf == NULL)
374 break;
375 anslen = res_search(qbuf, C_IN, T_PTR, buf->buf,
376 sizeof(buf->buf));
377 if (anslen < 0) {
378 free(buf);
379#ifdef DEBUG
380 if (_resp->options & RES_DEBUG)
381 printf("res_query failed\n");
382#endif
383 break;
384 }
385 net_entry = getnetanswer(buf, anslen, BYNAME);
386 free(buf);
387 if (net_entry != NULL)
388 return (net_entry);
389 break;
390 case 'f':
391 net_entry = _getnetbyname(net);
392 if (net_entry != NULL)
393 return (net_entry);
394 break;
395 }
396 }
397
398 /* Nothing matched. */
399 return (NULL);
400}
diff --git a/src/lib/libc/net/getproto.c b/src/lib/libc/net/getproto.c
new file mode 100644
index 0000000000..dee089d5c2
--- /dev/null
+++ b/src/lib/libc/net/getproto.c
@@ -0,0 +1,51 @@
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. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char rcsid[] = "$OpenBSD: getproto.c,v 1.4 2003/06/02 20:18:35 millert Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <netdb.h>
35
36extern int _proto_stayopen;
37
38struct protoent *
39getprotobynumber(proto)
40 register int proto;
41{
42 register struct protoent *p;
43
44 setprotoent(_proto_stayopen);
45 while ((p = getprotoent()))
46 if (p->p_proto == proto)
47 break;
48 if (!_proto_stayopen)
49 endprotoent();
50 return (p);
51}
diff --git a/src/lib/libc/net/getprotoent.3 b/src/lib/libc/net/getprotoent.3
new file mode 100644
index 0000000000..be257966a2
--- /dev/null
+++ b/src/lib/libc/net/getprotoent.3
@@ -0,0 +1,130 @@
1.\" $OpenBSD: getprotoent.3,v 1.9 2003/06/02 20:18:35 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. Neither the name of the University nor the names of its contributors
15.\" may be used to endorse or promote products derived from this software
16.\" without specific prior written permission.
17.\"
18.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28.\" SUCH DAMAGE.
29.\"
30.Dd June 4, 1993
31.Dt GETPROTOENT 3
32.Os
33.Sh NAME
34.Nm getprotoent ,
35.Nm getprotobynumber ,
36.Nm getprotobyname ,
37.Nm setprotoent ,
38.Nm endprotoent
39.Nd get protocol entry
40.Sh SYNOPSIS
41.Fd #include <netdb.h>
42.Ft struct protoent *
43.Fn getprotoent "void"
44.Ft struct protoent *
45.Fn getprotobyname "char *name"
46.Ft struct protoent *
47.Fn getprotobynumber "int proto"
48.Ft void
49.Fn setprotoent "int stayopen"
50.Ft void
51.Fn endprotoent "void"
52.Sh DESCRIPTION
53The
54.Fn getprotoent ,
55.Fn getprotobyname ,
56and
57.Fn getprotobynumber
58functions each return a pointer to an object with the following structure
59containing the broken-out fields of a line in the network protocol database,
60.Pa /etc/protocols .
61.Bd -literal -offset indent
62.Pp
63struct protoent {
64 char *p_name; /* official name of protocol */
65 char **p_aliases; /* alias list */
66 int p_proto; /* protocol number */
67};
68.Ed
69.Pp
70The members of this structure are:
71.Bl -tag -width p_aliases
72.It Fa p_name
73The official name of the protocol.
74.It Fa p_aliases
75A zero-terminated list of alternate names for the protocol.
76.It Fa p_proto
77The protocol number.
78.El
79.Pp
80The
81.Fn getprotoent
82function reads the next line of the file, opening the file if necessary.
83.Pp
84The
85.Fn setprotoent
86function opens and rewinds the file.
87If the
88.Fa stayopen
89flag is non-zero,
90the net database will not be closed after each call to
91.Fn getprotobyname
92or
93.Fn getprotobynumber .
94.Pp
95The
96.Fn endprotoent
97function closes the file.
98.Pp
99The
100.Fn getprotobyname
101and
102.Fn getprotobynumber
103functions sequentially search from the beginning of the file until a
104matching protocol name or protocol number is found, or until
105.Dv EOF
106is encountered.
107.Sh RETURN VALUES
108Null pointer (0) returned on
109.Dv EOF
110or error.
111.Sh FILES
112.Bl -tag -width /etc/protocols -compact
113.It Pa /etc/protocols
114.El
115.Sh SEE ALSO
116.Xr protocols 5
117.Sh HISTORY
118The
119.Fn getprotoent ,
120.Fn getprotobynumber ,
121.Fn getprotobyname ,
122.Fn setprotoent ,
123and
124.Fn endprotoent
125functions appeared in
126.Bx 4.2 .
127.Sh BUGS
128These functions use a static data space; if the data is needed for future use,
129it should be copied before any subsequent calls overwrite it.
130Only 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..b2bdd2e164
--- /dev/null
+++ b/src/lib/libc/net/getprotoent.c
@@ -0,0 +1,123 @@
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. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char rcsid[] = "$OpenBSD: getprotoent.c,v 1.5 2003/06/02 20:18:35 millert Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <sys/types.h>
35#include <sys/socket.h>
36#include <netdb.h>
37#include <stdio.h>
38#include <stdlib.h>
39#include <string.h>
40
41#define MAXALIASES 35
42
43static FILE *protof = NULL;
44static char line[BUFSIZ+1];
45static struct protoent proto;
46static char *proto_aliases[MAXALIASES];
47int _proto_stayopen;
48
49void
50setprotoent(f)
51 int f;
52{
53 if (protof == NULL)
54 protof = fopen(_PATH_PROTOCOLS, "r" );
55 else
56 rewind(protof);
57 _proto_stayopen |= f;
58}
59
60void
61endprotoent()
62{
63 if (protof) {
64 fclose(protof);
65 protof = NULL;
66 }
67 _proto_stayopen = 0;
68}
69
70struct protoent *
71getprotoent()
72{
73 char *p, *cp, **q, *endp;
74 long l;
75 size_t len;
76
77 if (protof == NULL && (protof = fopen(_PATH_PROTOCOLS, "r" )) == NULL)
78 return (NULL);
79again:
80 if ((p = fgetln(protof, &len)) == NULL)
81 return (NULL);
82 if (p[len-1] == '\n')
83 len--;
84 if (len >= sizeof(line) || len == 0)
85 goto again;
86 p = memcpy(line, p, len);
87 line[len] = '\0';
88 if (*p == '#')
89 goto again;
90 if ((cp = strchr(p, '#')) != NULL)
91 *cp = '\0';
92 proto.p_name = p;
93 cp = strpbrk(p, " \t");
94 if (cp == NULL)
95 goto again;
96 *cp++ = '\0';
97 while (*cp == ' ' || *cp == '\t')
98 cp++;
99 p = strpbrk(cp, " \t");
100 if (p != NULL)
101 *p++ = '\0';
102 l = strtol(cp, &endp, 10);
103 if (endp == cp || *endp != '\0' || l < 0 || l >= INT_MAX)
104 goto again;
105 proto.p_proto = l;
106 q = proto.p_aliases = proto_aliases;
107 if (p != NULL) {
108 cp = p;
109 while (cp && *cp) {
110 if (*cp == ' ' || *cp == '\t') {
111 cp++;
112 continue;
113 }
114 if (q < &proto_aliases[MAXALIASES - 1])
115 *q++ = cp;
116 cp = strpbrk(cp, " \t");
117 if (cp != NULL)
118 *cp++ = '\0';
119 }
120 }
121 *q = NULL;
122 return (&proto);
123}
diff --git a/src/lib/libc/net/getprotoname.c b/src/lib/libc/net/getprotoname.c
new file mode 100644
index 0000000000..4742a60a04
--- /dev/null
+++ b/src/lib/libc/net/getprotoname.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. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char rcsid[] = "$OpenBSD: getprotoname.c,v 1.4 2003/06/02 20:18:35 millert Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <netdb.h>
35#include <string.h>
36
37extern int _proto_stayopen;
38
39struct protoent *
40getprotobyname(name)
41 register const char *name;
42{
43 register struct protoent *p;
44 register char **cp;
45
46 setprotoent(_proto_stayopen);
47 while ((p = getprotoent())) {
48 if (strcmp(p->p_name, name) == 0)
49 break;
50 for (cp = p->p_aliases; *cp != 0; cp++)
51 if (strcmp(*cp, name) == 0)
52 goto found;
53 }
54found:
55 if (!_proto_stayopen)
56 endprotoent();
57 return (p);
58}
diff --git a/src/lib/libc/net/getrrsetbyname.3 b/src/lib/libc/net/getrrsetbyname.3
new file mode 100644
index 0000000000..a786ff8747
--- /dev/null
+++ b/src/lib/libc/net/getrrsetbyname.3
@@ -0,0 +1,165 @@
1.\" $OpenBSD: getrrsetbyname.3,v 1.11 2003/05/30 21:37:59 jmc 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 October 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
105structure.
106Memory allocated for the dynamically allocated structures created by
107a successful call to
108.Fn getrrsetbyname
109is released by
110.Fn freerrset .
111.Li rrset
112is a pointer to a
113.Li struct rrset
114created by a call to
115.Fn getrrsetbyname .
116.Pp
117If the EDNS0 option is activated in
118.Xr resolv.conf 5 ,
119.Fn getrrsetbyname
120will request DNSSEC authentication using the EDNS0 DNSSEC OK (DO) bit.
121.Sh RETURN VALUES
122.Fn getrrsetbyname
123returns zero on success, and one of the following error
124codes if an error occurred:
125.Pp
126.Bl -tag -width ERRSET_NOMEMORY -compact
127.It Dv ERRSET_NONAME
128the name does not exist
129.It Dv ERRSET_NODATA
130the name exists, but does not have data of the desired type
131.It Dv ERRSET_NOMEMORY
132memory could not be allocated
133.It Dv ERRSET_INVAL
134a parameter is invalid
135.It Dv ERRSET_FAIL
136other failure
137.El
138.Sh SEE ALSO
139.Xr resolver 3 ,
140.Xr resolv.conf 5 ,
141.Xr named 8
142.Sh HISTORY
143.Fn getrrsetbyname
144first appeared in
145.Ox 3.0 .
146The API first appeared in ISC BIND version 9.
147.Sh AUTHORS
148.An Jakob Schlyter Aq jakob@openbsd.org
149.Sh CAVEATS
150The
151.Dv RRSET_VALIDATED
152flag in
153.Li rri_flags
154is set if the AD (authenticated data) bit in the DNS answer is
155set.
156This flag
157.Em should not
158be trusted unless the transport between the nameserver and the resolver
159is secure (e.g. IPsec, trusted network, loopback communication).
160.Sh BUGS
161The data in
162.Li *rdi_data
163should be returned in uncompressed wire format.
164Currently, the data is in compressed format and the caller can't
165uncompress since it doesn't have the full message.
diff --git a/src/lib/libc/net/getrrsetbyname.c b/src/lib/libc/net/getrrsetbyname.c
new file mode 100644
index 0000000000..f00ac2b021
--- /dev/null
+++ b/src/lib/libc/net/getrrsetbyname.c
@@ -0,0 +1,512 @@
1/* $OpenBSD: getrrsetbyname.c,v 1.7 2003/03/07 07:34:14 itojun 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#include "thread_private.h"
55
56#define ANSWER_BUFFER_SIZE 1024*64
57
58struct dns_query {
59 char *name;
60 u_int16_t type;
61 u_int16_t class;
62 struct dns_query *next;
63};
64
65struct dns_rr {
66 char *name;
67 u_int16_t type;
68 u_int16_t class;
69 u_int16_t ttl;
70 u_int16_t size;
71 void *rdata;
72 struct dns_rr *next;
73};
74
75struct dns_response {
76 HEADER header;
77 struct dns_query *query;
78 struct dns_rr *answer;
79 struct dns_rr *authority;
80 struct dns_rr *additional;
81};
82
83static struct dns_response *parse_dns_response(const u_char *, int);
84static struct dns_query *parse_dns_qsection(const u_char *, int,
85 const u_char **, int);
86static struct dns_rr *parse_dns_rrsection(const u_char *, int, const u_char **,
87 int);
88
89static void free_dns_query(struct dns_query *);
90static void free_dns_rr(struct dns_rr *);
91static void free_dns_response(struct dns_response *);
92
93static int count_dns_rr(struct dns_rr *, u_int16_t, u_int16_t);
94
95int
96getrrsetbyname(const char *hostname, unsigned int rdclass,
97 unsigned int rdtype, unsigned int flags,
98 struct rrsetinfo **res)
99{
100 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
101 int result;
102 struct rrsetinfo *rrset = NULL;
103 struct dns_response *response;
104 struct dns_rr *rr;
105 struct rdatainfo *rdata;
106 int length;
107 unsigned int index_ans, index_sig;
108 u_char answer[ANSWER_BUFFER_SIZE];
109
110 /* check for invalid class and type */
111 if (rdclass > 0xffff || rdtype > 0xffff) {
112 result = ERRSET_INVAL;
113 goto fail;
114 }
115
116 /* don't allow queries of class or type ANY */
117 if (rdclass == 0xff || rdtype == 0xff) {
118 result = ERRSET_INVAL;
119 goto fail;
120 }
121
122 /* don't allow flags yet, unimplemented */
123 if (flags) {
124 result = ERRSET_INVAL;
125 goto fail;
126 }
127
128 /* initialize resolver */
129 if ((_resp->options & RES_INIT) == 0 && res_init() == -1) {
130 result = ERRSET_FAIL;
131 goto fail;
132 }
133
134#ifdef DEBUG
135 _resp->options |= RES_DEBUG;
136#endif /* DEBUG */
137
138#ifdef RES_USE_DNSSEC
139 /* turn on DNSSEC if EDNS0 is configured */
140 if (_resp->options & RES_USE_EDNS0)
141 _resp->options |= RES_USE_DNSSEC;
142#endif /* RES_USE_DNSEC */
143
144 /* make query */
145 length = res_query(hostname, (signed int) rdclass, (signed int) rdtype,
146 answer, sizeof(answer));
147 if (length < 0) {
148 switch(h_errno) {
149 case HOST_NOT_FOUND:
150 result = ERRSET_NONAME;
151 goto fail;
152 case NO_DATA:
153 result = ERRSET_NODATA;
154 goto fail;
155 default:
156 result = ERRSET_FAIL;
157 goto fail;
158 }
159 }
160
161 /* parse result */
162 response = parse_dns_response(answer, length);
163 if (response == NULL) {
164 result = ERRSET_FAIL;
165 goto fail;
166 }
167
168 if (response->header.qdcount != 1) {
169 result = ERRSET_FAIL;
170 goto fail;
171 }
172
173 /* initialize rrset */
174 rrset = calloc(1, sizeof(struct rrsetinfo));
175 if (rrset == NULL) {
176 result = ERRSET_NOMEMORY;
177 goto fail;
178 }
179 rrset->rri_rdclass = response->query->class;
180 rrset->rri_rdtype = response->query->type;
181 rrset->rri_ttl = response->answer->ttl;
182 rrset->rri_nrdatas = response->header.ancount;
183
184 /* check for authenticated data */
185 if (response->header.ad == 1)
186 rrset->rri_flags |= RRSET_VALIDATED;
187
188 /* copy name from answer section */
189 length = strlen(response->answer->name);
190 rrset->rri_name = malloc(length + 1);
191 if (rrset->rri_name == NULL) {
192 result = ERRSET_NOMEMORY;
193 goto fail;
194 }
195 strlcpy(rrset->rri_name, response->answer->name, length + 1);
196
197 /* count answers */
198 rrset->rri_nrdatas = count_dns_rr(response->answer, rrset->rri_rdclass,
199 rrset->rri_rdtype);
200 rrset->rri_nsigs = count_dns_rr(response->answer, rrset->rri_rdclass,
201 T_SIG);
202
203 /* allocate memory for answers */
204 rrset->rri_rdatas = calloc(rrset->rri_nrdatas,
205 sizeof(struct rdatainfo));
206 if (rrset->rri_rdatas == NULL) {
207 result = ERRSET_NOMEMORY;
208 goto fail;
209 }
210
211 /* allocate memory for signatures */
212 rrset->rri_sigs = calloc(rrset->rri_nsigs, sizeof(struct rdatainfo));
213 if (rrset->rri_sigs == NULL) {
214 result = ERRSET_NOMEMORY;
215 goto fail;
216 }
217
218 /* copy answers & signatures */
219 for (rr = response->answer, index_ans = 0, index_sig = 0;
220 rr; rr = rr->next) {
221
222 rdata = NULL;
223
224 if (rr->class == rrset->rri_rdclass &&
225 rr->type == rrset->rri_rdtype)
226 rdata = &rrset->rri_rdatas[index_ans++];
227
228 if (rr->class == rrset->rri_rdclass &&
229 rr->type == T_SIG)
230 rdata = &rrset->rri_sigs[index_sig++];
231
232 if (rdata) {
233 rdata->rdi_length = rr->size;
234 rdata->rdi_data = malloc(rr->size);
235
236 if (rdata->rdi_data == NULL) {
237 result = ERRSET_NOMEMORY;
238 goto fail;
239 }
240 memcpy(rdata->rdi_data, rr->rdata, rr->size);
241 }
242 }
243
244 *res = rrset;
245 return (ERRSET_SUCCESS);
246
247fail:
248 if (rrset != NULL)
249 freerrset(rrset);
250 return (result);
251}
252
253void
254freerrset(struct rrsetinfo *rrset)
255{
256 u_int16_t i;
257
258 if (rrset == NULL)
259 return;
260
261 if (rrset->rri_rdatas) {
262 for (i = 0; i < rrset->rri_nrdatas; i++) {
263 if (rrset->rri_rdatas[i].rdi_data == NULL)
264 break;
265 free(rrset->rri_rdatas[i].rdi_data);
266 }
267 free(rrset->rri_rdatas);
268 }
269
270 if (rrset->rri_sigs) {
271 for (i = 0; i < rrset->rri_nsigs; i++) {
272 if (rrset->rri_sigs[i].rdi_data == NULL)
273 break;
274 free(rrset->rri_sigs[i].rdi_data);
275 }
276 free(rrset->rri_sigs);
277 }
278
279 if (rrset->rri_name)
280 free(rrset->rri_name);
281 free(rrset);
282}
283
284/*
285 * DNS response parsing routines
286 */
287static struct dns_response *
288parse_dns_response(const u_char *answer, int size)
289{
290 struct dns_response *resp;
291 const u_char *cp;
292
293 /* allocate memory for the response */
294 resp = calloc(1, sizeof(*resp));
295 if (resp == NULL)
296 return (NULL);
297
298 /* initialize current pointer */
299 cp = answer;
300
301 /* copy header */
302 memcpy(&resp->header, cp, HFIXEDSZ);
303 cp += HFIXEDSZ;
304
305 /* fix header byte order */
306 resp->header.qdcount = ntohs(resp->header.qdcount);
307 resp->header.ancount = ntohs(resp->header.ancount);
308 resp->header.nscount = ntohs(resp->header.nscount);
309 resp->header.arcount = ntohs(resp->header.arcount);
310
311 /* there must be at least one query */
312 if (resp->header.qdcount < 1) {
313 free_dns_response(resp);
314 return (NULL);
315 }
316
317 /* parse query section */
318 resp->query = parse_dns_qsection(answer, size, &cp,
319 resp->header.qdcount);
320 if (resp->header.qdcount && resp->query == NULL) {
321 free_dns_response(resp);
322 return (NULL);
323 }
324
325 /* parse answer section */
326 resp->answer = parse_dns_rrsection(answer, size, &cp,
327 resp->header.ancount);
328 if (resp->header.ancount && resp->answer == NULL) {
329 free_dns_response(resp);
330 return (NULL);
331 }
332
333 /* parse authority section */
334 resp->authority = parse_dns_rrsection(answer, size, &cp,
335 resp->header.nscount);
336 if (resp->header.nscount && resp->authority == NULL) {
337 free_dns_response(resp);
338 return (NULL);
339 }
340
341 /* parse additional section */
342 resp->additional = parse_dns_rrsection(answer, size, &cp,
343 resp->header.arcount);
344 if (resp->header.arcount && resp->additional == NULL) {
345 free_dns_response(resp);
346 return (NULL);
347 }
348
349 return (resp);
350}
351
352static struct dns_query *
353parse_dns_qsection(const u_char *answer, int size, const u_char **cp, int count)
354{
355 struct dns_query *head, *curr, *prev;
356 int i, length;
357 char name[MAXDNAME];
358
359 for (i = 1, head = NULL, prev = NULL; i <= count; i++, prev = curr) {
360
361 /* allocate and initialize struct */
362 curr = calloc(1, sizeof(struct dns_query));
363 if (curr == NULL) {
364 free_dns_query(head);
365 return (NULL);
366 }
367 if (head == NULL)
368 head = curr;
369 if (prev != NULL)
370 prev->next = curr;
371
372 /* name */
373 length = dn_expand(answer, answer + size, *cp, name,
374 sizeof(name));
375 if (length < 0) {
376 free_dns_query(head);
377 return (NULL);
378 }
379 curr->name = strdup(name);
380 if (curr->name == NULL) {
381 free_dns_query(head);
382 return (NULL);
383 }
384 *cp += length;
385
386 /* type */
387 curr->type = _getshort(*cp);
388 *cp += INT16SZ;
389
390 /* class */
391 curr->class = _getshort(*cp);
392 *cp += INT16SZ;
393 }
394
395 return (head);
396}
397
398static struct dns_rr *
399parse_dns_rrsection(const u_char *answer, int size, const u_char **cp, int count)
400{
401 struct dns_rr *head, *curr, *prev;
402 int i, length;
403 char name[MAXDNAME];
404
405 for (i = 1, head = NULL, prev = NULL; i <= count; i++, prev = curr) {
406
407 /* allocate and initialize struct */
408 curr = calloc(1, sizeof(struct dns_rr));
409 if (curr == NULL) {
410 free_dns_rr(head);
411 return (NULL);
412 }
413 if (head == NULL)
414 head = curr;
415 if (prev != NULL)
416 prev->next = curr;
417
418 /* name */
419 length = dn_expand(answer, answer + size, *cp, name,
420 sizeof(name));
421 if (length < 0) {
422 free_dns_rr(head);
423 return (NULL);
424 }
425 curr->name = strdup(name);
426 if (curr->name == NULL) {
427 free_dns_rr(head);
428 return (NULL);
429 }
430 *cp += length;
431
432 /* type */
433 curr->type = _getshort(*cp);
434 *cp += INT16SZ;
435
436 /* class */
437 curr->class = _getshort(*cp);
438 *cp += INT16SZ;
439
440 /* ttl */
441 curr->ttl = _getlong(*cp);
442 *cp += INT32SZ;
443
444 /* rdata size */
445 curr->size = _getshort(*cp);
446 *cp += INT16SZ;
447
448 /* rdata itself */
449 curr->rdata = malloc(curr->size);
450 if (curr->rdata == NULL) {
451 free_dns_rr(head);
452 return (NULL);
453 }
454 memcpy(curr->rdata, *cp, curr->size);
455 *cp += curr->size;
456 }
457
458 return (head);
459}
460
461static void
462free_dns_query(struct dns_query *p)
463{
464 if (p == NULL)
465 return;
466
467 if (p->name)
468 free(p->name);
469 free_dns_query(p->next);
470 free(p);
471}
472
473static void
474free_dns_rr(struct dns_rr *p)
475{
476 if (p == NULL)
477 return;
478
479 if (p->name)
480 free(p->name);
481 if (p->rdata)
482 free(p->rdata);
483 free_dns_rr(p->next);
484 free(p);
485}
486
487static void
488free_dns_response(struct dns_response *p)
489{
490 if (p == NULL)
491 return;
492
493 free_dns_query(p->query);
494 free_dns_rr(p->answer);
495 free_dns_rr(p->authority);
496 free_dns_rr(p->additional);
497 free(p);
498}
499
500static int
501count_dns_rr(struct dns_rr *p, u_int16_t class, u_int16_t type)
502{
503 int n = 0;
504
505 while(p) {
506 if (p->class == class && p->type == type)
507 n++;
508 p = p->next;
509 }
510
511 return (n);
512}
diff --git a/src/lib/libc/net/getservbyname.c b/src/lib/libc/net/getservbyname.c
new file mode 100644
index 0000000000..f1c312ea82
--- /dev/null
+++ b/src/lib/libc/net/getservbyname.c
@@ -0,0 +1,83 @@
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. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char rcsid[] = "$OpenBSD: getservbyname.c,v 1.6 2003/06/02 20:18:35 millert Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <netdb.h>
35#include <string.h>
36#include "thread_private.h"
37
38extern int _serv_stayopen;
39
40_THREAD_PRIVATE_MUTEX(getservbyname_r);
41
42struct servent *
43getservbyname_r(name, proto, se, buf, buflen)
44 const char *name, *proto;
45 struct servent *se;
46 char *buf;
47 int buflen;
48{
49 register struct servent *p;
50 register char **cp;
51
52 _THREAD_PRIVATE_MUTEX_LOCK(getservbyname_r);
53 setservent(_serv_stayopen);
54 while ((p = getservent())) {
55 if (strcmp(name, p->s_name) == 0)
56 goto gotname;
57 for (cp = p->s_aliases; *cp; cp++)
58 if (strcmp(name, *cp) == 0)
59 goto gotname;
60 continue;
61gotname:
62 if (proto == 0 || strcmp(p->s_proto, proto) == 0)
63 break;
64 }
65 if (!_serv_stayopen)
66 endservent();
67 _THREAD_PRIVATE_MUTEX_UNLOCK(getservbyname_r);
68 return (p);
69}
70
71struct servent *getservbyname(name, proto)
72 const char *name, *proto;
73{
74 _THREAD_PRIVATE_KEY(getservbyname);
75 static char buf[4096];
76 char *bufp = (char*)_THREAD_PRIVATE(getservbyname, buf, NULL);
77
78 if (bufp == NULL)
79 return (NULL);
80 return getservbyname_r(name, proto, (struct servent*) bufp,
81 bufp + sizeof(struct servent),
82 sizeof buf - sizeof(struct servent) );
83}
diff --git a/src/lib/libc/net/getservbyport.c b/src/lib/libc/net/getservbyport.c
new file mode 100644
index 0000000000..992a77d638
--- /dev/null
+++ b/src/lib/libc/net/getservbyport.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. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char rcsid[] = "$OpenBSD: getservbyport.c,v 1.4 2003/06/02 20:18:35 millert Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <netdb.h>
35#include <string.h>
36
37extern int _serv_stayopen;
38
39struct servent *
40getservbyport(port, proto)
41 int port;
42 const char *proto;
43{
44 register struct servent *p;
45
46 setservent(_serv_stayopen);
47 while ((p = getservent())) {
48 if (p->s_port != port)
49 continue;
50 if (proto == 0 || strcmp(p->s_proto, proto) == 0)
51 break;
52 }
53 if (!_serv_stayopen)
54 endservent();
55 return (p);
56}
diff --git a/src/lib/libc/net/getservent.3 b/src/lib/libc/net/getservent.3
new file mode 100644
index 0000000000..72201126f8
--- /dev/null
+++ b/src/lib/libc/net/getservent.3
@@ -0,0 +1,137 @@
1.\" $OpenBSD: getservent.3,v 1.12 2003/06/02 20:18:35 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. Neither the name of the University nor the names of its contributors
15.\" may be used to endorse or promote products derived from this software
16.\" without specific prior written permission.
17.\"
18.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28.\" SUCH DAMAGE.
29.\"
30.Dd January 12, 1994
31.Dt GETSERVENT 3
32.Os
33.Sh NAME
34.Nm getservent ,
35.Nm getservbyport ,
36.Nm getservbyname ,
37.Nm setservent ,
38.Nm endservent
39.Nd get service entry
40.Sh SYNOPSIS
41.Fd #include <netdb.h>
42.Ft struct servent *
43.Fn getservent "void"
44.Ft struct servent *
45.Fn getservbyname "char *name" "char *proto"
46.Ft struct servent *
47.Fn getservbyport "int port" "char *proto"
48.Ft void
49.Fn setservent "int stayopen"
50.Ft void
51.Fn endservent "void"
52.Sh DESCRIPTION
53The
54.Fn getservent ,
55.Fn getservbyname ,
56and
57.Fn getservbyport
58functions each return a pointer to an object with the following structure
59containing the broken-out fields of a line in the network services database,
60.Pa /etc/services .
61.Bd -literal -offset indent
62struct servent {
63 char *s_name; /* official name of service */
64 char **s_aliases; /* alias list */
65 int s_port; /* port service resides at */
66 char *s_proto; /* protocol to use */
67};
68.Ed
69.Pp
70The members of this structure are:
71.Bl -tag -width s_aliases
72.It Fa s_name
73The official name of the service.
74.It Fa s_aliases
75A zero-terminated list of alternate names for the service.
76.It Fa s_port
77The port number at which the service resides.
78Port numbers are returned in network byte order.
79.It Fa s_proto
80The name of the protocol to use when contacting the service.
81.El
82.Pp
83The
84.Fn getservent
85function reads the next line of the file, opening the file if necessary.
86.Pp
87The
88.Fn setservent
89function opens and rewinds the file.
90If the
91.Fa stayopen
92flag is non-zero,
93the net database will not be closed after each call to
94.Fn getservbyname
95or
96.Fn getservbyport .
97.Pp
98The
99.Fn endservent
100function closes the file.
101.Pp
102The
103.Fn getservbyname
104and
105.Fn getservbyport
106functions sequentially search from the beginning of the file until a
107matching protocol name or port number (specified in network byte order)
108is found, or until
109.Dv EOF
110is encountered.
111If a protocol name is also supplied (non-null),
112searches must also match the protocol.
113.Sh FILES
114.Bl -tag -width /etc/services -compact
115.It Pa /etc/services
116.El
117.Sh DIAGNOSTICS
118Null pointer (0) returned on
119.Dv EOF
120or error.
121.Sh SEE ALSO
122.Xr getprotoent 3 ,
123.Xr services 5
124.Sh HISTORY
125The
126.Fn getservent ,
127.Fn getservbyport ,
128.Fn getservbyname ,
129.Fn setservent ,
130and
131.Fn endservent
132functions appeared in
133.Bx 4.2 .
134.Sh BUGS
135These functions use static data storage; if the data is needed for future use,
136it should be copied before any subsequent calls overwrite it.
137Expecting 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..bad3316f6c
--- /dev/null
+++ b/src/lib/libc/net/getservent.c
@@ -0,0 +1,125 @@
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. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char rcsid[] = "$OpenBSD: getservent.c,v 1.6 2003/06/02 20:18:35 millert Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <sys/types.h>
35#include <sys/socket.h>
36#include <netdb.h>
37#include <stdio.h>
38#include <string.h>
39#include <stdlib.h>
40
41#define MAXALIASES 35
42
43static FILE *servf = NULL;
44static char line[BUFSIZ+1];
45static struct servent serv;
46static char *serv_aliases[MAXALIASES];
47int _serv_stayopen;
48
49void
50setservent(f)
51 int f;
52{
53 if (servf == NULL)
54 servf = fopen(_PATH_SERVICES, "r" );
55 else
56 rewind(servf);
57 _serv_stayopen |= f;
58}
59
60void
61endservent()
62{
63 if (servf) {
64 fclose(servf);
65 servf = NULL;
66 }
67 _serv_stayopen = 0;
68}
69
70struct servent *
71getservent()
72{
73 char *p, *cp, **q, *endp;
74 long l;
75 size_t len;
76
77 if (servf == NULL && (servf = fopen(_PATH_SERVICES, "r" )) == NULL)
78 return (NULL);
79again:
80 if ((p = fgetln(servf, &len)) == NULL)
81 return (NULL);
82 if (p[len-1] == '\n')
83 len--;
84 if (len >= sizeof(line) || len == 0)
85 goto again;
86 p = memcpy(line, p, len);
87 line[len] = '\0';
88 if (*p == '#')
89 goto again;
90 if ((cp = strchr(p, '#')) != NULL)
91 *cp = '\0';
92 serv.s_name = p;
93 p = strpbrk(p, " \t");
94 if (p == NULL)
95 goto again;
96 *p++ = '\0';
97 while (*p == ' ' || *p == '\t')
98 p++;
99 cp = strpbrk(p, ",/");
100 if (cp == NULL)
101 goto again;
102 *cp++ = '\0';
103 l = strtol(p, &endp, 10);
104 if (endp == p || *endp != '\0' || l < 0 || l > USHRT_MAX)
105 goto again;
106 serv.s_port = htons((in_port_t)l);
107 serv.s_proto = cp;
108 q = serv.s_aliases = serv_aliases;
109 cp = strpbrk(cp, " \t");
110 if (cp != NULL)
111 *cp++ = '\0';
112 while (cp && *cp) {
113 if (*cp == ' ' || *cp == '\t') {
114 cp++;
115 continue;
116 }
117 if (q < &serv_aliases[MAXALIASES - 1])
118 *q++ = cp;
119 cp = strpbrk(cp, " \t");
120 if (cp != NULL)
121 *cp++ = '\0';
122 }
123 *q = NULL;
124 return (&serv);
125}
diff --git a/src/lib/libc/net/herror.c b/src/lib/libc/net/herror.c
new file mode 100644
index 0000000000..e8f6fa28fc
--- /dev/null
+++ b/src/lib/libc/net/herror.c
@@ -0,0 +1,117 @@
1/* $OpenBSD: herror.c,v 1.5 2003/06/02 20:18:35 millert 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. 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)
55#if 0
56static char sccsid[] = "@(#)herror.c 8.1 (Berkeley) 6/4/93";
57static char rcsid[] = "$From: herror.c,v 8.3 1996/08/05 08:31:35 vixie Exp $";
58#else
59static char rcsid[] = "$OpenBSD: herror.c,v 1.5 2003/06/02 20:18:35 millert Exp $";
60#endif
61#endif /* LIBC_SCCS and not lint */
62
63#include <sys/types.h>
64#include <sys/param.h>
65#include <sys/uio.h>
66#include <netdb.h>
67#include <unistd.h>
68#include <string.h>
69
70const char *h_errlist[] = {
71 "Resolver Error 0 (no error)",
72 "Unknown host", /* 1 HOST_NOT_FOUND */
73 "Host name lookup failure", /* 2 TRY_AGAIN */
74 "Unknown server error", /* 3 NO_RECOVERY */
75 "No address associated with name", /* 4 NO_ADDRESS */
76};
77int h_nerr = { sizeof h_errlist / sizeof h_errlist[0] };
78
79extern int h_errno;
80
81/*
82 * herror --
83 * print the error indicated by the h_errno value.
84 */
85void
86herror(s)
87 const char *s;
88{
89 struct iovec iov[4];
90 register struct iovec *v = iov;
91
92 if (s && *s) {
93 v->iov_base = (char *)s;
94 v->iov_len = strlen(s);
95 v++;
96 v->iov_base = ": ";
97 v->iov_len = 2;
98 v++;
99 }
100 v->iov_base = (char *)hstrerror(h_errno);
101 v->iov_len = strlen(v->iov_base);
102 v++;
103 v->iov_base = "\n";
104 v->iov_len = 1;
105 writev(STDERR_FILENO, iov, (v - iov) + 1);
106}
107
108const char *
109hstrerror(err)
110 int err;
111{
112 if (err < 0)
113 return ("Resolver internal error");
114 else if (err < h_nerr)
115 return (h_errlist[err]);
116 return ("Unknown resolver error");
117}
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..30293dcdf2
--- /dev/null
+++ b/src/lib/libc/net/if_indextoname.3
@@ -0,0 +1,136 @@
1.\" $OpenBSD: if_indextoname.3,v 1.7 2003/08/08 09:26:02 jmc 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. Neither the name of the University nor the names of its contributors
14.\" may be used to endorse or promote products derived from this software
15.\" without specific prior written permission.
16.\"
17.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27.\" SUCH DAMAGE.
28.\"
29.\" From: @(#)rcmd.3 8.1 (Berkeley) 6/4/93
30.\"
31.Dd May 21, 1998
32.Dt IF_NAMETOINDEX 3
33.Os
34.Sh NAME
35.Nm if_nametoindex ,
36.Nm if_indextoname ,
37.Nm if_nameindex ,
38.Nm if_freenameindex
39.Nd convert interface index to name, and vice versa
40.Sh SYNOPSIS
41.Fd #include <net/if.h>
42.Ft "unsigned int"
43.Fn if_nametoindex "const char *ifname"
44.Ft "char *"
45.Fn if_indextoname "unsigned int ifindex" "char *ifname"
46.Ft "struct if_nameindex *"
47.Fn if_nameindex "void"
48.Ft "void"
49.Fn if_freenameindex "struct if_nameindex *ptr"
50.Sh DESCRIPTION
51These functions map interface indexes to interface names (such as
52.Dq lo0 ) ,
53and vice versa.
54.Pp
55The
56.Fn if_nametoindex
57function converts an interface name specified by the
58.Fa ifname
59argument to an interface index (positive integer value).
60If the specified interface does not exist, 0 will be returned.
61.Pp
62.Fn if_indextoname
63converts an interface index specified by the
64.Fa ifindex
65argument to an interface name.
66The
67.Fa ifname
68argument must point to a buffer of at least
69.Dv IF_NAMESIZE
70bytes into which the interface name corresponding to the specified index is
71returned.
72.Pf ( Dv IF_NAMESIZE
73is also defined in
74.Aq Pa net/if.h
75and its value includes a terminating null byte at the end of the
76interface name.)
77This pointer is also the return value of the function.
78If there is no interface corresponding to the specified index,
79.Dv NULL
80is returned.
81.Pp
82.Fn if_nameindex
83returns an array of
84.Fa if_nameindex
85structures.
86.Fa if_nametoindex
87is also defined in
88.Aq Pa net/if.h ,
89and is as follows:
90.Bd -literal -offset
91struct if_nameindex {
92 unsigned int if_index; /* 1, 2, ... */
93 char *if_name; /* null terminated name: "le0", ... */
94};
95.Ed
96.Pp
97The end of the array of structures is indicated by a structure with
98an
99.Fa if_index
100of 0 and an
101.Fa if_name
102of
103.Dv NULL .
104The function returns a null pointer on error.
105The memory used for this array of structures along with the interface
106names pointed to by the
107.Fa if_name
108members is obtained dynamically.
109This memory is freed by the
110.Fn if_freenameindex
111function.
112.Pp
113.Fn if_freenameindex
114takes a pointer that was returned by
115.Fn if_nameindex
116as argument
117.Pq Fa ptr ,
118and it reclaims the region allocated.
119.Sh DIAGNOSTICS
120.Fn if_nametoindex
121returns 0 on error, positive integer on success.
122.Fn if_indextoname
123and
124.Fn if_nameindex
125return
126.Dv NULL
127on errors.
128.Sh SEE ALSO
129.Xr getifaddrs 3 ,
130.Xr networking 4
131.Pp
132R. Gilligan, S. Thomson, J. Bound, and W. Stevens,
133``Basic Socket Interface Extensions for IPv6,'' RFC 2553, March 1999.
134.Sh STANDARDS
135These functions are defined in ``Basic Socket Interface Extensions for IPv6''
136.Pq RFC 2533 .
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..43cb5bafd7
--- /dev/null
+++ b/src/lib/libc/net/inet.3
@@ -0,0 +1,355 @@
1.\" $OpenBSD: inet.3,v 1.18 2003/09/09 12:00:39 jmc 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. Neither the name of the University 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 REGENTS 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 REGENTS 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.\" @(#)inet.3 8.1 (Berkeley) 6/4/93
32.\"
33.Dd June 18, 1997
34.Dt INET 3
35.Os
36.Sh NAME
37.Nm inet_addr ,
38.Nm inet_aton ,
39.Nm inet_lnaof ,
40.Nm inet_makeaddr ,
41.Nm inet_netof ,
42.Nm inet_network ,
43.Nm inet_ntoa ,
44.Nm inet_ntop ,
45.Nm inet_pton
46.Nd Internet address manipulation routines
47.Sh SYNOPSIS
48.Fd #include <sys/types.h>
49.Fd #include <sys/socket.h>
50.Fd #include <netinet/in.h>
51.Fd #include <arpa/inet.h>
52.Ft in_addr_t
53.Fn inet_addr "const char *cp"
54.Ft int
55.Fn inet_aton "const char *cp" "struct in_addr *addr"
56.Ft in_addr_t
57.Fn inet_lnaof "struct in_addr in"
58.Ft struct in_addr
59.Fn inet_makeaddr "in_addr_t net" "in_addr_t lna"
60.Ft in_addr_t
61.Fn inet_netof "struct in_addr in"
62.Ft in_addr_t
63.Fn inet_network "const char *cp"
64.Ft char *
65.Fn inet_ntoa "struct in_addr in"
66.Ft const char *
67.Fn inet_ntop "int af" "const void *src" "char *dst" "size_t size"
68.Ft int
69.Fn inet_pton "int af" "const char *src" "void *dst"
70.Sh DESCRIPTION
71The routines
72.Fn inet_aton ,
73.Fn inet_addr
74and
75.Fn inet_network
76interpret character strings representing
77numbers expressed in the Internet standard
78.Ql \&.
79notation.
80The
81.Fn inet_pton
82function converts a presentation format address (that is, printable form
83as held in a character string) to network format (usually a
84.Li struct in_addr
85or some other internal binary representation, in network byte order).
86It returns 1 if the address was valid for the specified address family, or
870 if the address wasn't parseable in the specified address family, or \-1
88if some system error occurred (in which case
89.Va errno
90will have been set).
91This function is presently valid for
92.Dv AF_INET
93and
94.Dv AF_INET6 .
95The
96.Fn inet_aton
97routine interprets the specified character string as an Internet address,
98placing the address into the structure provided.
99It returns 1 if the string was successfully interpreted,
100or 0 if the string was invalid.
101The
102.Fn inet_addr
103and
104.Fn inet_network
105functions return numbers suitable for use
106as Internet addresses and Internet network
107numbers, respectively.
108.Pp
109The function
110.Fn inet_ntop
111converts an address from network format (usually a
112.Li struct in_addr
113or some other binary form, in network byte order) to presentation format
114(suitable for external display purposes).
115It returns
116.Dv NULL
117if a system
118error occurs (in which case,
119.Va errno
120will have been set), or it returns a pointer to the destination string.
121The routine
122.Fn inet_ntoa
123takes an Internet address and returns an
124.Tn ASCII
125string representing the address in
126.Ql \&.
127notation.
128The routine
129.Fn inet_makeaddr
130takes an Internet network number and a local
131network address and constructs an Internet address
132from it.
133The routines
134.Fn inet_netof
135and
136.Fn inet_lnaof
137break apart Internet host addresses, returning
138the network number and local network address part,
139respectively.
140.Pp
141All Internet addresses are returned in network
142order (bytes ordered from left to right).
143All network numbers and local address parts are
144returned as machine format integer values.
145.Sh INTERNET ADDRESSES (IP VERSION 4)
146Values specified using the
147.Ql \&.
148notation take one
149of the following forms:
150.Bd -literal -offset indent
151a.b.c.d
152a.b.c
153a.b
154a
155.Ed
156.Pp
157When four parts are specified, each is interpreted
158as a byte of data and assigned, from left to right,
159to the four bytes of an Internet address.
160Note that when an Internet address is viewed as a 32-bit
161integer quantity on a system that uses little-endian
162byte order (such as the
163.Tn Intel 386, 486
164and
165.Tn Pentium
166processors) the bytes referred to above appear as
167.Dq Li d.c.b.a .
168That is, little-endian bytes are ordered from right to left.
169.Pp
170When a three part address is specified, the last
171part is interpreted as a 16-bit quantity and placed
172in the rightmost two bytes of the network address.
173This makes the three part address format convenient
174for specifying Class B network addresses as
175.Dq Li 128.net.host .
176.Pp
177When a two part address is supplied, the last part
178is interpreted as a 24-bit quantity and placed in
179the rightmost three bytes of the network address.
180This makes the two part address format convenient
181for specifying Class A network addresses as
182.Dq Li net.host .
183.Pp
184When only one part is given, the value is stored
185directly in the network address without any byte
186rearrangement.
187.Pp
188All numbers supplied as
189.Dq parts
190in a
191.Ql \&.
192notation
193may be decimal, octal, or hexadecimal, as specified
194in the C language (i.e., a leading 0x or 0X implies
195hexadecimal; otherwise, a leading 0 implies octal;
196otherwise, the number is interpreted as decimal).
197.Sh INTERNET ADDRESSES (IP VERSION 6)
198In order to support scoped IPv6 addresses,
199.Xr getaddrinfo 3
200and
201.Xr getnameinfo 3
202are recommended rather than the functions presented here.
203.Pp
204The presentation format of an IPv6 address is given in RFC 2373:
205.Pp
206There are three conventional forms for representing IPv6 addresses as
207text strings:
208.Bl -enum
209.It
210The preferred form is x:x:x:x:x:x:x:x, where the 'x's are the
211hexadecimal values of the eight 16-bit pieces of the address.
212Examples:
213.Bd -literal -offset indent
214FEDC:BA98:7654:3210:FEDC:BA98:7654:3210
2151080:0:0:0:8:800:200C:417A
216.Ed
217.Pp
218Note that it is not necessary to write the leading zeros in an
219individual field, but there must be at least one numeral in
220every field (except for the case described in 2.).
221.It
222Due to the method of allocating certain styles of IPv6
223addresses, it will be common for addresses to contain long
224strings of zero bits.
225In order to make writing addresses
226containing zero bits easier, a special syntax is available to
227compress the zeros.
228The use of
229.Dq \&:\&:
230indicates multiple groups
231of 16 bits of zeros.
232The
233.Dq \&:\&:
234can only appear once in an
235address.
236The
237.Dq \&:\&:
238can also be used to compress the leading and/or trailing zeros in an address.
239.Pp
240For example the following addresses:
241.Bd -literal -offset indent
2421080:0:0:0:8:800:200C:417A a unicast address
243FF01:0:0:0:0:0:0:43 a multicast address
2440:0:0:0:0:0:0:1 the loopback address
2450:0:0:0:0:0:0:0 the unspecified addresses
246.Ed
247.Pp
248may be represented as:
249.Bd -literal -offset indent
2501080::8:800:200C:417A a unicast address
251FF01::43 a multicast address
252::1 the loopback address
253:: the unspecified addresses
254.Ed
255.It
256An alternative form that is sometimes more convenient when
257dealing with a mixed environment of IPv4 and IPv6 nodes is
258x:x:x:x:x:x:d.d.d.d, where the 'x's are the hexadecimal values
259of the six high-order 16-bit pieces of the address, and the 'd's
260are the decimal values of the four low-order 8-bit pieces of the
261address (standard IPv4 representation).
262Examples:
263.Bd -literal -offset indent
2640:0:0:0:0:0:13.1.68.3
2650:0:0:0:0:FFFF:129.144.52.38
266.Ed
267.Pp
268or in compressed form:
269.Bd -literal -offset indent
270::13.1.68.3
271::FFFF:129.144.52.38
272.Ed
273.El
274.Sh DIAGNOSTICS
275The constant
276.Dv INADDR_NONE
277is returned by
278.Fn inet_addr
279and
280.Fn inet_network
281for malformed requests.
282.Sh SEE ALSO
283.Xr byteorder 3 ,
284.Xr gethostbyname 3 ,
285.Xr getnetent 3 ,
286.Xr inet_net 3 ,
287.Xr hosts 5 ,
288.Xr networks 5
289.Rs
290.%R RFC 2373
291.%D July 1998
292.%T "IP Version 6 Addressing Architecture"
293.Re
294.Rs
295.%R RFC 3493
296.%D February 2003
297.%T "Basic Socket Interface Extensions for IPv6"
298.Re
299.Sh STANDARDS
300The
301.Nm inet_ntop
302and
303.Nm inet_pton
304functions conform to the IETF IPv6 BSD API and address formatting
305specifications.
306Note that
307.Nm inet_pton
308does not accept 1-, 2-, or 3-part dotted addresses; all four parts
309must be specified.
310This is a narrower input set than that accepted by
311.Nm inet_aton .
312.Sh HISTORY
313The
314.Nm inet_addr ,
315.Nm inet_network ,
316.Nm inet_makeaddr ,
317.Nm inet_lnaof
318and
319.Nm inet_netof
320functions appeared in
321.Bx 4.2 .
322The
323.Nm inet_aton
324and
325.Nm inet_ntoa
326functions appeared in
327.Bx 4.3 .
328The
329.Nm inet_pton
330and
331.Nm inet_ntop
332functions appeared in BIND 4.9.4.
333.Sh BUGS
334The value
335.Dv INADDR_NONE
336(0xffffffff) is a valid broadcast address, but
337.Fn inet_addr
338cannot return that value without indicating failure.
339Also,
340.Fn inet_addr
341should have been designed to return a
342.Li struct in_addr .
343The newer
344.Fn inet_aton
345function does not share these problems, and almost all existing code
346should be modified to use
347.Fn inet_aton
348instead.
349.Pp
350The problem of host byte ordering versus network byte ordering is
351confusing.
352.Pp
353The string returned by
354.Fn inet_ntoa
355resides 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..4e5dc22711
--- /dev/null
+++ b/src/lib/libc/net/inet6_option_space.3
@@ -0,0 +1,444 @@
1.\" $OpenBSD: inet6_option_space.3,v 1.13 2003/08/08 09:26:02 jmc 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. Neither the name of the University 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 REGENTS 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 REGENTS 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.Dd December 10, 1999
32.Dt INET6_OPTION_SPACE 3
33.Os
34.\"
35.Sh NAME
36.Nm inet6_option_space ,
37.Nm inet6_option_init ,
38.Nm inet6_option_append ,
39.Nm inet6_option_alloc ,
40.Nm inet6_option_next ,
41.Nm inet6_option_find
42.Nd IPv6 Hop-by-Hop and Destination Options manipulation
43.\"
44.Sh SYNOPSIS
45.Fd #include <netinet/in.h>
46.Ft "int"
47.Fn inet6_option_space "int nbytes"
48.Ft "int"
49.Fn inet6_option_init "void *bp" "struct cmsghdr **cmsgp" "int type"
50.Ft "int"
51.Fn inet6_option_append "struct cmsghdr *cmsg" "const u_int8_t *typep" "int multx" "int plusy"
52.Ft "u_int8_t *"
53.Fn inet6_option_alloc "struct cmsghdr *cmsg" "int datalen" "int multx" "int plusy"
54.Ft "int"
55.Fn inet6_option_next "const struct cmsghdr *cmsg" "u_int8_t **tptrp"
56.Ft "int"
57.Fn inet6_option_find "const struct cmsghdr *cmsg" "u_int8_t **tptrp" "int type"
58.\"
59.Sh DESCRIPTION
60.\"
61Building and parsing the Hop-by-Hop and Destination options is
62complicated due to alignment constraints, padding and
63ancillary data manipulation.
64RFC 2292 defines a set of functions to help the application.
65The function prototypes for
66these functions are all in the
67.Aq Pa netinet/in.h
68header.
69.\"
70.Ss inet6_option_space
71.Fn inet6_option_space
72returns the number of bytes required to hold an option when it is stored as
73ancillary data, including the
74.Li cmsghdr
75structure at the beginning,
76and any padding at the end
77.Po
78to make its size a multiple of 8 bytes
79.Pc .
80The argument is the size of the structure defining the option,
81which must include any pad bytes at the beginning
82.Po
83the value
84.Li y
85in the alignment term
86.Dq Li xn + y
87.Pc ,
88the type byte, the length byte, and the option data.
89.Pp
90Note: If multiple options are stored in a single ancillary data
91object, which is the recommended technique, this function
92overestimates the amount of space required by the size of
93.Li N-1
94.Li cmsghdr
95structures,
96where
97.Li N
98is the number of options to be stored in the object.
99This is of little consequence, since it is assumed that most
100Hop-by-Hop option headers and Destination option headers carry only
101one option
102.Pq appendix B of [RFC 2460] .
103.\"
104.Ss inet6_option_init
105.Fn inet6_option_init
106is called once per ancillary data object that will
107contain either Hop-by-Hop or Destination options.
108It returns
109.Li 0
110on success or
111.Li -1
112on an error.
113.Pp
114.Fa bp
115is a pointer to previously allocated space that will contain the
116ancillary data object.
117It must be large enough to contain all the
118individual options to be added by later calls to
119.Fn inet6_option_append
120and
121.Fn inet6_option_alloc .
122.Pp
123.Fa cmsgp
124is a pointer to a pointer to a
125.Li cmsghdr
126structure.
127.Fa *cmsgp
128is initialized by this function to point to the
129.Li cmsghdr
130structure constructed by this function in the buffer pointed to by
131.Fa bp .
132.Pp
133.Fa type
134is either
135.Dv IPV6_HOPOPTS
136or
137.Dv IPV6_DSTOPTS .
138This
139.Fa type
140is stored in the
141.Li cmsg_type
142member of the
143.Li cmsghdr
144structure pointed to by
145.Fa *cmsgp .
146.\"
147.Ss inet6_option_append
148This function appends a Hop-by-Hop option or a Destination option
149into an ancillary data object that has been initialized by
150.Fn inet6_option_init .
151This function returns
152.Li 0
153if it succeeds or
154.Li -1
155on an error.
156.Pp
157.Fa cmsg
158is a pointer to the
159.Li cmsghdr
160structure that must have been
161initialized by
162.Fn inet6_option_init .
163.Pp
164.Fa typep
165is a pointer to the 8-bit option type.
166It is assumed that this
167field is immediately followed by the 8-bit option data length field,
168which is then followed immediately by the option data.
169The caller
170initializes these three fields
171.Pq the type-length-value, or TLV
172before calling this function.
173.Pp
174The option type must have a value from
175.Li 2
176to
177.Li 255 ,
178inclusive.
179.Po
180.Li 0
181and
182.Li 1
183are reserved for the
184.Li Pad1
185and
186.Li PadN
187options, respectively.
188.Pc
189.Pp
190The option data length must have a value between
191.Li 0
192and
193.Li 255 ,
194inclusive, and is the length of the option data that follows.
195.Pp
196.Fa multx
197is the value
198.Li x
199in the alignment term
200.Dq Li xn + y .
201It must have a value of
202.Li 1 ,
203.Li 2 ,
204.Li 4 ,
205or
206.Li 8 .
207.Pp
208.Fa plusy
209is the value
210.Li y
211in the alignment term
212.Dq Li xn + y .
213It must have a value between
214.Li 0
215and
216.Li 7 ,
217inclusive.
218.\"
219.Ss inet6_option_alloc
220This function appends a Hop-by-Hop option or a Destination option
221into an ancillary data object that has been initialized by
222.Fn inet6_option_init .
223This function returns a pointer to the 8-bit
224option type field that starts the option on success, or
225.Dv NULL
226on an error.
227.Pp
228The difference between this function and
229.Fn inet6_option_append
230is that the latter copies the contents of a previously built option into
231the ancillary data object while the current function returns a
232pointer to the space in the data object where the option's TLV must
233then be built by the caller.
234.Pp
235.Fa cmsg
236is a pointer to the
237.Li cmsghdr
238structure that must have been
239initialized by
240.Fn inet6_option_init .
241.Pp
242.Fa datalen
243is the value of the option data length byte for this option.
244This value is required as an argument to allow the function to
245determine if padding must be appended at the end of the option.
246(The
247.Fn inet6_option_append
248function does not need a data length argument
249since the option data length must already be stored by the caller.)
250.Pp
251.Fa multx
252is the value
253.Li x
254in the alignment term
255.Dq Li xn + y .
256It must have a value of
257.Li 1 ,
258.Li 2 ,
259.Li 4 ,
260or
261.Li 8 .
262.Pp
263.Fa plusy
264is the value
265.Li y
266in the alignment term
267.Dq Li xn + y .
268It must have a value between
269.Li 0
270and
271.Li 7 ,
272inclusive.
273.\"
274.Ss inet6_option_next
275This function processes the next Hop-by-Hop option or Destination
276option in an ancillary data object.
277If another option remains to be
278processed, the return value of the function is
279.Li 0
280and
281.Fa *tptrp
282points to
283the 8-bit option type field
284(which is followed by the 8-bit option
285data length, followed by the option data).
286If no more options remain
287to be processed, the return value is
288.Li -1
289and
290.Fa *tptrp
291is
292.Dv NULL .
293If an error occurs, the return value is
294.Li -1
295and
296.Fa *tptrp
297is not
298.Dv NULL .
299.Pp
300.Fa cmsg
301is a pointer to
302.Li cmsghdr
303structure of which
304.Li cmsg_level
305equals
306.Dv IPPROTO_IPV6
307and
308.Li cmsg_type
309equals either
310.Dv IPV6_HOPOPTS
311or
312.Dv IPV6_DSTOPTS .
313.Pp
314.Fa tptrp
315is a pointer to a pointer to an 8-bit byte and
316.Fa *tptrp
317is used
318by the function to remember its place in the ancillary data object
319each time the function is called.
320The first time this function is
321called for a given ancillary data object,
322.Fa *tptrp
323must be set to
324.Dv NULL .
325.Pp
326Each time this function returns success,
327.Fa *tptrp
328points to the 8-bit
329option type field for the next option to be processed.
330.\"
331.Ss inet6_option_find
332This function is similar to the previously described
333.Fn inet6_option_next
334function, except this function lets the caller
335specify the option type to be searched for, instead of always
336returning the next option in the ancillary data object.
337.Fa cmsg
338is a
339pointer to
340.Li cmsghdr
341structure of which
342.Li cmsg_level
343equals
344.Dv IPPROTO_IPV6
345and
346.Li cmsg_type
347equals either
348.Dv IPV6_HOPOPTS
349or
350.Dv IPV6_DSTOPTS .
351.Pp
352.Fa tptrp
353is a pointer to a pointer to an 8-bit byte and
354.Fa *tptrp
355is used
356by the function to remember its place in the ancillary data object
357each time the function is called.
358The first time this function is
359called for a given ancillary data object,
360.Fa *tptrp
361must be set to
362.Dv NULL .
363.Pp
364This function starts searching for an option of the specified type
365beginning after the value of
366.Fa *tptrp .
367If an option of the specified
368type is located, this function returns
369.Li 0
370and
371.Fa *tptrp
372points to the 8-
373bit option type field for the option of the specified type.
374If an
375option of the specified type is not located, the return value is
376.Li -1
377and
378.Fa *tptrp
379is
380.Dv NULL .
381If an error occurs, the return value is
382.Li -1
383and
384.Fa *tptrp
385is not
386.Dv NULL .
387.\"
388.Sh EXAMPLES
389RFC 2292 gives comprehensive examples in chapter 6.
390.\"
391.Sh DIAGNOSTICS
392.Fn inet6_option_init
393and
394.Fn inet6_option_append
395return
396.Li 0
397on success or
398.Li -1
399on an error.
400.Pp
401.Fn inet6_option_alloc
402returns
403.Dv NULL
404on an error.
405.Pp
406On errors,
407.Fn inet6_option_next
408and
409.Fn inet6_option_find
410return
411.Li -1
412setting
413.Fa *tptrp
414to non
415.Dv NULL
416value.
417.\"
418.Sh SEE ALSO
419.Rs
420.%A W. Stevens
421.%A M. Thomas
422.%T "Advanced Sockets API for IPv6"
423.%N RFC 2292
424.%D February 1998
425.Re
426.Rs
427.%A S. Deering
428.%A R. Hinden
429.%T "Internet Protocol, Version 6 (IPv6) Specification"
430.%N RFC 2460
431.%D December 1998
432.Re
433.\"
434.Sh STANDARDS
435The functions
436are documented in
437.Dq Advanced Sockets API for IPv6
438.Pq RFC 2292 .
439.\"
440.Sh HISTORY
441The implementation first appeared in KAME advanced networking kit.
442.\"
443.Sh BUGS
444The text was shamelessly copied from RFC 2292.
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..33b209af4f
--- /dev/null
+++ b/src/lib/libc/net/inet6_rthdr_space.3
@@ -0,0 +1,317 @@
1.\" $OpenBSD: inet6_rthdr_space.3,v 1.13 2003/08/08 09:26:02 jmc 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. Neither the name of the University 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 REGENTS 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 REGENTS 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.Dd December 10, 1999
32.Dt INET6_RTHDR_SPACE 3
33.Os
34.\"
35.Sh NAME
36.Nm inet6_rthdr_space ,
37.Nm inet6_rthdr_init ,
38.Nm inet6_rthdr_add ,
39.Nm inet6_rthdr_lasthop ,
40.Nm inet6_rthdr_reverse ,
41.Nm inet6_rthdr_segments ,
42.Nm inet6_rthdr_getaddr ,
43.Nm inet6_rthdr_getflags
44.Nd IPv6 Routing Header Options manipulation
45.\"
46.Sh SYNOPSIS
47.Fd #include <netinet/in.h>
48.Ft size_t
49.Fn inet6_rthdr_space "int type" "int segments"
50.Ft "struct cmsghdr *"
51.Fn inet6_rthdr_init "void *bp" "int type"
52.Ft int
53.Fn inet6_rthdr_add "struct cmsghdr *cmsg" "const struct in6_addr *addr" "unsigned int flags"
54.Ft int
55.Fn inet6_rthdr_lasthop "struct cmsghdr *cmsg" "unsigned int flags"
56.Ft int
57.Fn inet6_rthdr_reverse "const struct cmsghdr *in" "struct cmsghdr *out"
58.Ft int
59.Fn inet6_rthdr_segments "const struct cmsghdr *cmsg"
60.Ft "struct in6_addr *"
61.Fn inet6_rthdr_getaddr "struct cmsghdr *cmsg" "int index"
62.Ft int
63.Fn inet6_rthdr_getflags "const struct cmsghdr *cmsg" "int index"
64.\"
65.Sh DESCRIPTION
66RFC 2292 IPv6 advanced API defines eight
67functions that the application calls to build and examine a Routing
68header.
69Four functions build a Routing header:
70.Bl -hang
71.It Fn inet6_rthdr_space
72return #bytes required for ancillary data
73.It Fn inet6_rthdr_init
74initialize ancillary data for Routing header
75.It Fn inet6_rthdr_add
76add IPv6 address & flags to Routing header
77.It Fn inet6_rthdr_lasthop
78specify the flags for the final hop
79.El
80.Pp
81Four functions deal with a returned Routing header:
82.Bl -hang
83.It Fn inet6_rthdr_reverse
84reverse a Routing header
85.It Fn inet6_rthdr_segments
86return #segments in a Routing header
87.It Fn inet6_rthdr_getaddr
88fetch one address from a Routing header
89.It Fn inet6_rthdr_getflags
90fetch one flag from a Routing header
91.El
92.Pp
93The function prototypes for these functions are all in the
94.Aq Pa netinet/in.h
95header.
96.\"
97.Ss inet6_rthdr_space
98This function returns the number of bytes required to hold a Routing
99header of the specified
100.Fa type
101containing the specified number of
102.Fa segments
103.Pq addresses .
104For an IPv6 Type 0 Routing header, the number
105of segments must be between 1 and 23, inclusive.
106The return value
107includes the size of the cmsghdr structure that precedes the Routing
108header, and any required padding.
109.Pp
110If the return value is 0, then either the type of the Routing header
111is not supported by this implementation or the number of segments is
112invalid for this type of Routing header.
113.Pp
114Note: This function returns the size but does not allocate the space
115required for the ancillary data.
116This allows an application to
117allocate a larger buffer, if other ancillary data objects are
118desired, since all the ancillary data objects must be specified to
119.Xr sendmsg 2
120as a single
121.Li msg_control
122buffer.
123.\"
124.Ss inet6_rthdr_init
125This function initializes the buffer pointed to by
126.Fa bp
127to contain a
128.Li cmsghdr
129structure followed by a Routing header of the specified
130.Fa type .
131The
132.Li cmsg_len
133member of the
134.Li cmsghdr
135structure is initialized to the
136size of the structure plus the amount of space required by the
137Routing header.
138The
139.Li cmsg_level
140and
141.Li cmsg_type
142members are also initialized as required.
143.Pp
144The caller must allocate the buffer and its size can be determined by
145calling
146.Fn inet6_rthdr_space .
147.Pp
148Upon success the return value is the pointer to the
149.Li cmsghdr
150structure, and this is then used as the first argument to the next
151two functions.
152Upon an error the return value is
153.Dv NULL .
154.\"
155.Ss inet6_rthdr_add
156This function adds the address pointed to by
157.Fa addr
158to the end of the
159Routing header being constructed and sets the type of this hop to the
160value of
161.Fa flags .
162For an IPv6 Type 0 Routing header,
163.Fa flags
164must be
165either
166.Dv IPV6_RTHDR_LOOSE
167or
168.Dv IPV6_RTHDR_STRICT .
169.Pp
170If successful, the
171.Li cmsg_len
172member of the
173.Li cmsghdr
174structure is
175updated to account for the new address in the Routing header and the
176return value of the function is 0.
177Upon an error the return value of
178the function is -1.
179.\"
180.Ss inet6_rthdr_lasthop
181This function specifies the Strict/Loose flag for the final hop of a
182Routing header.
183For an IPv6 Type 0 Routing header,
184.Fa flags
185must be either
186.Dv IPV6_RTHDR_LOOSE
187or
188.Dv IPV6_RTHDR_STRICT .
189.Pp
190The return value of the function is 0 upon success, or -1 upon an error.
191.Pp
192Notice that a Routing header specifying
193.Li N
194intermediate nodes requires
195.Li N+1
196Strict/Loose flags.
197This requires
198.Li N
199calls to
200.Fn inet6_rthdr_add
201followed by one call to
202.Fn inet6_rthdr_lasthop .
203.\"
204.Ss inet6_rthdr_reverse
205This function takes a Routing header that was received as ancillary
206data
207.Po
208pointed to by the first argument,
209.Fa in
210.Pc
211and writes a new Routing
212header that sends datagrams along the reverse of that route.
213Both
214arguments are allowed to point to the same buffer
215.Pq that is, the reversal can occur in place .
216.Pp
217The return value of the function is 0 on success, or -1 upon an
218error.
219.\"
220.Ss inet6_rthdr_segments
221This function returns the number of segments
222.Pq addresses
223contained in
224the Routing header described by
225.Fa cmsg .
226On success the return value is
227between 1 and 23, inclusive.
228The return value of the function is -1 upon an error.
229.\"
230.Ss inet6_rthdr_getaddr
231This function returns a pointer to the IPv6 address specified by
232.Fa index
233(which must have a value between 1 and the value returned by
234.Fn inet6_rthdr_segments )
235in the Routing header described by
236.Fa cmsg .
237An
238application should first call
239.Fn inet6_rthdr_segments
240to obtain the number of segments in the Routing header.
241.Pp
242Upon an error the return value of the function is
243.Dv NULL .
244.\"
245.Ss inet6_rthdr_getflags
246This function returns the flags value specified by
247.Fa index
248(which must
249have a value between 0 and the value returned by
250.Fn inet6_rthdr_segments )
251in the Routing header described by
252.Fa cmsg .
253For an IPv6 Type 0 Routing header the return value will be either
254.Dv IPV6_RTHDR_LOOSE
255or
256.Dv IPV6_RTHDR_STRICT .
257.Pp
258Upon an error the return value of the function is -1.
259.Pp
260Note: Addresses are indexed starting at 1, and flags starting at 0,
261to maintain consistency with the terminology and figures in RFC 2460.
262.\"
263.Sh EXAMPLES
264RFC 2292 gives comprehensive examples in chapter 8.
265.\"
266.Sh DIAGNOSTICS
267.Fn inet6_rthdr_space
268returns 0 on errors.
269.Pp
270.Fn inet6_rthdr_add ,
271.Fn inet6_rthdr_lasthop
272and
273.Fn inet6_rthdr_reverse
274return 0 on success, and returns -1 on error.
275.Pp
276.Fn inet6_rthdr_init
277and
278.Fn inet6_rthdr_getaddr
279return
280.Dv NULL
281on error.
282.Pp
283.Fn inet6_rthdr_segments
284and
285.Fn inet6_rthdr_getflags
286return -1 on error.
287.\"
288.Sh SEE ALSO
289.Rs
290.%A W. Stevens
291.%A M. Thomas
292.%T "Advanced Sockets API for IPv6"
293.%N RFC 2292
294.%D February 1998
295.Re
296.Rs
297.%A S. Deering
298.%A R. Hinden
299.%T "Internet Protocol, Version 6 (IPv6) Specification"
300.%N RFC 2460
301.%D December 1998
302.Re
303.\"
304.Sh STANDARDS
305The functions
306are documented in
307.Dq Advanced Sockets API for IPv6
308.Pq RFC 2292 .
309.\"
310.Sh HISTORY
311The implementation first appeared in KAME advanced networking kit.
312.\"
313.Sh BUGS
314The text was shamelessly copied from RFC 2292.
315.Pp
316.Fn inet6_rthdr_reverse
317is 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..716dcb6f80
--- /dev/null
+++ b/src/lib/libc/net/inet_addr.c
@@ -0,0 +1,183 @@
1/* $OpenBSD: inet_addr.c,v 1.7 2003/06/02 20:18:35 millert 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. 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)
55#if 0
56static char sccsid[] = "@(#)inet_addr.c 8.1 (Berkeley) 6/17/93";
57static char rcsid[] = "$From: inet_addr.c,v 8.5 1996/08/05 08:31:35 vixie Exp $";
58#else
59static char rcsid[] = "$OpenBSD: inet_addr.c,v 1.7 2003/06/02 20:18:35 millert Exp $";
60#endif
61#endif /* LIBC_SCCS and not lint */
62
63#include <sys/types.h>
64#include <sys/param.h>
65#include <netinet/in.h>
66#include <arpa/inet.h>
67#include <ctype.h>
68
69/*
70 * Ascii internet address interpretation routine.
71 * The value returned is in network order.
72 */
73in_addr_t
74inet_addr(cp)
75 register const char *cp;
76{
77 struct in_addr val;
78
79 if (inet_aton(cp, &val))
80 return (val.s_addr);
81 return (INADDR_NONE);
82}
83
84/*
85 * Check whether "cp" is a valid ascii representation
86 * of an Internet address and convert to a binary address.
87 * Returns 1 if the address is valid, 0 if not.
88 * This replaces inet_addr, the return value from which
89 * cannot distinguish between failure and a local broadcast address.
90 */
91int
92inet_aton(cp, addr)
93 register const char *cp;
94 struct in_addr *addr;
95{
96 register in_addr_t val;
97 register int base, n;
98 register char c;
99 u_int parts[4];
100 register u_int *pp = parts;
101
102 c = *cp;
103 for (;;) {
104 /*
105 * Collect number up to ``.''.
106 * Values are specified as for C:
107 * 0x=hex, 0=octal, isdigit=decimal.
108 */
109 if (!isdigit(c))
110 return (0);
111 val = 0; base = 10;
112 if (c == '0') {
113 c = *++cp;
114 if (c == 'x' || c == 'X')
115 base = 16, c = *++cp;
116 else
117 base = 8;
118 }
119 for (;;) {
120 if (isascii(c) && isdigit(c)) {
121 val = (val * base) + (c - '0');
122 c = *++cp;
123 } else if (base == 16 && isascii(c) && isxdigit(c)) {
124 val = (val << 4) |
125 (c + 10 - (islower(c) ? 'a' : 'A'));
126 c = *++cp;
127 } else
128 break;
129 }
130 if (c == '.') {
131 /*
132 * Internet format:
133 * a.b.c.d
134 * a.b.c (with c treated as 16 bits)
135 * a.b (with b treated as 24 bits)
136 */
137 if (pp >= parts + 3)
138 return (0);
139 *pp++ = val;
140 c = *++cp;
141 } else
142 break;
143 }
144 /*
145 * Check for trailing characters.
146 */
147 if (c != '\0' && (!isascii(c) || !isspace(c)))
148 return (0);
149 /*
150 * Concoct the address according to
151 * the number of parts specified.
152 */
153 n = pp - parts + 1;
154 switch (n) {
155
156 case 0:
157 return (0); /* initial nondigit */
158
159 case 1: /* a -- 32 bits */
160 break;
161
162 case 2: /* a.b -- 8.24 bits */
163 if ((val > 0xffffff) || (parts[0] > 0xff))
164 return (0);
165 val |= parts[0] << 24;
166 break;
167
168 case 3: /* a.b.c -- 8.8.16 bits */
169 if ((val > 0xffff) || (parts[0] > 0xff) || (parts[1] > 0xff))
170 return (0);
171 val |= (parts[0] << 24) | (parts[1] << 16);
172 break;
173
174 case 4: /* a.b.c.d -- 8.8.8.8 bits */
175 if ((val > 0xff) || (parts[0] > 0xff) || (parts[1] > 0xff) || (parts[2] > 0xff))
176 return (0);
177 val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
178 break;
179 }
180 if (addr)
181 addr->s_addr = htonl(val);
182 return (1);
183}
diff --git a/src/lib/libc/net/inet_lnaof.c b/src/lib/libc/net/inet_lnaof.c
new file mode 100644
index 0000000000..c1e9780cda
--- /dev/null
+++ b/src/lib/libc/net/inet_lnaof.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. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char rcsid[] = "$OpenBSD: inet_lnaof.c,v 1.4 2003/06/02 20:18:35 millert Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <sys/param.h>
35#include <netinet/in.h>
36#include <arpa/inet.h>
37
38/*
39 * Return the local network address portion of an
40 * internet address; handles class a/b/c network
41 * number formats.
42 */
43in_addr_t
44inet_lnaof(in)
45 struct in_addr in;
46{
47 register in_addr_t i = ntohl(in.s_addr);
48
49 if (IN_CLASSA(i))
50 return ((i)&IN_CLASSA_HOST);
51 else if (IN_CLASSB(i))
52 return ((i)&IN_CLASSB_HOST);
53 else
54 return ((i)&IN_CLASSC_HOST);
55}
diff --git a/src/lib/libc/net/inet_makeaddr.c b/src/lib/libc/net/inet_makeaddr.c
new file mode 100644
index 0000000000..a6b59707fa
--- /dev/null
+++ b/src/lib/libc/net/inet_makeaddr.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. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char rcsid[] = "$OpenBSD: inet_makeaddr.c,v 1.4 2003/06/02 20:18:35 millert Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <sys/param.h>
35#include <netinet/in.h>
36#include <arpa/inet.h>
37
38/*
39 * Formulate an Internet address from network + host. Used in
40 * building addresses stored in the ifnet structure.
41 */
42struct in_addr
43inet_makeaddr(net, host)
44 in_addr_t net, host;
45{
46 in_addr_t addr;
47
48 if (net < 128)
49 addr = (net << IN_CLASSA_NSHIFT) | (host & IN_CLASSA_HOST);
50 else if (net < 65536)
51 addr = (net << IN_CLASSB_NSHIFT) | (host & IN_CLASSB_HOST);
52 else if (net < 16777216L)
53 addr = (net << IN_CLASSC_NSHIFT) | (host & IN_CLASSC_HOST);
54 else
55 addr = net | host;
56 addr = htonl(addr);
57 return (*(struct in_addr *)&addr);
58}
diff --git a/src/lib/libc/net/inet_net.3 b/src/lib/libc/net/inet_net.3
new file mode 100644
index 0000000000..c14fa52e38
--- /dev/null
+++ b/src/lib/libc/net/inet_net.3
@@ -0,0 +1,181 @@
1.\" $OpenBSD: inet_net.3,v 1.10 2003/05/01 19:17:37 jmc 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
85Caution:
86The
87.Fa dst
88field should be zeroed before calling
89.Fn inet_net_pton
90as the function will only fill the number of bytes necessary to
91encode the network number in network byte order.
92.Pp
93The only value for
94.Fa af
95currently supported is
96.Dv AF_INET .
97.Fa size
98is the size of the result buffer
99.Fa dst .
100.Sh NETWORK NUMBERS (IP VERSION 4)
101The external representation of Internet network numbers may be specified in
102one of the following forms:
103.Bd -literal -offset indent
104a
105a.b
106a.b.c
107a.b.c.d
108.Ed
109.Pp
110Any of the above four forms may have
111.Dq Li /bits
112appended where
113.Dq Li bits
114is in the range
115.Li 0-32
116and is used to explicitly specify the number of bits in the network address.
117When
118.Dq Li /bits
119is not specified the number of bits in the network address is calculated
120as the larger of the number of bits in the class to which the address
121belongs and the number of bits provided rounded up modulo 8.
122Examples:
123.Bl -tag -width 10.1.2.3/24
124.It Li 10
125an 8 bit network number (class A), value
126.Li 10.0.0.0 .
127.It Li 192
128a 24 bit network number (class C), value
129.Li 192.0.0.0 .
130.It Li 10.10
131a 16 bit network number, value
132.Li 10.10.0.0 .
133.It Li 10.1.2
134a 24 bit network number, value
135.Li 10.1.2.0 .
136.It Li 10.1.2.3
137a 32 bit network number, value
138.Li 10.1.2.3 .
139.It Li 10.1.2.3/24
140a 24 bit network number (explicit), value
141.Li 10.1.2.3 .
142.El
143.Pp
144Note that when the number of bits is specified using
145.Dq Li /bits
146notation, the value of the address still includes all bits suplied
147in the external representation, even those bits which are the host
148part of an internet address.
149Also, unlike
150.Xr inet_pton 3
151where the external representation is assumed to be an internet address, the
152external representation for
153.Fn inet_net_pton
154is assumed to be a network address.
155Thus
156.Dq Li 10.1
157is assumed to be
158.Dq Li 10.1.0.0
159not
160.Dq Li 10.0.0.1
161.Pp
162All numbers supplied as
163.Dq parts
164in a
165.Ql \&.
166notation
167may be decimal, octal, or hexadecimal, as specified
168in the C language (i.e., a leading 0x or 0X implies
169hexadecimal; otherwise, a leading 0 implies octal;
170otherwise, the number is interpreted as decimal).
171.Sh SEE ALSO
172.Xr byteorder 3 ,
173.Xr inet 3 ,
174.Xr inet_pton 3 ,
175.Xr networks 5
176.Sh HISTORY
177The
178.Nm inet_net_ntop
179and
180.Nm inet_net_pton
181functions 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..3c72efac6b
--- /dev/null
+++ b/src/lib/libc/net/inet_net_pton.c
@@ -0,0 +1,206 @@
1/* $OpenBSD: inet_net_pton.c,v 1.3 2003/04/25 19:40:25 henning 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.3 2003/04/25 19:40:25 henning 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 < ((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..58be2d05cd
--- /dev/null
+++ b/src/lib/libc/net/inet_netof.c
@@ -0,0 +1,54 @@
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. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char rcsid[] = "$OpenBSD: inet_netof.c,v 1.4 2003/06/02 20:18:35 millert Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <sys/param.h>
35#include <netinet/in.h>
36#include <arpa/inet.h>
37
38/*
39 * Return the network number from an internet
40 * address; handles class a/b/c network #'s.
41 */
42in_addr_t
43inet_netof(in)
44 struct in_addr in;
45{
46 register in_addr_t i = ntohl(in.s_addr);
47
48 if (IN_CLASSA(i))
49 return (((i)&IN_CLASSA_NET) >> IN_CLASSA_NSHIFT);
50 else if (IN_CLASSB(i))
51 return (((i)&IN_CLASSB_NET) >> IN_CLASSB_NSHIFT);
52 else
53 return (((i)&IN_CLASSC_NET) >> IN_CLASSC_NSHIFT);
54}
diff --git a/src/lib/libc/net/inet_network.c b/src/lib/libc/net/inet_network.c
new file mode 100644
index 0000000000..5e36f78069
--- /dev/null
+++ b/src/lib/libc/net/inet_network.c
@@ -0,0 +1,88 @@
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. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char rcsid[] = "$OpenBSD: inet_network.c,v 1.8 2003/06/02 20:18:35 millert Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <sys/types.h>
35#include <netinet/in.h>
36#include <arpa/inet.h>
37#include <ctype.h>
38
39/*
40 * Internet network address interpretation routine.
41 * The library routines call this routine to interpret
42 * network numbers.
43 */
44in_addr_t
45inet_network(cp)
46 register const char *cp;
47{
48 register in_addr_t val, base, n;
49 register char c;
50 in_addr_t parts[4], *pp = parts;
51 register int i;
52
53again:
54 val = 0; base = 10;
55 if (*cp == '0')
56 base = 8, cp++;
57 if (*cp == 'x' || *cp == 'X')
58 base = 16, cp++;
59 while ((c = *cp)) {
60 if (isdigit(c)) {
61 val = (val * base) + (c - '0');
62 cp++;
63 continue;
64 }
65 if (base == 16 && isxdigit(c)) {
66 val = (val << 4) + (c + 10 - (islower(c) ? 'a' : 'A'));
67 cp++;
68 continue;
69 }
70 break;
71 }
72 if (*cp == '.') {
73 if (pp >= parts + 3)
74 return (INADDR_NONE);
75 *pp++ = val, cp++;
76 goto again;
77 }
78 if (*cp && !isspace(*cp))
79 return (INADDR_NONE);
80 *pp++ = val;
81 n = pp - parts;
82 for (val = 0, i = 0; i < 4; i++) {
83 val <<= 8;
84 if (i < n)
85 val |= parts[i] & 0xff;
86 }
87 return (val);
88}
diff --git a/src/lib/libc/net/inet_ntoa.c b/src/lib/libc/net/inet_ntoa.c
new file mode 100644
index 0000000000..bd3fd98b09
--- /dev/null
+++ b/src/lib/libc/net/inet_ntoa.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. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char rcsid[] = "$OpenBSD: inet_ntoa.c,v 1.4 2003/06/02 20:18:35 millert Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34/*
35 * Convert network-format internet address
36 * to base 256 d.d.d.d representation.
37 */
38#include <sys/types.h>
39#include <netinet/in.h>
40#include <arpa/inet.h>
41#include <stdio.h>
42
43char *
44inet_ntoa(in)
45 struct in_addr in;
46{
47 static char b[18];
48 register char *p;
49
50 p = (char *)&in;
51#define UC(b) (((int)b)&0xff)
52 (void)snprintf(b, sizeof(b),
53 "%u.%u.%u.%u", UC(p[0]), UC(p[1]), UC(p[2]), UC(p[3]));
54 return (b);
55}
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..64f6028db0
--- /dev/null
+++ b/src/lib/libc/net/ipx.3
@@ -0,0 +1,123 @@
1.\" $OpenBSD: ipx.3,v 1.10 2003/06/02 20:18:35 millert 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. Neither the name of the University nor the names of its contributors
15.\" may be used to endorse or promote products derived from this software
16.\" without specific prior written permission.
17.\"
18.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28.\" SUCH DAMAGE.
29.\"
30.Dd June 4, 1993
31.Dt IPX 3
32.Os
33.Sh NAME
34.Nm ipx_addr ,
35.Nm ipx_ntoa
36.Nd IPX address conversion routines
37.Sh SYNOPSIS
38.Fd #include <sys/types.h>
39.Fd #include <netipx/ipx.h>
40.Ft struct ipx_addr
41.Fn ipx_addr "const char *cp"
42.Ft char *
43.Fn ipx_ntoa "struct ipx_addr ipx"
44.Sh DESCRIPTION
45The routine
46.Fn ipx_addr
47interprets character strings representing
48.Tn IPX
49addresses, returning binary information suitable
50for use in system calls.
51The routine
52.Fn ipx_ntoa
53takes
54.Tn IPX
55addresses and returns
56.Tn ASCII
57strings representing the address in a
58notation in common use:
59.Bd -filled -offset indent
60<network number>.<host number>.<port number>
61.Ed
62.Pp
63Trailing zero fields are suppressed, and each number is printed in hexadecimal,
64in a format suitable for input to
65.Fn ipx_addr .
66Any fields lacking super-decimal digits will have a
67trailing
68.Sq H
69appended.
70.Pp
71An effort has been made to ensure that
72.Fn ipx_addr
73be compatible with most formats in common use.
74It will first separate an address into 1 to 3 fields using a single delimiter
75chosen from
76period
77.Pq Ql \&. ,
78colon
79.Pq Ql \&: ,
80or pound-sign
81.Pq Ql # .
82Each field is then examined for byte separators (colon or period).
83If there are byte separators, each subfield separated is taken to be
84a small hexadecimal number, and the entirety is taken as a network-byte-ordered
85quantity to be zero extended in the high-network-order bytes.
86Next, the field is inspected for hyphens, in which case
87the field is assumed to be a number in decimal notation
88with hyphens separating the millenia.
89Next, the field is assumed to be a number:
90It is interpreted
91as hexadecimal if there is a leading
92.Ql 0x
93(as in C),
94a trailing
95.Sq H
96(as in Mesa), or there are any super-decimal digits present.
97It is interpreted as octal if there is a leading
98.Ql 0
99and there are no super-octal digits.
100Otherwise, it is converted as a decimal number.
101.Sh RETURN VALUES
102None.
103(See
104.Sx BUGS . )
105.Sh SEE ALSO
106.Xr ns 4 ,
107.Xr hosts 5 ,
108.Xr networks 5
109.Sh HISTORY
110The precursor
111.Fn ns_addr
112and
113.Fn ns_ntoa
114functions appeared in
115.Bx 4.3 .
116.Sh BUGS
117The string returned by
118.Fn ipx_ntoa
119resides in a static memory area.
120The function
121.Fn ipx_addr
122should diagnose improperly formed input, and there should be an unambiguous
123way 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..371ac7c917
--- /dev/null
+++ b/src/lib/libc/net/ipx_addr.c
@@ -0,0 +1,224 @@
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. Neither the name of the University 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 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 * from @(#)ipx_addr.c
33 */
34
35#if defined(LIBC_SCCS) && !defined(lint)
36static char rcsid[] = "$OpenBSD: ipx_addr.c,v 1.6 2003/06/02 20:18:35 millert Exp $";
37#endif /* LIBC_SCCS and not lint */
38
39#include <sys/param.h>
40#include <netipx/ipx.h>
41#include <stdio.h>
42#include <string.h>
43
44static struct ipx_addr addr, zero_addr;
45
46static void Field(), cvtbase();
47
48struct ipx_addr
49ipx_addr(name)
50 const char *name;
51{
52 char separator;
53 char *hostname, *socketname, *cp;
54 char buf[50];
55
56 strlcpy(buf, name, sizeof(buf));
57
58 /*
59 * First, figure out what he intends as a field separtor.
60 * Despite the way this routine is written, the prefered
61 * form 2-272.AA001234H.01777, i.e. XDE standard.
62 * Great efforts are made to insure backward compatibility.
63 */
64 if ((hostname = strchr(buf, '#')))
65 separator = '#';
66 else {
67 hostname = strchr(buf, '.');
68 if ((cp = strchr(buf, ':')) &&
69 ((hostname && cp < hostname) || (hostname == 0))) {
70 hostname = cp;
71 separator = ':';
72 } else
73 separator = '.';
74 }
75 if (hostname)
76 *hostname++ = 0;
77
78 addr = zero_addr;
79 Field(buf, addr.ipx_net.c_net, 4);
80 if (hostname == 0)
81 return (addr); /* No separator means net only */
82
83 socketname = strchr(hostname, separator);
84 if (socketname) {
85 *socketname++ = 0;
86 Field(socketname, (u_char *)&addr.ipx_port, 2);
87 }
88
89 Field(hostname, addr.ipx_host.c_host, 6);
90
91 return (addr);
92}
93
94static void
95Field(buf, out, len)
96 char *buf;
97 u_char *out;
98 int len;
99{
100 register char *bp = buf;
101 int i, ibase, base16 = 0, base10 = 0, clen = 0;
102 int hb[6], *hp;
103 char *fmt;
104
105 /*
106 * first try 2-273#2-852-151-014#socket
107 */
108 if ((*buf != '-') &&
109 (1 < (i = sscanf(buf, "%d-%d-%d-%d-%d",
110 &hb[0], &hb[1], &hb[2], &hb[3], &hb[4])))) {
111 cvtbase(1000L, 256, hb, i, out, len);
112 return;
113 }
114 /*
115 * try form 8E1#0.0.AA.0.5E.E6#socket
116 */
117 if (1 < (i = sscanf(buf,"%x.%x.%x.%x.%x.%x",
118 &hb[0], &hb[1], &hb[2], &hb[3], &hb[4], &hb[5]))) {
119 cvtbase(256L, 256, hb, i, out, len);
120 return;
121 }
122 /*
123 * try form 8E1#0:0:AA:0:5E:E6#socket
124 */
125 if (1 < (i = sscanf(buf,"%x:%x:%x:%x:%x:%x",
126 &hb[0], &hb[1], &hb[2], &hb[3], &hb[4], &hb[5]))) {
127 cvtbase(256L, 256, hb, i, out, len);
128 return;
129 }
130 /*
131 * This is REALLY stretching it but there was a
132 * comma notation separting shorts -- definitely non standard
133 */
134 if (1 < (i = sscanf(buf,"%x,%x,%x",
135 &hb[0], &hb[1], &hb[2]))) {
136 hb[0] = htons(hb[0]); hb[1] = htons(hb[1]);
137 hb[2] = htons(hb[2]);
138 cvtbase(65536L, 256, hb, i, out, len);
139 return;
140 }
141
142 /* Need to decide if base 10, 16 or 8 */
143 while (*bp) switch (*bp++) {
144
145 case '0': case '1': case '2': case '3': case '4': case '5':
146 case '6': case '7': case '-':
147 break;
148
149 case '8': case '9':
150 base10 = 1;
151 break;
152
153 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
154 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
155 base16 = 1;
156 break;
157
158 case 'x': case 'X':
159 *--bp = '0';
160 base16 = 1;
161 break;
162
163 case 'h': case 'H':
164 base16 = 1;
165 /* fall into */
166
167 default:
168 *--bp = 0; /* Ends Loop */
169 }
170 if (base16) {
171 fmt = "%3x";
172 ibase = 4096;
173 } else if (base10 == 0 && *buf == '0') {
174 fmt = "%3o";
175 ibase = 512;
176 } else {
177 fmt = "%3d";
178 ibase = 1000;
179 }
180
181 for (bp = buf; *bp++; ) clen++;
182 if (clen == 0) clen++;
183 if (clen > 18) clen = 18;
184 i = ((clen - 1) / 3) + 1;
185 bp = clen + buf - 3;
186 hp = hb + i - 1;
187
188 while (hp > hb) {
189 (void)sscanf(bp, fmt, hp);
190 bp[0] = 0;
191 hp--;
192 bp -= 3;
193 }
194 (void)sscanf(buf, fmt, hp);
195 cvtbase((long)ibase, 256, hb, i, out, len);
196}
197
198static void
199cvtbase(oldbase,newbase,input,inlen,result,reslen)
200 long oldbase;
201 int newbase;
202 int input[];
203 int inlen;
204 unsigned char result[];
205 int reslen;
206{
207 int d, e;
208 long sum;
209
210 e = 1;
211 while (e > 0 && reslen > 0) {
212 d = 0; e = 0; sum = 0;
213 /* long division: input=input/newbase */
214 while (d < inlen) {
215 sum = sum*oldbase + (long) input[d];
216 e += (sum > 0);
217 input[d++] = sum / newbase;
218 sum %= newbase;
219 }
220 result[--reslen] = sum; /* accumulate remainder */
221 }
222 for (d=0; d < reslen; d++)
223 result[d] = 0;
224}
diff --git a/src/lib/libc/net/ipx_ntoa.c b/src/lib/libc/net/ipx_ntoa.c
new file mode 100644
index 0000000000..64ba146b31
--- /dev/null
+++ b/src/lib/libc/net/ipx_ntoa.c
@@ -0,0 +1,49 @@
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. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char rcsid[] = "$OpenBSD: ipx_ntoa.c,v 1.5 2003/09/26 06:19:25 deraadt Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <sys/param.h>
35#include <netipx/ipx.h>
36#include <stdio.h>
37
38char *
39ipx_ntoa(struct ipx_addr addr)
40{
41 static char obuf[] = "xxxxxxxxH.xx:xx:xx:xx:xx:xx.uuuuu";
42
43 snprintf(obuf, sizeof obuf, "%8xH.%02x:%02x:%02x:%02x:%02x:%02x.%u",
44 ntohl(addr.ipx_net.l_net), addr.ipx_host.c_host[0],
45 addr.ipx_host.c_host[1], addr.ipx_host.c_host[2],
46 addr.ipx_host.c_host[3], addr.ipx_host.c_host[4],
47 addr.ipx_host.c_host[5], ntohs(addr.ipx_port));
48 return (obuf);
49}
diff --git a/src/lib/libc/net/iso_addr.3 b/src/lib/libc/net/iso_addr.3
new file mode 100644
index 0000000000..896f769482
--- /dev/null
+++ b/src/lib/libc/net/iso_addr.3
@@ -0,0 +1,107 @@
1.\" $OpenBSD: iso_addr.3,v 1.5 2003/06/02 20:18:35 millert 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. Neither the name of the University nor the names of its contributors
15.\" may be used to endorse or promote products derived from this software
16.\" without specific prior written permission.
17.\"
18.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28.\" SUCH DAMAGE.
29.\"
30.Dd June 4, 1993
31.Dt ISO_ADDR 3
32.Os
33.Sh NAME
34.Nm iso_addr ,
35.Nm iso_ntoa
36.Nd "network address conversion routines for Open System Interconnection"
37.Sh SYNOPSIS
38.Fd #include <sys/types.h>
39.Fd #include <netiso/iso.h>
40.Ft struct iso_addr *
41.Fn iso_addr "char *cp"
42.Ft char *
43.Fn iso_ntoa "struct iso_addr *isoa"
44.Sh DESCRIPTION
45The routine
46.Fn iso_addr
47interprets character strings representing
48.Tn OSI
49addresses, returning binary information suitable
50for use in system calls.
51The routine
52.Fn iso_ntoa
53takes
54.Tn OSI
55addresses and returns
56.Tn ASCII
57strings representing NSAPs (network service
58access points) in a
59notation inverse to that accepted by
60.Fn iso_addr .
61.Pp
62Unfortunately, no universal standard exists for representing
63.Tn OSI
64network addresses.
65.Pp
66The format employed by
67.Fn iso_addr
68is a sequence of hexadecimal
69.Dq digits
70(optionally separated by periods),
71of the form:
72.Bd -filled -offset indent
73<hex digits>.<hex digits>.<hex digits>
74.Ed
75.Pp
76Each pair of hexadecimal digits represents a byte
77with the leading digit indicating the higher-ordered bits.
78A period following an even number of bytes has no
79effect (but may be used to increase legibility).
80A period following an odd number of bytes has the
81effect of causing the byte of address being translated
82to have its higher order bits filled with zeros.
83.Sh RETURN VALUES
84.Fn iso_ntoa
85always returns a null terminated string.
86.Fn iso_addr
87always returns a pointer to a
88.Li struct iso_addr .
89(See
90.Sx BUGS . )
91.Sh SEE ALSO
92.Xr iso 4
93.Sh HISTORY
94The
95.Fn iso_addr
96and
97.Fn iso_ntoa
98functions appeared in
99.Bx 4.3 Reno .
100.Sh BUGS
101The returned values
102reside in a static memory area.
103.Pp
104The function
105.Fn iso_addr
106should diagnose improperly formed input, and there should be an unambiguous
107way 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..f0f8444325
--- /dev/null
+++ b/src/lib/libc/net/iso_addr.c
@@ -0,0 +1,115 @@
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. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char rcsid[] = "$OpenBSD: iso_addr.c,v 1.3 2003/06/02 20:18:35 millert Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <sys/types.h>
35#include <netiso/iso.h>
36#include <string.h>
37
38/* States*/
39#define VIRGIN 0
40#define GOTONE 1
41#define GOTTWO 2
42/* Inputs */
43#define DIGIT (4*0)
44#define END (4*1)
45#define DELIM (4*2)
46
47struct iso_addr *
48iso_addr(addr)
49 register const char *addr;
50{
51 static struct iso_addr out_addr;
52 register char *cp = out_addr.isoa_genaddr;
53 char *cplim = cp + sizeof(out_addr.isoa_genaddr);
54 register int byte = 0, state = VIRGIN, new;
55
56 bzero((char *)&out_addr, sizeof(out_addr));
57 do {
58 if ((*addr >= '0') && (*addr <= '9')) {
59 new = *addr - '0';
60 } else if ((*addr >= 'a') && (*addr <= 'f')) {
61 new = *addr - 'a' + 10;
62 } else if ((*addr >= 'A') && (*addr <= 'F')) {
63 new = *addr - 'A' + 10;
64 } else if (*addr == 0)
65 state |= END;
66 else
67 state |= DELIM;
68 addr++;
69 switch (state /* | INPUT */) {
70 case GOTTWO | DIGIT:
71 *cp++ = byte; /*FALLTHROUGH*/
72 case VIRGIN | DIGIT:
73 state = GOTONE; byte = new; continue;
74 case GOTONE | DIGIT:
75 state = GOTTWO; byte = new + (byte << 4); continue;
76 default: /* | DELIM */
77 state = VIRGIN; *cp++ = byte; byte = 0; continue;
78 case GOTONE | END:
79 case GOTTWO | END:
80 *cp++ = byte; /* FALLTHROUGH */
81 case VIRGIN | END:
82 break;
83 }
84 break;
85 } while (cp < cplim);
86 out_addr.isoa_len = cp - out_addr.isoa_genaddr;
87 return (&out_addr);
88}
89static char hexlist[] = "0123456789abcdef";
90
91char *
92iso_ntoa(isoa)
93 const struct iso_addr *isoa;
94{
95 static char obuf[64];
96 register char *out = obuf;
97 register int i;
98 register u_char *in = (u_char *)isoa->isoa_genaddr;
99 u_char *inlim = in + isoa->isoa_len;
100
101 out[1] = 0;
102 while (in < inlim) {
103 i = *in++;
104 *out++ = '.';
105 if (i > 0xf) {
106 out[1] = hexlist[i & 0xf];
107 i >>= 4;
108 out[0] = hexlist[i];
109 out += 2;
110 } else
111 *out++ = hexlist[i];
112 }
113 *out = 0;
114 return(obuf + 1);
115}
diff --git a/src/lib/libc/net/link_addr.3 b/src/lib/libc/net/link_addr.3
new file mode 100644
index 0000000000..929db4e1d6
--- /dev/null
+++ b/src/lib/libc/net/link_addr.3
@@ -0,0 +1,127 @@
1.\" $OpenBSD: link_addr.3,v 1.8 2003/06/02 20:18:35 millert 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. 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.Dd July 28, 1993
34.Dt LINK_ADDR 3
35.Os
36.Sh NAME
37.Nm link_addr ,
38.Nm link_ntoa
39.Nd elementary address specification routines for link level access
40.Sh SYNOPSIS
41.Fd #include <sys/types.h>
42.Fd #include <sys/socket.h>
43.Fd #include <net/if_dl.h>
44.Ft void
45.Fn link_addr "const char *addr" "struct sockaddr_dl *sdl"
46.Ft char *
47.Fn link_ntoa "const struct sockaddr_dl *sdl"
48.Sh DESCRIPTION
49The
50.Fn link_addr
51function interprets character strings representing
52link-level addresses, returning binary information suitable
53for use in system calls.
54.Fn link_ntoa
55takes
56a link-level
57address and returns an
58.Tn ASCII
59string representing some of the information present,
60including the link level address itself, and the interface name
61or number, if present.
62This facility is experimental and is
63still subject to change.
64.Pp
65For
66.Fn link_addr ,
67the string
68.Fa addr
69may contain
70an optional network interface identifier of the form
71.Dq name unit-number ,
72suitable for the first argument to
73.Xr ifconfig 8 ,
74followed in all cases by a colon and
75an interface address in the form of
76groups of hexadecimal digits
77separated by periods.
78Each group represents a byte of address;
79address bytes are filled left to right from
80low order bytes through high order bytes.
81.Pp
82.\" A regular expression may make this format clearer:
83.\" .Bd -literal -offset indent
84.\" ([a-z]+[0-9]+:)?[0-9a-f]+(\e.[0-9a-f]+)*
85.\" .Ed
86.\" .Pp
87Thus
88.Li le0:8.0.9.13.d.30
89represents an Ethernet address
90to be transmitted on the first Lance Ethernet interface.
91.Sh RETURN VALUES
92.Fn link_ntoa
93always returns a null-terminated string.
94.Fn link_addr
95has no return value.
96(See
97.Sx BUGS . )
98.Sh SEE ALSO
99.Xr iso 4 ,
100.Xr ifconfig 8
101.Sh HISTORY
102The
103.Fn link_addr
104and
105.Fn link_ntoa
106functions appeared in
107.Bx 4.3 Reno .
108.Sh BUGS
109The returned values for link_ntoa
110reside in a static memory area.
111.Pp
112The function
113.Fn link_addr
114should diagnose improperly formed input, and there should be an unambiguous
115way to recognize this.
116.Pp
117If the
118.Fa sdl_len
119field of the link socket address
120.Fa sdl
121is 0,
122.Fn link_ntoa
123will not insert a colon before the interface address bytes.
124If this translated address is given to
125.Fn link_addr
126without inserting an initial colon,
127the 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..ee45ff767d
--- /dev/null
+++ b/src/lib/libc/net/linkaddr.c
@@ -0,0 +1,154 @@
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. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char rcsid[] = "$OpenBSD: linkaddr.c,v 1.3 2003/06/02 20:18:35 millert Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <sys/types.h>
35#include <sys/socket.h>
36#include <net/if_dl.h>
37#include <string.h>
38
39/* States*/
40#define NAMING 0
41#define GOTONE 1
42#define GOTTWO 2
43#define RESET 3
44/* Inputs */
45#define DIGIT (4*0)
46#define END (4*1)
47#define DELIM (4*2)
48#define LETTER (4*3)
49
50void
51link_addr(addr, sdl)
52 register const char *addr;
53 register struct sockaddr_dl *sdl;
54{
55 register char *cp = sdl->sdl_data;
56 char *cplim = sdl->sdl_len + (char *)sdl;
57 register int byte = 0, state = NAMING, new;
58
59 bzero((char *)&sdl->sdl_family, sdl->sdl_len - 1);
60 sdl->sdl_family = AF_LINK;
61 do {
62 state &= ~LETTER;
63 if ((*addr >= '0') && (*addr <= '9')) {
64 new = *addr - '0';
65 } else if ((*addr >= 'a') && (*addr <= 'f')) {
66 new = *addr - 'a' + 10;
67 } else if ((*addr >= 'A') && (*addr <= 'F')) {
68 new = *addr - 'A' + 10;
69 } else if (*addr == 0) {
70 state |= END;
71 } else if (state == NAMING &&
72 (((*addr >= 'A') && (*addr <= 'Z')) ||
73 ((*addr >= 'a') && (*addr <= 'z'))))
74 state |= LETTER;
75 else
76 state |= DELIM;
77 addr++;
78 switch (state /* | INPUT */) {
79 case NAMING | DIGIT:
80 case NAMING | LETTER:
81 *cp++ = addr[-1];
82 continue;
83 case NAMING | DELIM:
84 state = RESET;
85 sdl->sdl_nlen = cp - sdl->sdl_data;
86 continue;
87 case GOTTWO | DIGIT:
88 *cp++ = byte;
89 /* FALLTHROUGH */
90 case RESET | DIGIT:
91 state = GOTONE;
92 byte = new;
93 continue;
94 case GOTONE | DIGIT:
95 state = GOTTWO;
96 byte = new + (byte << 4);
97 continue;
98 default: /* | DELIM */
99 state = RESET;
100 *cp++ = byte;
101 byte = 0;
102 continue;
103 case GOTONE | END:
104 case GOTTWO | END:
105 *cp++ = byte;
106 /* FALLTHROUGH */
107 case RESET | END:
108 break;
109 }
110 break;
111 } while (cp < cplim);
112 sdl->sdl_alen = cp - LLADDR(sdl);
113 new = cp - (char *)sdl;
114 if (new > sizeof(*sdl))
115 sdl->sdl_len = new;
116 return;
117}
118
119static char hexlist[] = "0123456789abcdef";
120
121char *
122link_ntoa(sdl)
123 register const struct sockaddr_dl *sdl;
124{
125 static char obuf[64];
126 register char *out = obuf;
127 register int i;
128 register u_char *in = (u_char *)LLADDR(sdl);
129 u_char *inlim = in + sdl->sdl_alen;
130 int firsttime = 1;
131
132 if (sdl->sdl_nlen) {
133 bcopy(sdl->sdl_data, obuf, sdl->sdl_nlen);
134 out += sdl->sdl_nlen;
135 if (sdl->sdl_alen)
136 *out++ = ':';
137 }
138 while (in < inlim) {
139 if (firsttime)
140 firsttime = 0;
141 else
142 *out++ = '.';
143 i = *in++;
144 if (i > 0xf) {
145 out[1] = hexlist[i & 0xf];
146 i >>= 4;
147 out[0] = hexlist[i];
148 out += 2;
149 } else
150 *out++ = hexlist[i];
151 }
152 *out = 0;
153 return (obuf);
154}
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..9c7aeab312
--- /dev/null
+++ b/src/lib/libc/net/ns.3
@@ -0,0 +1,127 @@
1.\" $OpenBSD: ns.3,v 1.9 2003/06/02 20:18:35 millert 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. Neither the name of the University nor the names of its contributors
15.\" may be used to endorse or promote products derived from this software
16.\" without specific prior written permission.
17.\"
18.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28.\" SUCH DAMAGE.
29.\"
30.Dd June 4, 1993
31.Dt NS 3
32.Os
33.Sh NAME
34.Nm ns_addr ,
35.Nm ns_ntoa
36.Nd Xerox
37.Tn NS Ns (tm)
38address conversion routines
39.Sh SYNOPSIS
40.Fd #include <sys/types.h>
41.Fd #include <netns/ns.h>
42.Ft struct ns_addr
43.Fn ns_addr "char *cp"
44.Ft char *
45.Fn ns_ntoa "struct ns_addr ns"
46.Sh DESCRIPTION
47The routine
48.Fn ns_addr
49interprets character strings representing
50.Tn XNS
51addresses, returning binary information suitable
52for use in system calls.
53The routine
54.Fn ns_ntoa
55takes
56.Tn XNS
57addresses and returns
58.Tn ASCII
59strings representing the address in a
60notation in common use in the Xerox Development Environment:
61.Bd -filled -offset indent
62<network number>.<host number>.<port number>
63.Ed
64.Pp
65Trailing zero fields are suppressed, and each number is printed in hexadecimal,
66in a format suitable for input to
67.Fn ns_addr .
68Any fields lacking super-decimal digits will have a
69trailing
70.Sq H
71appended.
72.Pp
73Unfortunately, no universal standard exists for representing
74.Tn XNS
75addresses.
76An effort has been made to ensure that
77.Fn ns_addr
78be compatible with most formats in common use.
79It will first separate an address into 1 to 3 fields using a single delimiter
80chosen from
81period
82.Pq Ql \&. ,
83colon
84.Pq Ql \&: ,
85or pound-sign
86.Ql # .
87Each field is then examined for byte separators (colon or period).
88If there are byte separators, each subfield separated is taken to be
89a small hexadecimal number, and the entirety is taken as a network-byte-ordered
90quantity to be zero extended in the high-network-order bytes.
91Next, the field is inspected for hyphens, in which case
92the field is assumed to be a number in decimal notation
93with hyphens separating the millenia.
94Next, the field is assumed to be a number:
95It is interpreted
96as hexadecimal if there is a leading
97.Ql 0x
98(as in C),
99a trailing
100.Sq H
101(as in Mesa), or there are any super-decimal digits present.
102It is interpreted as octal if there is a leading
103.Ql 0
104and there are no super-octal digits.
105Otherwise, it is converted as a decimal number.
106.Sh RETURN VALUES
107None.
108(See
109.Sx BUGS . )
110.Sh SEE ALSO
111.Xr hosts 5 ,
112.Xr networks 5
113.Sh HISTORY
114The
115.Fn ns_addr
116and
117.Fn ns_toa
118functions appeared in
119.Bx 4.3 .
120.Sh BUGS
121The string returned by
122.Fn ns_ntoa
123resides in a static memory area.
124The function
125.Fn ns_addr
126should diagnose improperly formed input, and there should be an unambiguous
127way 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..0f8feda55c
--- /dev/null
+++ b/src/lib/libc/net/ns_addr.c
@@ -0,0 +1,223 @@
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. Neither the name of the University 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 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#if defined(LIBC_SCCS) && !defined(lint)
34static char rcsid[] = "$OpenBSD: ns_addr.c,v 1.8 2003/06/02 20:18:35 millert Exp $";
35#endif /* LIBC_SCCS and not lint */
36
37#include <sys/param.h>
38#include <netns/ns.h>
39#include <stdio.h>
40#include <string.h>
41
42static struct ns_addr addr, zero_addr;
43
44static void Field(char *, u_int8_t *, int);
45static void cvtbase(long, int, int[], int, u_int8_t[], int);
46
47struct ns_addr
48ns_addr(name)
49 const char *name;
50{
51 char separator;
52 char *hostname, *socketname, *cp;
53 char buf[50];
54
55 strlcpy(buf, name, sizeof(buf));
56
57 /*
58 * First, figure out what he intends as a field separtor.
59 * Despite the way this routine is written, the prefered
60 * form 2-272.AA001234H.01777, i.e. XDE standard.
61 * Great efforts are made to insure backward compatibility.
62 */
63 if ((hostname = strchr(buf, '#')))
64 separator = '#';
65 else {
66 hostname = strchr(buf, '.');
67 if ((cp = strchr(buf, ':')) &&
68 ((hostname && cp < hostname) || (hostname == 0))) {
69 hostname = cp;
70 separator = ':';
71 } else
72 separator = '.';
73 }
74 if (hostname)
75 *hostname++ = 0;
76
77 addr = zero_addr;
78 Field(buf, addr.x_net.c_net, 4);
79 if (hostname == 0)
80 return (addr); /* No separator means net only */
81
82 socketname = strchr(hostname, separator);
83 if (socketname) {
84 *socketname++ = 0;
85 Field(socketname, (u_char *)&addr.x_port, 2);
86 }
87
88 Field(hostname, (u_char *)addr.x_host.c_host, 6);
89
90 return (addr);
91}
92
93static void
94Field(buf, out, len)
95 char *buf;
96 u_char *out;
97 int len;
98{
99 register char *bp = buf;
100 int i, ibase, base16 = 0, base10 = 0, clen = 0;
101 int hb[6], *hp;
102 char *fmt;
103
104 /*
105 * first try 2-273#2-852-151-014#socket
106 */
107 if ((*buf != '-') &&
108 (1 < (i = sscanf(buf, "%d-%d-%d-%d-%d",
109 &hb[0], &hb[1], &hb[2], &hb[3], &hb[4])))) {
110 cvtbase(1000L, 256, hb, i, out, len);
111 return;
112 }
113 /*
114 * try form 8E1#0.0.AA.0.5E.E6#socket
115 */
116 if (1 < (i = sscanf(buf,"%x.%x.%x.%x.%x.%x",
117 &hb[0], &hb[1], &hb[2], &hb[3], &hb[4], &hb[5]))) {
118 cvtbase(256L, 256, hb, i, out, len);
119 return;
120 }
121 /*
122 * try form 8E1#0:0:AA:0:5E:E6#socket
123 */
124 if (1 < (i = sscanf(buf,"%x:%x:%x:%x:%x:%x",
125 &hb[0], &hb[1], &hb[2], &hb[3], &hb[4], &hb[5]))) {
126 cvtbase(256L, 256, hb, i, out, len);
127 return;
128 }
129 /*
130 * This is REALLY stretching it but there was a
131 * comma notation separting shorts -- definitely non standard
132 */
133 if (1 < (i = sscanf(buf,"%x,%x,%x",
134 &hb[0], &hb[1], &hb[2]))) {
135 hb[0] = htons(hb[0]); hb[1] = htons(hb[1]);
136 hb[2] = htons(hb[2]);
137 cvtbase(65536L, 256, hb, i, out, len);
138 return;
139 }
140
141 /* Need to decide if base 10, 16 or 8 */
142 while (*bp) switch (*bp++) {
143
144 case '0': case '1': case '2': case '3': case '4': case '5':
145 case '6': case '7': case '-':
146 break;
147
148 case '8': case '9':
149 base10 = 1;
150 break;
151
152 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
153 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
154 base16 = 1;
155 break;
156
157 case 'x': case 'X':
158 *--bp = '0';
159 base16 = 1;
160 break;
161
162 case 'h': case 'H':
163 base16 = 1;
164 /* fall into */
165
166 default:
167 *--bp = 0; /* Ends Loop */
168 }
169 if (base16) {
170 fmt = "%3x";
171 ibase = 4096;
172 } else if (base10 == 0 && *buf == '0') {
173 fmt = "%3o";
174 ibase = 512;
175 } else {
176 fmt = "%3d";
177 ibase = 1000;
178 }
179
180 for (bp = buf; *bp++; ) clen++;
181 if (clen == 0) clen++;
182 if (clen > 18) clen = 18;
183 i = ((clen - 1) / 3) + 1;
184 bp = clen + buf - 3;
185 hp = hb + i - 1;
186
187 while (hp > hb) {
188 (void)sscanf(bp, fmt, hp);
189 bp[0] = 0;
190 hp--;
191 bp -= 3;
192 }
193 (void)sscanf(buf, fmt, hp);
194 cvtbase((long)ibase, 256, hb, i, out, len);
195}
196
197static void
198cvtbase(oldbase,newbase,input,inlen,result,reslen)
199 long oldbase;
200 int newbase;
201 int input[];
202 int inlen;
203 unsigned char result[];
204 int reslen;
205{
206 int d, e;
207 long sum;
208
209 e = 1;
210 while (e > 0 && reslen > 0) {
211 d = 0; e = 0; sum = 0;
212 /* long division: input=input/newbase */
213 while (d < inlen) {
214 sum = sum*oldbase + (long) input[d];
215 e += (sum > 0);
216 input[d++] = sum / newbase;
217 sum %= newbase;
218 }
219 result[--reslen] = sum; /* accumulate remainder */
220 }
221 for (d=0; d < reslen; d++)
222 result[d] = 0;
223}
diff --git a/src/lib/libc/net/ns_ntoa.c b/src/lib/libc/net/ns_ntoa.c
new file mode 100644
index 0000000000..fd67e459da
--- /dev/null
+++ b/src/lib/libc/net/ns_ntoa.c
@@ -0,0 +1,106 @@
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. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char rcsid[] = "$OpenBSD: ns_ntoa.c,v 1.13 2003/09/25 21:14:46 millert Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <sys/param.h>
35#include <netns/ns.h>
36#include <stdio.h>
37
38static char *spectHex(char *);
39
40char *
41ns_ntoa(struct ns_addr addr)
42{
43 static char obuf[40];
44 union { union ns_net net_e; u_int32_t long_e; } net;
45 in_port_t port = htons(addr.x_port);
46 char *cp, *cp2;
47 u_char *up = addr.x_host.c_host;
48 u_char *uplim = up + 6;
49 size_t rem;
50
51 net.net_e = addr.x_net;
52 snprintf(obuf, sizeof obuf, "%x", ntohl(net.long_e));
53 cp = spectHex(obuf);
54 rem = sizeof(obuf) - (cp - obuf);
55 cp2 = cp + 1;
56 while (up < uplim && *up==0)
57 up++;
58 if (up == uplim) {
59 if (port) {
60 snprintf(cp, rem, ".0");
61 cp += 2;
62 rem -= 2;
63 }
64 } else {
65 snprintf(cp, rem, ".%x", *up++);
66 while (up < uplim) {
67 while (*cp) {
68 cp++;
69 rem--;
70 }
71 snprintf(cp, rem, "%02x", *up++);
72 }
73 cp = spectHex(cp2);
74 rem = sizeof(obuf) - (cp - obuf);
75 }
76 if (port) {
77 snprintf(cp, rem, ".%x", port);
78 spectHex(cp + 1);
79 }
80 return (obuf);
81}
82
83static char *
84spectHex(char *p0)
85{
86 int ok = 0, nonzero = 0;
87 char *p = p0;
88
89 for (; *p; p++) {
90 switch (*p) {
91 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
92 *p += ('A' - 'a');
93 /* fall into . . . */
94 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
95 ok = 1;
96 case '1': case '2': case '3': case '4': case '5':
97 case '6': case '7': case '8': case '9':
98 nonzero = 1;
99 }
100 }
101 if (nonzero && !ok) {
102 *p++ = 'H';
103 *p = 0;
104 }
105 return (p);
106}
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..df31a60b63
--- /dev/null
+++ b/src/lib/libc/net/rcmd.3
@@ -0,0 +1,266 @@
1.\" $OpenBSD: rcmd.3,v 1.26 2003/06/02 20:18:35 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. Neither the name of the University nor the names of its contributors
15.\" may be used to endorse or promote products derived from this software
16.\" without specific prior written permission.
17.\"
18.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28.\" SUCH DAMAGE.
29.\"
30.Dd June 4, 1993
31.Dt RCMD 3
32.Os
33.Sh NAME
34.Nm rcmd ,
35.Nm rcmd_af ,
36.Nm rresvport ,
37.Nm rresvport_af ,
38.Nm iruserok ,
39.Nm ruserok ,
40.Nm iruserok_sa
41.Nd routines for returning a stream to a remote command
42.Sh SYNOPSIS
43.Fd #include <unistd.h>
44.Ft int
45.Fn rcmd "char **ahost" "int inport" "const char *locuser" "const char *remuser" "const char *cmd" "int *fd2p"
46.Ft int
47.Fn rcmd_af "char **ahost" "int inport" "const char *locuser" "const char *remuser" "const char *cmd" "int *fd2p" "int af"
48.Ft int
49.Fn rresvport "int *port"
50.Ft int
51.Fn rresvport_af "int *port" "int af"
52.Ft int
53.Fn iruserok "u_int32_t raddr" "int superuser" "const char *ruser" "const char *luser"
54.Ft int
55.Fn ruserok "const char *rhost" "int superuser" "const char *ruser" "const char *luser"
56.Ft int
57.Fn iruserok_sa "const void *sa" "int salen" "int superuser" "const char *ruser" "const char *luser"
58.Sh DESCRIPTION
59The
60.Fn rcmd
61function is used by the superuser to execute a command on a remote
62machine using an authentication scheme based on reserved
63port numbers.
64If the calling process is not setuid, the
65.Ev RSH
66environment variable is set, and
67.Fa inport
68is
69.Dq shell/tcp ,
70.Xr rcmdsh 3
71is called instead with the value of
72.Ev RSH .
73Alternately, if the user is not the superuser,
74.Fn rcmd
75will invoke
76.Xr rcmdsh 3
77to run the command via
78.Xr rsh 1 .
79While
80.Fn rcmd
81can handle IPv4 cases only,
82the
83.Fn rcmd_af
84function can handle other cases as well.
85.Pp
86The
87.Fn rresvport
88and
89.Fn rresvport_af
90functions return a descriptor to a socket
91with an address in the privileged port space.
92The
93.Fn iruserok
94and
95.Fn ruserok
96functions are used by servers
97to authenticate clients requesting service with
98.Fn rcmd .
99All four functions are present in the same file and are used
100by the
101.Xr rshd 8
102server (among others).
103.Fn iruserok_sa
104is an address family independent variant of
105.Fn iruserok .
106.Pp
107The
108.Fn rcmd
109function looks up the host
110.Fa *ahost
111using
112.Xr gethostbyname 3 ,
113returning \-1 if the host does not exist.
114Otherwise
115.Fa *ahost
116is set to the standard name of the host
117and a connection is established to a server
118residing at the well-known Internet port
119.Fa inport .
120If the user is not the superuser, the only valid port is
121.Dq shell/tcp
122(usually port 514).
123.Pp
124If the connection succeeds,
125a socket in the Internet domain of type
126.Dv SOCK_STREAM
127is returned to the caller, and given to the remote
128command as stdin and stdout.
129If
130.Fa fd2p
131is non-zero, then an auxiliary channel to a control
132process will be set up, and a descriptor for it will be placed
133in
134.Fa *fd2p .
135The control process will return diagnostic
136output from the command (unit 2) on this channel, and will also
137accept bytes on this channel as being
138.Tn UNIX
139signal numbers, to be
140forwarded to the process group of the command.
141If
142.Fa fd2p
143is
144.Va NULL ,
145then the standard error (unit 2 of the remote command) will be made
146the same as the standard output and no provision is made for sending
147arbitrary signals to the remote process, although you may be able to
148get its attention by using out-of-band data.
149Note that if the user is not the superuser,
150.Fa fd2p
151must be
152.Va NULL .
153.Pp
154.Fn rcmd_af
155takes address family in the last argument.
156If the last argument is
157.Dv PF_UNSPEC ,
158interpretation of
159.Fa *ahost
160will obey the underlying address resolution like DNS.
161.Pp
162The protocol is described in detail in
163.Xr rshd 8 .
164.Pp
165The
166.Fn rresvport
167and
168.Fn rresvport_af
169functions are used to obtain a socket with a privileged
170address bound to it.
171This socket is suitable for use by
172.Fn rcmd
173and several other functions.
174Privileged Internet ports are those in the range 0 to
175.Va IPPORT_RESERVED - 1 ,
176which happens to be 1023.
177Only the superuser is allowed to bind an address of this sort to a socket.
178.Fn rresvport
179and
180.Fn rresvport_af
181need to be seeded with a port number; if that port
182is not available these functions will find another.
183.Pp
184The
185.Fn iruserok
186and
187.Fn ruserok
188functions take a remote host's IP address or name, respectively,
189two user names and a flag indicating whether the local user's
190name is that of the superuser.
191Then, if the user is
192.Em not
193the superuser, it checks the
194.Pa /etc/hosts.equiv
195file.
196If that lookup is not done, or is unsuccessful, the
197.Pa .rhosts
198in the local user's home directory is checked to see if the request for
199service is allowed.
200.Pp
201If this file does not exist, is not a regular file, is owned by anyone
202other than the user or the superuser, or is writeable by anyone other
203than the owner, the check automatically fails.
204Zero is returned if the machine name is listed in the
205.Pa hosts.equiv
206file, or the host and remote user name are found in the
207.Pa .rhosts
208file; otherwise
209.Fn iruserok
210and
211.Fn ruserok
212return \-1.
213If the local domain (as obtained from
214.Xr gethostname 3 )
215is the same as the remote domain, only the machine name need be specified.
216.Pp
217If the IP address of the remote host is known,
218.Fn iruserok
219should be used in preference to
220.Fn ruserok ,
221as it does not require trusting the DNS server for the remote host's domain.
222.Pp
223While
224.Fn iruserok
225can handle IPv4 addresses only,
226.Fn iruserok_sa
227and
228.Fn ruserok
229can handle other address families as well, like IPv6.
230The first argument of
231.Fn iruserok_sa
232is typed as
233.Li "void *"
234to avoid dependency between
235.Aq Pa unistd.h
236and
237.Aq Pa sys/socket.h .
238.Sh DIAGNOSTICS
239The
240.Fn rcmd
241function returns a valid socket descriptor on success.
242It returns \-1 on error and prints a diagnostic message on the standard error.
243.Pp
244The
245.Fn rresvport
246and
247.Fn rresvport_af
248functions return a valid, bound socket descriptor on success.
249It returns \-1 on error with the global value
250.Va errno
251set according to the reason for failure.
252The error code
253.Er EAGAIN
254is overloaded to mean
255.Dq all network ports in use .
256.Sh SEE ALSO
257.Xr rsh 1 ,
258.Xr intro 2 ,
259.Xr bindresvport 3 ,
260.Xr bindresvport_sa 3 ,
261.Xr rcmdsh 3 ,
262.Xr rshd 8
263.Sh HISTORY
264These
265functions appeared in
266.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..769e85e0a4
--- /dev/null
+++ b/src/lib/libc/net/rcmd.c
@@ -0,0 +1,728 @@
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. Neither the name of the University nor the names of its contributors
15 * may be used to endorse or promote products derived from this software
16 * without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31#if defined(LIBC_SCCS) && !defined(lint)
32static char *rcsid = "$OpenBSD: rcmd.c,v 1.48 2003/09/25 21:14:46 millert Exp $";
33#endif /* LIBC_SCCS and not lint */
34
35#include <sys/param.h>
36#include <sys/socket.h>
37#include <sys/stat.h>
38
39#include <netinet/in.h>
40#include <arpa/inet.h>
41
42#include <signal.h>
43#include <fcntl.h>
44#include <netdb.h>
45#include <unistd.h>
46#include <pwd.h>
47#include <errno.h>
48#include <stdio.h>
49#include <ctype.h>
50#include <string.h>
51#include <syslog.h>
52#include <stdlib.h>
53#include <netgroup.h>
54
55int __ivaliduser(FILE *, in_addr_t, const char *, const char *);
56int __ivaliduser_sa(FILE *, struct sockaddr *, socklen_t,
57 const char *, const char *);
58static int __icheckhost(struct sockaddr *, socklen_t, const char *);
59static char *__gethostloop(struct sockaddr *, socklen_t);
60
61int
62rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
63 char **ahost;
64 in_port_t rport;
65 const char *locuser, *remuser, *cmd;
66 int *fd2p;
67{
68 return rcmd_af(ahost, rport, locuser, remuser, cmd, fd2p, AF_INET);
69}
70
71int
72rcmd_af(ahost, rport, locuser, remuser, cmd, fd2p, af)
73 char **ahost;
74 in_port_t rport;
75 const char *locuser, *remuser, *cmd;
76 int *fd2p;
77 int af;
78{
79 static char hbuf[MAXHOSTNAMELEN];
80 char pbuf[NI_MAXSERV];
81 struct addrinfo hints, *res, *r;
82 int error;
83 struct sockaddr_storage from;
84 fd_set *readsp = NULL;
85 sigset_t oldmask, mask;
86 pid_t pid;
87 int s, lport, timo;
88 char c, *p;
89 int refused;
90
91 /* call rcmdsh() with specified remote shell if appropriate. */
92 if (!issetugid() && (p = getenv("RSH")) && *p) {
93 struct servent *sp = getservbyname("shell", "tcp");
94
95 if (sp && sp->s_port == rport)
96 return (rcmdsh(ahost, rport, locuser, remuser,
97 cmd, p));
98 }
99
100 /* use rsh(1) if non-root and remote port is shell. */
101 if (geteuid()) {
102 struct servent *sp = getservbyname("shell", "tcp");
103
104 if (sp && sp->s_port == rport)
105 return (rcmdsh(ahost, rport, locuser, remuser,
106 cmd, NULL));
107 }
108
109 pid = getpid();
110 snprintf(pbuf, sizeof(pbuf), "%u", ntohs(rport));
111 memset(&hints, 0, sizeof(hints));
112 hints.ai_family = af;
113 hints.ai_socktype = SOCK_STREAM;
114 hints.ai_flags = AI_CANONNAME;
115 error = getaddrinfo(*ahost, pbuf, &hints, &res);
116 if (error) {
117#if 0
118 warnx("%s: %s", *ahost, gai_strerror(error));
119#endif
120 return (-1);
121 }
122 if (res->ai_canonname) {
123 strlcpy(hbuf, res->ai_canonname, sizeof(hbuf));
124 *ahost = hbuf;
125 } else
126 ; /*XXX*/
127
128 r = res;
129 refused = 0;
130 sigemptyset(&mask);
131 sigaddset(&mask, SIGURG);
132 oldmask = sigprocmask(SIG_BLOCK, &mask, &oldmask);
133 for (timo = 1, lport = IPPORT_RESERVED - 1;;) {
134 s = rresvport_af(&lport, r->ai_family);
135 if (s < 0) {
136 if (errno == EAGAIN)
137 (void)fprintf(stderr,
138 "rcmd: socket: All ports in use\n");
139 else
140 (void)fprintf(stderr, "rcmd: socket: %s\n",
141 strerror(errno));
142 if (r->ai_next) {
143 r = r->ai_next;
144 continue;
145 } else {
146 sigprocmask(SIG_SETMASK, &oldmask, NULL);
147 freeaddrinfo(res);
148 return (-1);
149 }
150 }
151 fcntl(s, F_SETOWN, pid);
152 if (connect(s, r->ai_addr, r->ai_addrlen) >= 0)
153 break;
154 (void)close(s);
155 if (errno == EADDRINUSE) {
156 lport--;
157 continue;
158 }
159 if (errno == ECONNREFUSED)
160 refused++;
161 if (r->ai_next) {
162 int oerrno = errno;
163 char hbuf[NI_MAXHOST];
164#ifdef NI_WITHSCOPEID
165 const int niflags = NI_NUMERICHOST | NI_WITHSCOPEID;
166#else
167 const int niflags = NI_NUMERICHOST;
168#endif
169
170 hbuf[0] = '\0';
171 if (getnameinfo(r->ai_addr, r->ai_addrlen,
172 hbuf, sizeof(hbuf), NULL, 0, niflags) != 0)
173 strlcpy(hbuf, "(invalid)", sizeof hbuf);
174 (void)fprintf(stderr, "connect to address %s: ", hbuf);
175 errno = oerrno;
176 perror(0);
177 r = r->ai_next;
178 hbuf[0] = '\0';
179 if (getnameinfo(r->ai_addr, r->ai_addrlen,
180 hbuf, sizeof(hbuf), NULL, 0, niflags) != 0)
181 strlcpy(hbuf, "(invalid)", sizeof hbuf);
182 (void)fprintf(stderr, "Trying %s...\n", hbuf);
183 continue;
184 }
185 if (refused && timo <= 16) {
186 (void)sleep(timo);
187 timo *= 2;
188 r = res;
189 refused = 0;
190 continue;
191 }
192 (void)fprintf(stderr, "%s: %s\n", res->ai_canonname,
193 strerror(errno));
194 sigprocmask(SIG_SETMASK, &oldmask, NULL);
195 freeaddrinfo(res);
196 return (-1);
197 }
198 /* given "af" can be PF_UNSPEC, we need the real af for "s" */
199 af = r->ai_family;
200 freeaddrinfo(res);
201#if 0
202 /*
203 * try to rresvport() to the same port. This will make rresvport()
204 * fail it's first bind, resulting in it choosing a random port.
205 */
206 lport--;
207#endif
208 if (fd2p == 0) {
209 write(s, "", 1);
210 lport = 0;
211 } else {
212 char num[8];
213 int s2 = rresvport_af(&lport, af), s3;
214 socklen_t len = sizeof(from);
215 int fdssize = howmany(MAX(s, s2)+1, NFDBITS) * sizeof(fd_mask);
216
217 if (s2 < 0)
218 goto bad;
219 readsp = (fd_set *)malloc(fdssize);
220 if (readsp == NULL)
221 goto bad;
222 listen(s2, 1);
223 (void)snprintf(num, sizeof(num), "%d", lport);
224 if (write(s, num, strlen(num)+1) != strlen(num)+1) {
225 (void)fprintf(stderr,
226 "rcmd: write (setting up stderr): %s\n",
227 strerror(errno));
228 (void)close(s2);
229 goto bad;
230 }
231again:
232 bzero(readsp, fdssize);
233 FD_SET(s, readsp);
234 FD_SET(s2, readsp);
235 errno = 0;
236 if (select(MAX(s, s2) + 1, readsp, 0, 0, 0) < 1 ||
237 !FD_ISSET(s2, readsp)) {
238 if (errno != 0)
239 (void)fprintf(stderr,
240 "rcmd: select (setting up stderr): %s\n",
241 strerror(errno));
242 else
243 (void)fprintf(stderr,
244 "select: protocol failure in circuit setup\n");
245 (void)close(s2);
246 goto bad;
247 }
248 s3 = accept(s2, (struct sockaddr *)&from, &len);
249 /*
250 * XXX careful for ftp bounce attacks. If discovered, shut them
251 * down and check for the real auxiliary channel to connect.
252 */
253 switch (from.ss_family) {
254 case AF_INET:
255 case AF_INET6:
256 if (getnameinfo((struct sockaddr *)&from, len,
257 NULL, 0, num, sizeof(num), NI_NUMERICSERV) == 0 &&
258 atoi(num) != 20) {
259 break;
260 }
261 close(s3);
262 goto again;
263 default:
264 break;
265 }
266 (void)close(s2);
267 if (s3 < 0) {
268 (void)fprintf(stderr,
269 "rcmd: accept: %s\n", strerror(errno));
270 lport = 0;
271 goto bad;
272 }
273 *fd2p = s3;
274 switch (from.ss_family) {
275 case AF_INET:
276 case AF_INET6:
277 if (getnameinfo((struct sockaddr *)&from, len,
278 NULL, 0, num, sizeof(num), NI_NUMERICSERV) != 0 ||
279 (atoi(num) >= IPPORT_RESERVED ||
280 atoi(num) < IPPORT_RESERVED / 2)) {
281 (void)fprintf(stderr,
282 "socket: protocol failure in circuit setup.\n");
283 goto bad2;
284 }
285 break;
286 default:
287 break;
288 }
289 }
290 (void)write(s, locuser, strlen(locuser)+1);
291 (void)write(s, remuser, strlen(remuser)+1);
292 (void)write(s, cmd, strlen(cmd)+1);
293 if (read(s, &c, 1) != 1) {
294 (void)fprintf(stderr,
295 "rcmd: %s: %s\n", *ahost, strerror(errno));
296 goto bad2;
297 }
298 if (c != 0) {
299 while (read(s, &c, 1) == 1) {
300 (void)write(STDERR_FILENO, &c, 1);
301 if (c == '\n')
302 break;
303 }
304 goto bad2;
305 }
306 sigprocmask(SIG_SETMASK, &oldmask, NULL);
307 free(readsp);
308 return (s);
309bad2:
310 if (lport)
311 (void)close(*fd2p);
312bad:
313 if (readsp)
314 free(readsp);
315 (void)close(s);
316 sigprocmask(SIG_SETMASK, &oldmask, NULL);
317 return (-1);
318}
319
320int __check_rhosts_file = 1;
321char *__rcmd_errstr;
322
323int
324ruserok(rhost, superuser, ruser, luser)
325 const char *rhost, *ruser, *luser;
326 int superuser;
327{
328 struct addrinfo hints, *res, *r;
329 int error;
330
331 memset(&hints, 0, sizeof(hints));
332 hints.ai_family = PF_UNSPEC;
333 hints.ai_socktype = SOCK_DGRAM; /*dummy*/
334 error = getaddrinfo(rhost, "0", &hints, &res);
335 if (error)
336 return (-1);
337
338 for (r = res; r; r = r->ai_next) {
339 if (iruserok_sa(r->ai_addr, r->ai_addrlen, superuser, ruser,
340 luser) == 0) {
341 freeaddrinfo(res);
342 return (0);
343 }
344 }
345 freeaddrinfo(res);
346 return (-1);
347}
348
349/*
350 * New .rhosts strategy: We are passed an ip address. We spin through
351 * hosts.equiv and .rhosts looking for a match. When the .rhosts only
352 * has ip addresses, we don't have to trust a nameserver. When it
353 * contains hostnames, we spin through the list of addresses the nameserver
354 * gives us and look for a match.
355 *
356 * Returns 0 if ok, -1 if not ok.
357 */
358int
359iruserok(raddr, superuser, ruser, luser)
360 u_int32_t raddr;
361 int superuser;
362 const char *ruser, *luser;
363{
364 struct sockaddr_in sin;
365
366 memset(&sin, 0, sizeof(sin));
367 sin.sin_family = AF_INET;
368 sin.sin_len = sizeof(struct sockaddr_in);
369 memcpy(&sin.sin_addr, &raddr, sizeof(sin.sin_addr));
370 return iruserok_sa(&sin, sizeof(struct sockaddr_in), superuser, ruser,
371 luser);
372}
373
374int
375iruserok_sa(raddr, rlen, superuser, ruser, luser)
376 const void *raddr;
377 int rlen;
378 int superuser;
379 const char *ruser, *luser;
380{
381 struct sockaddr *sa;
382 register char *cp;
383 struct stat sbuf;
384 struct passwd *pwd;
385 FILE *hostf;
386 uid_t uid;
387 int first;
388 char pbuf[MAXPATHLEN];
389
390 sa = (struct sockaddr *)raddr;
391 first = 1;
392 hostf = superuser ? NULL : fopen(_PATH_HEQUIV, "r");
393again:
394 if (hostf) {
395 if (__ivaliduser_sa(hostf, sa, rlen, luser, ruser) == 0) {
396 (void)fclose(hostf);
397 return (0);
398 }
399 (void)fclose(hostf);
400 }
401 if (first == 1 && (__check_rhosts_file || superuser)) {
402 first = 0;
403 if ((pwd = getpwnam(luser)) == NULL)
404 return (-1);
405 snprintf(pbuf, sizeof pbuf, "%s/.rhosts", pwd->pw_dir);
406
407 /*
408 * Change effective uid while opening .rhosts. If root and
409 * reading an NFS mounted file system, can't read files that
410 * are protected read/write owner only.
411 */
412 uid = geteuid();
413 (void)seteuid(pwd->pw_uid);
414 hostf = fopen(pbuf, "r");
415 (void)seteuid(uid);
416
417 if (hostf == NULL)
418 return (-1);
419 /*
420 * If not a regular file, or is owned by someone other than
421 * user or root or if writeable by anyone but the owner, quit.
422 */
423 cp = NULL;
424 if (lstat(pbuf, &sbuf) < 0)
425 cp = ".rhosts lstat failed";
426 else if (!S_ISREG(sbuf.st_mode))
427 cp = ".rhosts not regular file";
428 else if (fstat(fileno(hostf), &sbuf) < 0)
429 cp = ".rhosts fstat failed";
430 else if (sbuf.st_uid && sbuf.st_uid != pwd->pw_uid)
431 cp = "bad .rhosts owner";
432 else if (sbuf.st_mode & (S_IWGRP|S_IWOTH))
433 cp = ".rhosts writable by other than owner";
434 /* If there were any problems, quit. */
435 if (cp) {
436 __rcmd_errstr = cp;
437 (void)fclose(hostf);
438 return (-1);
439 }
440 goto again;
441 }
442 return (-1);
443}
444
445/*
446 * XXX
447 * Don't make static, used by lpd(8).
448 *
449 * Returns 0 if ok, -1 if not ok.
450 */
451int
452__ivaliduser(hostf, raddrl, luser, ruser)
453 FILE *hostf;
454 in_addr_t raddrl;
455 const char *luser, *ruser;
456{
457 struct sockaddr_in sin;
458
459 memset(&sin, 0, sizeof(sin));
460 sin.sin_family = AF_INET;
461 sin.sin_len = sizeof(struct sockaddr_in);
462 memcpy(&sin.sin_addr, &raddrl, sizeof(sin.sin_addr));
463 return __ivaliduser_sa(hostf, (struct sockaddr *)&sin, sin.sin_len,
464 luser, ruser);
465}
466
467int
468__ivaliduser_sa(hostf, raddr, salen, luser, ruser)
469 FILE *hostf;
470 struct sockaddr *raddr;
471 socklen_t salen;
472 const char *luser, *ruser;
473{
474 register char *user, *p;
475 char *buf;
476 const char *auser, *ahost;
477 int hostok, userok;
478 char *rhost = (char *)-1;
479 char domain[MAXHOSTNAMELEN];
480 size_t buflen;
481
482 getdomainname(domain, sizeof(domain));
483
484 while ((buf = fgetln(hostf, &buflen))) {
485 p = buf;
486 if (*p == '#')
487 continue;
488 while (p < buf + buflen && *p != '\n' && *p != ' ' && *p != '\t') {
489 if (!isprint(*p))
490 goto bail;
491 *p = isupper(*p) ? tolower(*p) : *p;
492 p++;
493 }
494 if (p >= buf + buflen)
495 continue;
496 if (*p == ' ' || *p == '\t') {
497 *p++ = '\0';
498 while (p < buf + buflen && (*p == ' ' || *p == '\t'))
499 p++;
500 if (p >= buf + buflen)
501 continue;
502 user = p;
503 while (p < buf + buflen && *p != '\n' && *p != ' ' &&
504 *p != '\t') {
505 if (!isprint(*p))
506 goto bail;
507 p++;
508 }
509 } else
510 user = p;
511 *p = '\0';
512
513 if (p == buf)
514 continue;
515
516 auser = *user ? user : luser;
517 ahost = buf;
518
519 if (strlen(ahost) >= MAXHOSTNAMELEN)
520 continue;
521
522 /*
523 * innetgr() must lookup a hostname (we do not attempt
524 * to change the semantics so that netgroups may have
525 * #.#.#.# addresses in the list.)
526 */
527 if (ahost[0] == '+')
528 switch (ahost[1]) {
529 case '\0':
530 hostok = 1;
531 break;
532 case '@':
533 if (rhost == (char *)-1)
534 rhost = __gethostloop(raddr, salen);
535 hostok = 0;
536 if (rhost)
537 hostok = innetgr(&ahost[2], rhost,
538 NULL, domain);
539 break;
540 default:
541 hostok = __icheckhost(raddr, salen, &ahost[1]);
542 break;
543 }
544 else if (ahost[0] == '-')
545 switch (ahost[1]) {
546 case '\0':
547 hostok = -1;
548 break;
549 case '@':
550 if (rhost == (char *)-1)
551 rhost = __gethostloop(raddr, salen);
552 hostok = 0;
553 if (rhost)
554 hostok = -innetgr(&ahost[2], rhost,
555 NULL, domain);
556 break;
557 default:
558 hostok = -__icheckhost(raddr, salen, &ahost[1]);
559 break;
560 }
561 else
562 hostok = __icheckhost(raddr, salen, ahost);
563
564
565 if (auser[0] == '+')
566 switch (auser[1]) {
567 case '\0':
568 userok = 1;
569 break;
570 case '@':
571 userok = innetgr(&auser[2], NULL, ruser,
572 domain);
573 break;
574 default:
575 userok = strcmp(ruser, &auser[1]) ? 0 : 1;
576 break;
577 }
578 else if (auser[0] == '-')
579 switch (auser[1]) {
580 case '\0':
581 userok = -1;
582 break;
583 case '@':
584 userok = -innetgr(&auser[2], NULL, ruser,
585 domain);
586 break;
587 default:
588 userok = strcmp(ruser, &auser[1]) ? 0 : -1;
589 break;
590 }
591 else
592 userok = strcmp(ruser, auser) ? 0 : 1;
593
594 /* Check if one component did not match */
595 if (hostok == 0 || userok == 0)
596 continue;
597
598 /* Check if we got a forbidden pair */
599 if (userok <= -1 || hostok <= -1)
600 return (-1);
601
602 /* Check if we got a valid pair */
603 if (hostok >= 1 && userok >= 1)
604 return (0);
605 }
606bail:
607 return (-1);
608}
609
610/*
611 * Returns "true" if match, 0 if no match. If we do not find any
612 * semblance of an A->PTR->A loop, allow a simple #.#.#.# match to work.
613 *
614 * NI_WITHSCOPEID is useful for comparing sin6_scope_id portion
615 * if af == AF_INET6.
616 */
617static int
618__icheckhost(raddr, salen, lhost)
619 struct sockaddr *raddr;
620 socklen_t salen;
621 const char *lhost;
622{
623 struct addrinfo hints, *res, *r;
624 char h1[NI_MAXHOST], h2[NI_MAXHOST];
625 int error;
626#ifdef NI_WITHSCOPEID
627 const int niflags = NI_NUMERICHOST | NI_WITHSCOPEID;
628#else
629 const int niflags = NI_NUMERICHOST;
630#endif
631
632 h1[0] = '\0';
633 if (getnameinfo(raddr, salen, h1, sizeof(h1), NULL, 0,
634 niflags) != 0)
635 return (0);
636
637 /* Resolve laddr into sockaddr */
638 memset(&hints, 0, sizeof(hints));
639 hints.ai_family = raddr->sa_family;
640 hints.ai_socktype = SOCK_DGRAM; /*dummy*/
641 res = NULL;
642 error = getaddrinfo(lhost, "0", &hints, &res);
643 if (error)
644 return (0);
645
646 /*
647 * Try string comparisons between raddr and laddr.
648 */
649 for (r = res; r; r = r->ai_next) {
650 h2[0] = '\0';
651 if (getnameinfo(r->ai_addr, r->ai_addrlen, h2, sizeof(h2),
652 NULL, 0, niflags) != 0)
653 continue;
654 if (strcmp(h1, h2) == 0) {
655 freeaddrinfo(res);
656 return (1);
657 }
658 }
659
660 /* No match. */
661 freeaddrinfo(res);
662 return (0);
663}
664
665/*
666 * Return the hostname associated with the supplied address.
667 * Do a reverse lookup as well for security. If a loop cannot
668 * be found, pack the result of inet_ntoa() into the string.
669 *
670 * NI_WITHSCOPEID is useful for comparing sin6_scope_id portion
671 * if af == AF_INET6.
672 */
673static char *
674__gethostloop(raddr, salen)
675 struct sockaddr *raddr;
676 socklen_t salen;
677{
678 static char remotehost[NI_MAXHOST];
679 char h1[NI_MAXHOST], h2[NI_MAXHOST];
680 struct addrinfo hints, *res, *r;
681 int error;
682#ifdef NI_WITHSCOPEID
683 const int niflags = NI_NUMERICHOST | NI_WITHSCOPEID;
684#else
685 const int niflags = NI_NUMERICHOST;
686#endif
687
688 h1[0] = remotehost[0] = '\0';
689 if (getnameinfo(raddr, salen, remotehost, sizeof(remotehost),
690 NULL, 0, NI_NAMEREQD) != 0)
691 return (NULL);
692 if (getnameinfo(raddr, salen, h1, sizeof(h1), NULL, 0,
693 niflags) != 0)
694 return (NULL);
695
696 /*
697 * Look up the name and check that the supplied
698 * address is in the list
699 */
700 memset(&hints, 0, sizeof(hints));
701 hints.ai_family = raddr->sa_family;
702 hints.ai_socktype = SOCK_DGRAM; /*dummy*/
703 hints.ai_flags = AI_CANONNAME;
704 res = NULL;
705 error = getaddrinfo(remotehost, "0", &hints, &res);
706 if (error)
707 return (NULL);
708
709 for (r = res; r; r = r->ai_next) {
710 h2[0] = '\0';
711 if (getnameinfo(r->ai_addr, r->ai_addrlen, h2, sizeof(h2),
712 NULL, 0, niflags) != 0)
713 continue;
714 if (strcmp(h1, h2) == 0) {
715 freeaddrinfo(res);
716 return (remotehost);
717 }
718 }
719
720 /*
721 * either the DNS adminstrator has made a configuration
722 * mistake, or someone has attempted to spoof us
723 */
724 syslog(LOG_NOTICE, "rcmd: address %s not listed for host %s",
725 h1, res->ai_canonname ? res->ai_canonname : remotehost);
726 freeaddrinfo(res);
727 return (NULL);
728}
diff --git a/src/lib/libc/net/rcmdsh.3 b/src/lib/libc/net/rcmdsh.3
new file mode 100644
index 0000000000..be566f09ca
--- /dev/null
+++ b/src/lib/libc/net/rcmdsh.3
@@ -0,0 +1,96 @@
1.\" $OpenBSD: rcmdsh.3,v 1.11 2003/06/02 20:18:35 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. Neither the name of the University nor the names of its contributors
15.\" may be used to endorse or promote products derived from this software
16.\" without specific prior written permission.
17.\"
18.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28.\" SUCH DAMAGE.
29.\"
30.Dd May 5, 2003
31.Dt RCMDSH 3
32.Os
33.Sh NAME
34.Nm rcmdsh
35.Nd return a stream to a remote command without superuser
36.Sh SYNOPSIS
37.Fd #include <unistd.h>
38.Ft int
39.Fn rcmdsh "char **ahost" "int inport" "const char *locuser" "const char *remuser" "const char *cmd" "char *rshprog"
40.Sh DESCRIPTION
41The
42.Fn rcmdsh
43function is used by normal users to execute a command on a remote machine
44using an authentication scheme based on reserved port numbers using
45.Xr rsh 1
46or the value of
47.Fa rshprog
48(if non-null).
49.Fa rshprog
50may be a fully-qualified path, a non-qualified command, or a command containing
51space-separated command line arguments.
52.Pp
53The
54.Fn rcmdsh
55function looks up the host
56.Fa *ahost
57using
58.Xr gethostbyname 3 ,
59returning \-1 if the host does not exist.
60Otherwise
61.Fa *ahost
62is set to the standard name of the host and a connection is established to
63a server residing at the well-known Internet port
64.Li shell/tcp
65(or whatever port is used by
66.Fa rshprog ) .
67The parameter
68.Fa inport
69is ignored; it is only included to provide an interface similar to
70.Xr rcmd 3 .
71.Pp
72If the connection succeeds, a socket in the
73.Tn UNIX
74domain of type
75.Dv SOCK_STREAM
76is returned to the caller, and given to the remote
77command as stdin and stdout, and stderr.
78.Sh DIAGNOSTICS
79The
80.Fn rcmdsh
81function returns a valid socket descriptor on success.
82It returns \-1 on error and prints a diagnostic message on the standard error.
83.Sh SEE ALSO
84.Xr rsh 1 ,
85.Xr socketpair 2 ,
86.Xr rcmd 3 ,
87.Xr rshd 8
88.Sh HISTORY
89The
90.Fn rcmdsh
91function first appeared in
92.Ox 2.0 .
93.Sh BUGS
94If
95.Xr rsh 1
96encounters an error, a file descriptor is still returned instead of \-1.
diff --git a/src/lib/libc/net/rcmdsh.c b/src/lib/libc/net/rcmdsh.c
new file mode 100644
index 0000000000..2a2a5d77fe
--- /dev/null
+++ b/src/lib/libc/net/rcmdsh.c
@@ -0,0 +1,192 @@
1/* $OpenBSD: rcmdsh.c,v 1.8 2003/05/05 22:13:03 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.8 2003/05/05 22:13:03 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 <stdlib.h>
48#include <string.h>
49#include <pwd.h>
50#include <paths.h>
51#include <unistd.h>
52
53/*
54 * This is a replacement rcmd() function that uses the rsh(1)
55 * program in place of a direct rcmd(3) function call so as to
56 * avoid having to be root. Note that rport is ignored.
57 */
58/* ARGSUSED */
59int
60rcmdsh(ahost, rport, locuser, remuser, cmd, rshprog)
61 char **ahost;
62 int rport;
63 const char *locuser, *remuser, *cmd;
64 char *rshprog;
65{
66 struct hostent *hp;
67 int sp[2];
68 pid_t cpid;
69 char *p;
70 struct passwd *pw;
71
72 /* What rsh/shell to use. */
73 if (rshprog == NULL)
74 rshprog = _PATH_RSH;
75
76 /* locuser must exist on this host. */
77 if ((pw = getpwnam(locuser)) == NULL) {
78 (void) fprintf(stderr, "rcmdsh: unknown user: %s\n", locuser);
79 return(-1);
80 }
81
82 /* Validate remote hostname. */
83 if (strcmp(*ahost, "localhost") != 0) {
84 if ((hp = gethostbyname(*ahost)) == NULL) {
85 herror(*ahost);
86 return(-1);
87 }
88 *ahost = hp->h_name;
89 }
90
91 /* Get a socketpair we'll use for stdin and stdout. */
92 if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, sp) < 0) {
93 perror("rcmdsh: socketpair");
94 return(-1);
95 }
96
97 cpid = fork();
98 if (cpid < 0) {
99 perror("rcmdsh: fork failed");
100 return(-1);
101 } else if (cpid == 0) {
102 /*
103 * Child. We use sp[1] to be stdin/stdout, and close sp[0].
104 */
105 (void) close(sp[0]);
106 if (dup2(sp[1], 0) < 0 || dup2(0, 1) < 0) {
107 perror("rcmdsh: dup2 failed");
108 _exit(255);
109 }
110 /* Fork again to lose parent. */
111 cpid = fork();
112 if (cpid < 0) {
113 perror("rcmdsh: fork to lose parent failed");
114 _exit(255);
115 }
116 if (cpid > 0)
117 _exit(0);
118
119 /* In grandchild here. Become local user for rshprog. */
120 if (setuid(pw->pw_uid)) {
121 (void) fprintf(stderr, "rcmdsh: setuid(%u): %s\n",
122 pw->pw_uid, strerror(errno));
123 _exit(255);
124 }
125
126 /*
127 * If remote host is "localhost" and local and remote user
128 * are the same, avoid running remote shell for efficiency.
129 */
130 if (!strcmp(*ahost, "localhost") && !strcmp(locuser, remuser)) {
131 char *argv[4];
132 if (pw->pw_shell[0] == '\0')
133 rshprog = _PATH_BSHELL;
134 else
135 rshprog = pw->pw_shell;
136 p = strrchr(rshprog, '/');
137 argv[0] = p ? p + 1 : rshprog;
138 argv[1] = "-c";
139 argv[2] = (char *)cmd;
140 argv[3] = NULL;
141 execvp(rshprog, argv);
142 } else if ((p = strchr(rshprog, ' ')) == NULL) {
143 /* simple case */
144 char *argv[6];
145 p = strrchr(rshprog, '/');
146 argv[0] = p ? p + 1 : rshprog;
147 argv[1] = "-l";
148 argv[2] = (char *)remuser;
149 argv[3] = *ahost;
150 argv[4] = (char *)cmd;
151 argv[5] = NULL;
152 execvp(rshprog, argv);
153 } else {
154 /* must pull args out of rshprog and dyn alloc argv */
155 char **argv, **ap;
156 int n;
157 for (n = 7; (p = strchr(++p, ' ')) != NULL; n++)
158 continue;
159 rshprog = strdup(rshprog);
160 ap = argv = malloc(sizeof(char *) * n);
161 if (rshprog == NULL || argv == NULL) {
162 perror("rcmdsh");
163 _exit(255);
164 }
165 while ((p = strsep(&rshprog, " ")) != NULL) {
166 if (*p == '\0')
167 continue;
168 *ap++ = p;
169 }
170 if (ap != argv) /* all spaces?!? */
171 rshprog = argv[0];
172 if ((p = strrchr(argv[0], '/')) != NULL)
173 argv[0] = p + 1;
174 *ap++ = "-l";
175 *ap++ = (char *)remuser;
176 *ap++ = *ahost;
177 *ap++ = (char *)cmd;
178 *ap++ = NULL;
179 execvp(rshprog, argv);
180 }
181 (void) fprintf(stderr, "rcmdsh: execvp %s failed: %s\n",
182 rshprog, strerror(errno));
183 _exit(255);
184 } else {
185 /* Parent. close sp[1], return sp[0]. */
186 (void) close(sp[1]);
187 /* Reap child. */
188 (void) wait(NULL);
189 return(sp[0]);
190 }
191 /* NOTREACHED */
192}
diff --git a/src/lib/libc/net/recv.c b/src/lib/libc/net/recv.c
new file mode 100644
index 0000000000..0947465377
--- /dev/null
+++ b/src/lib/libc/net/recv.c
@@ -0,0 +1,46 @@
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. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char rcsid[] = "$OpenBSD: recv.c,v 1.3 2003/06/02 20:18:35 millert Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <sys/types.h>
35#include <sys/socket.h>
36
37#include <stddef.h>
38
39ssize_t
40recv(s, buf, len, flags)
41 int s, flags;
42 size_t len;
43 void *buf;
44{
45 return (recvfrom(s, buf, len, flags, NULL, 0));
46}
diff --git a/src/lib/libc/net/res_comp.c b/src/lib/libc/net/res_comp.c
new file mode 100644
index 0000000000..c10eb52931
--- /dev/null
+++ b/src/lib/libc/net/res_comp.c
@@ -0,0 +1,499 @@
1/* $OpenBSD: res_comp.c,v 1.11 2003/06/02 20:18: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. 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)
55#if 0
56static char sccsid[] = "@(#)res_comp.c 8.1 (Berkeley) 6/4/93";
57static char rcsid[] = "$From: res_comp.c,v 8.11 1996/12/02 09:17:22 vixie Exp $";
58#else
59static char rcsid[] = "$OpenBSD: res_comp.c,v 1.11 2003/06/02 20:18:36 millert Exp $";
60#endif
61#endif /* LIBC_SCCS and not lint */
62
63#include <sys/types.h>
64#include <sys/param.h>
65#include <netinet/in.h>
66#include <arpa/nameser.h>
67
68#include <stdio.h>
69#include <resolv.h>
70#include <ctype.h>
71
72#include <unistd.h>
73#include <string.h>
74
75static int dn_find(u_char *, u_char *, u_char **, u_char **);
76
77/*
78 * Expand compressed domain name 'comp_dn' to full domain name.
79 * 'msg' is a pointer to the begining of the message,
80 * 'eomorig' points to the first location after the message,
81 * 'exp_dn' is a pointer to a buffer of size 'length' for the result.
82 * Return size of compressed name or -1 if there was an error.
83 */
84int
85dn_expand(msg, eomorig, comp_dn, exp_dn, length)
86 const u_char *msg, *eomorig, *comp_dn;
87 char *exp_dn;
88 int length;
89{
90 register const u_char *cp;
91 register char *dn;
92 register int n, c;
93 char *eom;
94 int len = -1, checked = 0;
95
96 dn = exp_dn;
97 cp = comp_dn;
98 if (length > MAXHOSTNAMELEN-1)
99 length = MAXHOSTNAMELEN-1;
100 eom = exp_dn + length;
101 /*
102 * fetch next label in domain name
103 */
104 while ((n = *cp++)) {
105 /*
106 * Check for indirection
107 */
108 switch (n & INDIR_MASK) {
109 case 0:
110 if (dn != exp_dn) {
111 if (dn >= eom)
112 return (-1);
113 *dn++ = '.';
114 }
115 if (dn+n >= eom)
116 return (-1);
117 checked += n + 1;
118 while (--n >= 0) {
119 if (((c = *cp++) == '.') || (c == '\\')) {
120 if (dn + n + 2 >= eom)
121 return (-1);
122 *dn++ = '\\';
123 }
124 *dn++ = c;
125 if (cp >= eomorig) /* out of range */
126 return (-1);
127 }
128 break;
129
130 case INDIR_MASK:
131 if (len < 0)
132 len = cp - comp_dn + 1;
133 cp = msg + (((n & 0x3f) << 8) | (*cp & 0xff));
134 if (cp < msg || cp >= eomorig) /* out of range */
135 return (-1);
136 checked += 2;
137 /*
138 * Check for loops in the compressed name;
139 * if we've looked at the whole message,
140 * there must be a loop.
141 */
142 if (checked >= eomorig - msg)
143 return (-1);
144 break;
145
146 default:
147 return (-1); /* flag error */
148 }
149 }
150 *dn = '\0';
151 if (len < 0)
152 len = cp - comp_dn;
153 return (len);
154}
155
156/*
157 * Compress domain name 'exp_dn' into 'comp_dn'.
158 * Return the size of the compressed name or -1.
159 * 'length' is the size of the array pointed to by 'comp_dn'.
160 * 'dnptrs' is a list of pointers to previous compressed names. dnptrs[0]
161 * is a pointer to the beginning of the message. The list ends with NULL.
162 * 'lastdnptr' is a pointer to the end of the arrary pointed to
163 * by 'dnptrs'. Side effect is to update the list of pointers for
164 * labels inserted into the message as we compress the name.
165 * If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr'
166 * is NULL, we don't update the list.
167 */
168int
169dn_comp(exp_dn, comp_dn, length, dnptrs, lastdnptr)
170 const char *exp_dn;
171 u_char *comp_dn, **dnptrs, **lastdnptr;
172 int length;
173{
174 register u_char *cp, *dn;
175 register int c, l;
176 u_char **cpp, **lpp, *sp, *eob;
177 u_char *msg;
178
179 dn = (u_char *)exp_dn;
180 cp = comp_dn;
181 eob = cp + length;
182 lpp = cpp = NULL;
183 if (dnptrs != NULL) {
184 if ((msg = *dnptrs++) != NULL) {
185 for (cpp = dnptrs; *cpp != NULL; cpp++)
186 ;
187 lpp = cpp; /* end of list to search */
188 }
189 } else
190 msg = NULL;
191 for (c = *dn++; c != '\0'; ) {
192 /* look to see if we can use pointers */
193 if (msg != NULL) {
194 if ((l = dn_find(dn-1, msg, dnptrs, lpp)) >= 0) {
195 if (cp+1 >= eob)
196 return (-1);
197 *cp++ = (l >> 8) | INDIR_MASK;
198 *cp++ = l % 256;
199 return (cp - comp_dn);
200 }
201 /* not found, save it */
202 if (lastdnptr != NULL && cpp < lastdnptr-1) {
203 *cpp++ = cp;
204 *cpp = NULL;
205 }
206 }
207 sp = cp++; /* save ptr to length byte */
208 do {
209 if (c == '.') {
210 c = *dn++;
211 break;
212 }
213 if (c == '\\') {
214 if ((c = *dn++) == '\0')
215 break;
216 }
217 if (cp >= eob) {
218 if (msg != NULL)
219 *lpp = NULL;
220 return (-1);
221 }
222 *cp++ = c;
223 } while ((c = *dn++) != '\0');
224 /* catch trailing '.'s but not '..' */
225 if ((l = cp - sp - 1) == 0 && c == '\0') {
226 cp--;
227 break;
228 }
229 if (l <= 0 || l > MAXLABEL) {
230 if (msg != NULL)
231 *lpp = NULL;
232 return (-1);
233 }
234 *sp = l;
235 }
236 if (cp >= eob) {
237 if (msg != NULL)
238 *lpp = NULL;
239 return (-1);
240 }
241 *cp++ = '\0';
242 return (cp - comp_dn);
243}
244
245/*
246 * Skip over a compressed domain name. Return the size or -1.
247 */
248int
249__dn_skipname(comp_dn, eom)
250 const u_char *comp_dn, *eom;
251{
252 register const u_char *cp;
253 register int n;
254
255 cp = comp_dn;
256 while (cp < eom && (n = *cp++)) {
257 /*
258 * check for indirection
259 */
260 switch (n & INDIR_MASK) {
261 case 0: /* normal case, n == len */
262 cp += n;
263 continue;
264 case INDIR_MASK: /* indirection */
265 cp++;
266 break;
267 default: /* illegal type */
268 return (-1);
269 }
270 break;
271 }
272 if (cp > eom)
273 return (-1);
274 return (cp - comp_dn);
275}
276
277static int
278mklower(ch)
279 register int ch;
280{
281 if (isascii(ch) && isupper(ch))
282 return (tolower(ch));
283 return (ch);
284}
285
286/*
287 * Search for expanded name from a list of previously compressed names.
288 * Return the offset from msg if found or -1.
289 * dnptrs is the pointer to the first name on the list,
290 * not the pointer to the start of the message.
291 */
292static int
293dn_find(exp_dn, msg, dnptrs, lastdnptr)
294 u_char *exp_dn, *msg;
295 u_char **dnptrs, **lastdnptr;
296{
297 register u_char *dn, *cp, **cpp;
298 register int n;
299 u_char *sp;
300
301 for (cpp = dnptrs; cpp < lastdnptr; cpp++) {
302 dn = exp_dn;
303 sp = cp = *cpp;
304 while ((n = *cp++)) {
305 /*
306 * check for indirection
307 */
308 switch (n & INDIR_MASK) {
309 case 0: /* normal case, n == len */
310 while (--n >= 0) {
311 if (*dn == '.')
312 goto next;
313 if (*dn == '\\')
314 dn++;
315 if (mklower(*dn++) != mklower(*cp++))
316 goto next;
317 }
318 if ((n = *dn++) == '\0' && *cp == '\0')
319 return (sp - msg);
320 if (n == '.')
321 continue;
322 goto next;
323
324 case INDIR_MASK: /* indirection */
325 cp = msg + (((n & 0x3f) << 8) | *cp);
326 break;
327
328 default: /* illegal type */
329 return (-1);
330 }
331 }
332 if (*dn == '\0')
333 return (sp - msg);
334 next: ;
335 }
336 return (-1);
337}
338
339/*
340 * Verify that a domain name uses an acceptable character set.
341 */
342
343/*
344 * Note the conspicuous absence of ctype macros in these definitions. On
345 * non-ASCII hosts, we can't depend on string literals or ctype macros to
346 * tell us anything about network-format data. The rest of the BIND system
347 * is not careful about this, but for some reason, we're doing it right here.
348 */
349#define PERIOD 0x2e
350#define hyphenchar(c) ((c) == 0x2d)
351#define bslashchar(c) ((c) == 0x5c)
352#define periodchar(c) ((c) == PERIOD)
353#define asterchar(c) ((c) == 0x2a)
354#define alphachar(c) (((c) >= 0x41 && (c) <= 0x5a) \
355 || ((c) >= 0x61 && (c) <= 0x7a))
356#define digitchar(c) ((c) >= 0x30 && (c) <= 0x39)
357
358#define borderchar(c) (alphachar(c) || digitchar(c))
359#define middlechar(c) (borderchar(c) || hyphenchar(c))
360#define domainchar(c) ((c) > 0x20 && (c) < 0x7f)
361
362int
363res_hnok(dn)
364 const char *dn;
365{
366 int pch = PERIOD, ch = *dn++;
367
368 while (ch != '\0') {
369 int nch = *dn++;
370
371 if (periodchar(ch)) {
372 ;
373 } else if (periodchar(pch)) {
374 if (!borderchar(ch))
375 return (0);
376 } else if (periodchar(nch) || nch == '\0') {
377 if (!borderchar(ch))
378 return (0);
379 } else {
380 if (!middlechar(ch))
381 return (0);
382 }
383 pch = ch, ch = nch;
384 }
385 return (1);
386}
387
388/*
389 * hostname-like (A, MX, WKS) owners can have "*" as their first label
390 * but must otherwise be as a host name.
391 */
392int
393res_ownok(dn)
394 const char *dn;
395{
396 if (asterchar(dn[0])) {
397 if (periodchar(dn[1]))
398 return (res_hnok(dn+2));
399 if (dn[1] == '\0')
400 return (1);
401 }
402 return (res_hnok(dn));
403}
404
405/*
406 * SOA RNAMEs and RP RNAMEs can have any printable character in their first
407 * label, but the rest of the name has to look like a host name.
408 */
409int
410res_mailok(dn)
411 const char *dn;
412{
413 int ch, escaped = 0;
414
415 /* "." is a valid missing representation */
416 if (*dn == '\0')
417 return(1);
418
419 /* otherwise <label>.<hostname> */
420 while ((ch = *dn++) != '\0') {
421 if (!domainchar(ch))
422 return (0);
423 if (!escaped && periodchar(ch))
424 break;
425 if (escaped)
426 escaped = 0;
427 else if (bslashchar(ch))
428 escaped = 1;
429 }
430 if (periodchar(ch))
431 return (res_hnok(dn));
432 return(0);
433}
434
435/*
436 * This function is quite liberal, since RFC 1034's character sets are only
437 * recommendations.
438 */
439int
440res_dnok(dn)
441 const char *dn;
442{
443 int ch;
444
445 while ((ch = *dn++) != '\0')
446 if (!domainchar(ch))
447 return (0);
448 return (1);
449}
450
451/*
452 * Routines to insert/extract short/long's.
453 */
454
455u_int16_t
456_getshort(msgp)
457 register const u_char *msgp;
458{
459 register u_int16_t u;
460
461 GETSHORT(u, msgp);
462 return (u);
463}
464
465#ifdef NeXT
466/*
467 * nExt machines have some funky library conventions, which we must maintain.
468 */
469u_int16_t
470res_getshort(msgp)
471 register const u_char *msgp;
472{
473 return (_getshort(msgp));
474}
475#endif
476
477u_int32_t
478_getlong(msgp)
479 register const u_char *msgp;
480{
481 register u_int32_t u;
482
483 GETLONG(u, msgp);
484 return (u);
485}
486
487void
488__putshort(register u_int16_t s, register u_char *msgp)
489{
490 PUTSHORT(s, msgp);
491}
492
493void
494__putlong(l, msgp)
495 register u_int32_t l;
496 register u_char *msgp;
497{
498 PUTLONG(l, msgp);
499}
diff --git a/src/lib/libc/net/res_data.c b/src/lib/libc/net/res_data.c
new file mode 100644
index 0000000000..967264bcb7
--- /dev/null
+++ b/src/lib/libc/net/res_data.c
@@ -0,0 +1,113 @@
1/* $OpenBSD: res_data.c,v 1.2 2003/06/02 20:18:36 millert 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. 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)
55#if 0
56static char rcsid[] = "$From: res_data.c,v 8.2 1996/08/05 08:31:35 vixie Exp $";
57#else
58static char rcsid[] = "$OpenBSD: res_data.c,v 1.2 2003/06/02 20:18:36 millert Exp $";
59#endif
60#endif /* LIBC_SCCS and not lint */
61
62#include <sys/types.h>
63#include <sys/param.h>
64#include <sys/socket.h>
65#include <sys/time.h>
66#include <netinet/in.h>
67#include <arpa/inet.h>
68#include <arpa/nameser.h>
69
70#include <stdio.h>
71#include <ctype.h>
72#include <resolv.h>
73#include <unistd.h>
74#include <stdlib.h>
75#include <string.h>
76
77const char *_res_opcodes[] = {
78 "QUERY",
79 "IQUERY",
80 "CQUERYM",
81 "CQUERYU", /* experimental */
82 "NOTIFY", /* experimental */
83 "5",
84 "6",
85 "7",
86 "8",
87 "UPDATEA",
88 "UPDATED",
89 "UPDATEDA",
90 "UPDATEM",
91 "UPDATEMA",
92 "ZONEINIT",
93 "ZONEREF",
94};
95
96const char *_res_resultcodes[] = {
97 "NOERROR",
98 "FORMERR",
99 "SERVFAIL",
100 "NXDOMAIN",
101 "NOTIMP",
102 "REFUSED",
103 "6",
104 "7",
105 "8",
106 "9",
107 "10",
108 "11",
109 "12",
110 "13",
111 "14",
112 "NOCHANGE",
113};
diff --git a/src/lib/libc/net/res_debug.c b/src/lib/libc/net/res_debug.c
new file mode 100644
index 0000000000..8f66c7d009
--- /dev/null
+++ b/src/lib/libc/net/res_debug.c
@@ -0,0 +1,1561 @@
1/* $OpenBSD: res_debug.c,v 1.17 2003/06/02 20:18:36 millert 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. 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 * Portions Copyright (c) 1995 by International Business Machines, Inc.
52 *
53 * International Business Machines, Inc. (hereinafter called IBM) grants
54 * permission under its copyrights to use, copy, modify, and distribute this
55 * Software with or without fee, provided that the above copyright notice and
56 * all paragraphs of this notice appear in all copies, and that the name of IBM
57 * not be used in connection with the marketing of any product incorporating
58 * the Software or modifications thereof, without specific, written prior
59 * permission.
60 *
61 * To the extent it has a right to do so, IBM grants an immunity from suit
62 * under its patents, if any, for the use, sale or manufacture of products to
63 * the extent that such products are used for performing Domain Name System
64 * dynamic updates in TCP/IP networks by means of the Software. No immunity is
65 * granted for any product per se or for any other function of any product.
66 *
67 * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
68 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
69 * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
70 * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
71 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
72 * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
73 * --Copyright--
74 */
75
76#if defined(LIBC_SCCS) && !defined(lint)
77#if 0
78static char sccsid[] = "@(#)res_debug.c 8.1 (Berkeley) 6/4/93";
79static char rcsid[] = "$From: res_debug.c,v 8.19 1996/11/26 10:11:23 vixie Exp $";
80#else
81static char rcsid[] = "$OpenBSD: res_debug.c,v 1.17 2003/06/02 20:18:36 millert Exp $";
82#endif
83#endif /* LIBC_SCCS and not lint */
84
85#include <sys/param.h>
86#include <sys/types.h>
87#include <sys/socket.h>
88#include <netinet/in.h>
89#include <arpa/inet.h>
90#include <arpa/nameser.h>
91
92#include <ctype.h>
93#include <netdb.h>
94#include <resolv.h>
95#include <stdio.h>
96#include <time.h>
97
98#include <stdlib.h>
99#include <string.h>
100
101#include "thread_private.h"
102
103extern const char *_res_opcodes[];
104extern const char *_res_resultcodes[];
105
106static const char *loc_ntoal(const u_char *binary, char *ascii, int ascii_len);
107
108/* XXX: we should use getservbyport() instead. */
109static const char *
110dewks(wks)
111 int wks;
112{
113 static char nbuf[20];
114
115 switch (wks) {
116 case 5: return "rje";
117 case 7: return "echo";
118 case 9: return "discard";
119 case 11: return "systat";
120 case 13: return "daytime";
121 case 15: return "netstat";
122 case 17: return "qotd";
123 case 19: return "chargen";
124 case 20: return "ftp-data";
125 case 21: return "ftp";
126 case 23: return "telnet";
127 case 25: return "smtp";
128 case 37: return "time";
129 case 39: return "rlp";
130 case 42: return "name";
131 case 43: return "whois";
132 case 53: return "domain";
133 case 57: return "apts";
134 case 59: return "apfs";
135 case 67: return "bootps";
136 case 68: return "bootpc";
137 case 69: return "tftp";
138 case 77: return "rje";
139 case 79: return "finger";
140 case 87: return "link";
141 case 95: return "supdup";
142 case 100: return "newacct";
143 case 101: return "hostnames";
144 case 102: return "iso-tsap";
145 case 103: return "x400";
146 case 104: return "x400-snd";
147 case 105: return "csnet-ns";
148 case 109: return "pop-2";
149 case 111: return "sunrpc";
150 case 113: return "auth";
151 case 115: return "sftp";
152 case 117: return "uucp-path";
153 case 119: return "nntp";
154 case 121: return "erpc";
155 case 123: return "ntp";
156 case 133: return "statsrv";
157 case 136: return "profile";
158 case 144: return "NeWS";
159 case 161: return "snmp";
160 case 162: return "snmp-trap";
161 case 170: return "print-srv";
162 default:
163 (void) snprintf(nbuf, sizeof nbuf, "%d", wks);
164 return (nbuf);
165 }
166}
167
168/* XXX: we should use getprotobynumber() instead. */
169static const char *
170deproto(protonum)
171 int protonum;
172{
173 static char nbuf[20];
174
175 switch (protonum) {
176 case 1: return "icmp";
177 case 2: return "igmp";
178 case 3: return "ggp";
179 case 5: return "st";
180 case 6: return "tcp";
181 case 7: return "ucl";
182 case 8: return "egp";
183 case 9: return "igp";
184 case 11: return "nvp-II";
185 case 12: return "pup";
186 case 16: return "chaos";
187 case 17: return "udp";
188 default:
189 (void) snprintf(nbuf, sizeof nbuf, "%d", protonum);
190 return (nbuf);
191 }
192}
193
194static const u_char *
195do_rrset(msg, len, cp, cnt, pflag, file, hs)
196 int cnt, pflag, len;
197 const u_char *cp, *msg;
198 const char *hs;
199 FILE *file;
200{
201 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
202 int n;
203 int sflag;
204
205 /*
206 * Print answer records.
207 */
208 sflag = (_resp->pfcode & pflag);
209 if ((n = ntohs(cnt))) {
210 if ((!_resp->pfcode) ||
211 ((sflag) && (_resp->pfcode & RES_PRF_HEAD1)))
212 fprintf(file, "%s", hs);
213 while (--n >= 0) {
214 if ((!_resp->pfcode) || sflag) {
215 cp = p_rr(cp, msg, file);
216 } else {
217 unsigned int dlen;
218 cp += __dn_skipname(cp, cp + MAXCDNAME);
219 cp += INT16SZ;
220 cp += INT16SZ;
221 cp += INT32SZ;
222 dlen = _getshort((u_char*)cp);
223 cp += INT16SZ;
224 cp += dlen;
225 }
226 if ((cp - msg) > len)
227 return (NULL);
228 }
229 if ((!_resp->pfcode) ||
230 ((sflag) && (_resp->pfcode & RES_PRF_HEAD1)))
231 putc('\n', file);
232 }
233 return (cp);
234}
235
236void
237__p_query(msg)
238 const u_char *msg;
239{
240 __fp_query(msg, stdout);
241}
242
243/*
244 * Print the current options.
245 * This is intended to be primarily a debugging routine.
246 */
247void
248__fp_resstat(statp, file)
249 struct __res_state *statp;
250 FILE *file;
251{
252 register u_long mask;
253
254 fprintf(file, ";; res options:");
255 if (!statp)
256 statp = &_res;
257 for (mask = 1; mask != 0; mask <<= 1)
258 if (statp->options & mask)
259 fprintf(file, " %s", p_option(mask));
260 putc('\n', file);
261}
262
263/*
264 * Print the contents of a query.
265 * This is intended to be primarily a debugging routine.
266 */
267void
268__fp_nquery(msg, len, file)
269 const u_char *msg;
270 int len;
271 FILE *file;
272{
273 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
274 register const u_char *cp, *endMark;
275 register const HEADER *hp;
276 register int n;
277
278 if ((_resp->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 ((!_resp->pfcode) || (_resp->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 ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_HEADX))
298 putc(';', file);
299 if ((!_resp->pfcode) || (_resp->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 ((!_resp->pfcode) || (_resp->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 ((!_resp->pfcode) || (_resp->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 ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_QUES))
333 fprintf(file, ";; QUESTIONS:\n");
334 while (--n >= 0) {
335 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_QUES))
336 fprintf(file, ";;\t");
337 TruncTest(cp);
338 if ((!_resp->pfcode) || (_resp->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 ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_QUES))
353 fprintf(file, ", type = %s",
354 __p_type(_getshort((u_char*)cp)));
355 cp += INT16SZ;
356 TruncTest(cp);
357 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_QUES))
358 fprintf(file, ", class = %s\n",
359 __p_class(_getshort((u_char*)cp)));
360 cp += INT16SZ;
361 if ((!_resp->pfcode) || (_resp->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 strlcpy(name + newlen, ".", namelen - 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 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
482 int type, class, dlen, n, c;
483 struct in_addr inaddr;
484 const u_char *cp1, *cp2;
485 u_int32_t tmpttl, t;
486 int lcnt;
487 u_int16_t keyflags;
488 char rrname[MAXDNAME]; /* The fqdn of this RR */
489 char base64_key[MAX_KEY_BASE64];
490
491 if ((_resp->options & RES_INIT) == 0 && res_init() == -1) {
492 h_errno = NETDB_INTERNAL;
493 return (NULL);
494 }
495 cp = __p_fqnname(cp, msg, MAXCDNAME, rrname, sizeof rrname);
496 if (!cp)
497 return (NULL); /* compression error */
498 fputs(rrname, file);
499
500 type = _getshort((u_char*)cp);
501 cp += INT16SZ;
502 class = _getshort((u_char*)cp);
503 cp += INT16SZ;
504 tmpttl = _getlong((u_char*)cp);
505 cp += INT32SZ;
506 dlen = _getshort((u_char*)cp);
507 cp += INT16SZ;
508 cp1 = cp;
509 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_TTLID))
510 fprintf(file, "\t%lu", (u_long)tmpttl);
511 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_CLASS))
512 fprintf(file, "\t%s", __p_class(class));
513 fprintf(file, "\t%s", __p_type(type));
514 /*
515 * Print type specific data, if appropriate
516 */
517 switch (type) {
518 case T_A:
519 switch (class) {
520 case C_IN:
521 case C_HS:
522 bcopy(cp, (char *)&inaddr, INADDRSZ);
523 if (dlen == 4) {
524 fprintf(file, "\t%s", inet_ntoa(inaddr));
525 cp += dlen;
526 } else if (dlen == 7) {
527 char *address;
528 u_char protocol;
529 in_port_t port;
530
531 address = inet_ntoa(inaddr);
532 cp += INADDRSZ;
533 protocol = *(u_char*)cp;
534 cp += sizeof (u_char);
535 port = _getshort((u_char*)cp);
536 cp += INT16SZ;
537 fprintf(file, "\t%s\t; proto %u, port %u",
538 address, protocol, port);
539 }
540 break;
541 default:
542 cp += dlen;
543 }
544 break;
545 case T_CNAME:
546 case T_MB:
547 case T_MG:
548 case T_MR:
549 case T_NS:
550 case T_PTR:
551 putc('\t', file);
552 if ((cp = p_fqname(cp, msg, file)) == NULL)
553 return (NULL);
554 break;
555
556 case T_HINFO:
557 case T_ISDN:
558 cp2 = cp + dlen;
559 (void) fputs("\t\"", file);
560 if ((n = (unsigned char) *cp++) != 0) {
561 for (c = n; c > 0 && cp < cp2; c--) {
562 if (strchr("\n\"\\", *cp))
563 (void) putc('\\', file);
564 (void) putc(*cp++, file);
565 }
566 }
567 putc('"', file);
568 if (cp < cp2 && (n = (unsigned char) *cp++) != 0) {
569 (void) fputs ("\t\"", file);
570 for (c = n; c > 0 && cp < cp2; c--) {
571 if (strchr("\n\"\\", *cp))
572 (void) putc('\\', file);
573 (void) putc(*cp++, file);
574 }
575 putc('"', file);
576 } else if (type == T_HINFO) {
577 (void) fputs("\"?\"", file);
578 fprintf(file, "\n;; *** Warning *** OS-type missing");
579 }
580 break;
581
582 case T_SOA:
583 putc('\t', file);
584 if ((cp = p_fqname(cp, msg, file)) == NULL)
585 return (NULL);
586 putc(' ', file);
587 if ((cp = p_fqname(cp, msg, file)) == NULL)
588 return (NULL);
589 fputs(" (\n", file);
590 t = _getlong((u_char*)cp); cp += INT32SZ;
591 fprintf(file, "\t\t\t%lu\t; serial\n", (u_long)t);
592 t = _getlong((u_char*)cp); cp += INT32SZ;
593 fprintf(file, "\t\t\t%lu\t; refresh (%s)\n",
594 (u_long)t, __p_time(t));
595 t = _getlong((u_char*)cp); cp += INT32SZ;
596 fprintf(file, "\t\t\t%lu\t; retry (%s)\n",
597 (u_long)t, __p_time(t));
598 t = _getlong((u_char*)cp); cp += INT32SZ;
599 fprintf(file, "\t\t\t%lu\t; expire (%s)\n",
600 (u_long)t, __p_time(t));
601 t = _getlong((u_char*)cp); cp += INT32SZ;
602 fprintf(file, "\t\t\t%lu )\t; minimum (%s)",
603 (u_long)t, __p_time(t));
604 break;
605
606 case T_MX:
607 case T_AFSDB:
608 case T_RT:
609 fprintf(file, "\t%u ", _getshort((u_char*)cp));
610 cp += INT16SZ;
611 if ((cp = p_fqname(cp, msg, file)) == NULL)
612 return (NULL);
613 break;
614
615 case T_PX:
616 fprintf(file, "\t%u ", _getshort((u_char*)cp));
617 cp += INT16SZ;
618 if ((cp = p_fqname(cp, msg, file)) == NULL)
619 return (NULL);
620 putc(' ', file);
621 if ((cp = p_fqname(cp, msg, file)) == NULL)
622 return (NULL);
623 break;
624
625 case T_X25:
626 cp2 = cp + dlen;
627 (void) fputs("\t\"", file);
628 if ((n = (unsigned char) *cp++) != 0) {
629 for (c = n; c > 0 && cp < cp2; c--) {
630 if (strchr("\n\"\\", *cp))
631 (void) putc('\\', file);
632 (void) putc(*cp++, file);
633 }
634 }
635 putc('"', file);
636 break;
637
638 case T_TXT:
639 (void) putc('\t', file);
640 cp2 = cp1 + dlen;
641 while (cp < cp2) {
642 putc('"', file);
643 if ((n = (unsigned char) *cp++)) {
644 for (c = n; c > 0 && cp < cp2; c--) {
645 if (strchr("\n\"\\", *cp))
646 (void) putc('\\', file);
647 (void) putc(*cp++, file);
648 }
649 }
650 putc('"', file);
651 if (cp < cp2)
652 putc(' ', file);
653 }
654 break;
655
656 case T_NSAP:
657 (void) fprintf(file, "\t%s", inet_nsap_ntoa(dlen, cp, NULL));
658 cp += dlen;
659 break;
660
661 case T_AAAA: {
662 char t[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"];
663
664 fprintf(file, "\t%s", inet_ntop(AF_INET6, cp, t, sizeof t));
665 cp += dlen;
666 break;
667 }
668
669 case T_LOC: {
670 char t[255];
671
672 fprintf(file, "\t%s", loc_ntoal(cp, t, sizeof t));
673 cp += dlen;
674 break;
675 }
676
677 case T_NAPTR: {
678 u_int order, preference;
679
680 order = _getshort(cp); cp += INT16SZ;
681 preference = _getshort(cp); cp += INT16SZ;
682 fprintf(file, "\t%u %u ",order, preference);
683 /* Flags */
684 n = *cp++;
685 fprintf(file,"\"%.*s\" ", (int)n, cp);
686 cp += n;
687 /* Service */
688 n = *cp++;
689 fprintf(file,"\"%.*s\" ", (int)n, cp);
690 cp += n;
691 /* Regexp */
692 n = *cp++;
693 fprintf(file,"\"%.*s\" ", (int)n, cp);
694 cp += n;
695 if ((cp = p_fqname(cp, msg, file)) == NULL)
696 return (NULL);
697 break;
698 }
699
700 case T_SRV: {
701 u_int priority, weight, port;
702
703 priority = _getshort(cp); cp += INT16SZ;
704 weight = _getshort(cp); cp += INT16SZ;
705 port = _getshort(cp); cp += INT16SZ;
706 fprintf(file, "\t%u %u %u ", priority, weight, port);
707 if ((cp = p_fqname(cp, msg, file)) == NULL)
708 return (NULL);
709 break;
710 }
711
712 case T_MINFO:
713 case T_RP:
714 putc('\t', file);
715 if ((cp = p_fqname(cp, msg, file)) == NULL)
716 return (NULL);
717 putc(' ', file);
718 if ((cp = p_fqname(cp, msg, file)) == NULL)
719 return (NULL);
720 break;
721
722 case T_UINFO:
723 putc('\t', file);
724 fputs((char *)cp, file);
725 cp += dlen;
726 break;
727
728 case T_UID:
729 case T_GID:
730 if (dlen == 4) {
731 fprintf(file, "\t%u", _getlong((u_char*)cp));
732 cp += INT32SZ;
733 }
734 break;
735
736 case T_WKS:
737 if (dlen < INT32SZ + 1)
738 break;
739 bcopy(cp, (char *)&inaddr, INADDRSZ);
740 cp += INT32SZ;
741 fprintf(file, "\t%s %s ( ",
742 inet_ntoa(inaddr),
743 deproto((int) *cp));
744 cp += sizeof (u_char);
745 n = 0;
746 lcnt = 0;
747 while (cp < cp1 + dlen) {
748 c = *cp++;
749 do {
750 if (c & 0200) {
751 if (lcnt == 0) {
752 fputs("\n\t\t\t", file);
753 lcnt = 5;
754 }
755 fputs(dewks(n), file);
756 putc(' ', file);
757 lcnt--;
758 }
759 c <<= 1;
760 } while (++n & 07);
761 }
762 putc(')', file);
763 break;
764
765 case T_KEY:
766 putc('\t', file);
767 keyflags = _getshort(cp);
768 cp += 2;
769 fprintf(file,"0x%04x", keyflags ); /* flags */
770 fprintf(file," %u", *cp++); /* protocol */
771 fprintf(file," %u (", *cp++); /* algorithm */
772
773 n = b64_ntop(cp, (cp1 + dlen) - cp,
774 base64_key, sizeof base64_key);
775 for (c = 0; c < n; ++c) {
776 if (0 == (c & 0x3F))
777 fprintf(file, "\n\t");
778 putc(base64_key[c], file); /* public key data */
779 }
780
781 fprintf(file, " )");
782 if (n < 0)
783 fprintf(file, "\t; BAD BASE64");
784 fflush(file);
785 cp = cp1 + dlen;
786 break;
787
788 case T_SIG:
789 type = _getshort((u_char*)cp);
790 cp += INT16SZ;
791 fprintf(file, " %s", p_type(type));
792 fprintf(file, "\t%u", *cp++); /* algorithm */
793 /* Check label value and print error if wrong. */
794 n = *cp++;
795 c = dn_count_labels (rrname);
796 if (n != c)
797 fprintf(file, "\t; LABELS WRONG (%d should be %d)\n\t",
798 n, c);
799 /* orig ttl */
800 n = _getlong((u_char*)cp);
801 if (n != tmpttl)
802 fprintf(file, " %u", n);
803 cp += INT32SZ;
804 /* sig expire */
805 fprintf(file, " (\n\t%s",
806 __p_secstodate(_getlong((u_char*)cp)));
807 cp += INT32SZ;
808 /* time signed */
809 fprintf(file, " %s", __p_secstodate(_getlong((u_char*)cp)));
810 cp += INT32SZ;
811 /* sig footprint */
812 fprintf(file," %u ", _getshort((u_char*)cp));
813 cp += INT16SZ;
814 /* signer's name */
815 cp = p_fqname(cp, msg, file);
816 n = b64_ntop(cp, (cp1 + dlen) - cp,
817 base64_key, sizeof base64_key);
818 for (c = 0; c < n; c++) {
819 if (0 == (c & 0x3F))
820 fprintf (file, "\n\t");
821 putc(base64_key[c], file); /* signature */
822 }
823 /* Clean up... */
824 fprintf(file, " )");
825 if (n < 0)
826 fprintf(file, "\t; BAD BASE64");
827 fflush(file);
828 cp = cp1+dlen;
829 break;
830
831#ifdef ALLOW_T_UNSPEC
832 case T_UNSPEC:
833 {
834 int NumBytes = 8;
835 u_char *DataPtr;
836 int i;
837
838 if (dlen < NumBytes) NumBytes = dlen;
839 fprintf(file, "\tFirst %d bytes of hex data:",
840 NumBytes);
841 for (i = 0, DataPtr = cp; i < NumBytes; i++, DataPtr++)
842 fprintf(file, " %x", *DataPtr);
843 cp += dlen;
844 }
845 break;
846#endif /* ALLOW_T_UNSPEC */
847
848 default:
849 fprintf(file, "\t?%d?", type);
850 cp += dlen;
851 }
852#if 0
853 fprintf(file, "\t; dlen=%d, ttl %s\n", dlen, __p_time(tmpttl));
854#else
855 putc('\n', file);
856#endif
857 if (cp - cp1 != dlen) {
858 fprintf(file, ";; packet size error (found %ld, dlen was %d)\n",
859 (long)(cp - cp1), dlen);
860 cp = NULL;
861 }
862 return (cp);
863}
864
865/*
866 * Names of RR classes and qclasses. Classes and qclasses are the same, except
867 * that C_ANY is a qclass but not a class. (You can ask for records of class
868 * C_ANY, but you can't have any records of that class in the database.)
869 */
870const struct res_sym __p_class_syms[] = {
871 {C_IN, "IN"},
872 {C_CHAOS, "CHAOS"},
873 {C_HS, "HS"},
874 {C_HS, "HESIOD"},
875 {C_ANY, "ANY"},
876 {C_IN, (char *)0}
877};
878
879/*
880 * Names of RR types and qtypes. Types and qtypes are the same, except
881 * that T_ANY is a qtype but not a type. (You can ask for records of type
882 * T_ANY, but you can't have any records of that type in the database.)
883 */
884const struct res_sym __p_type_syms[] = {
885 {T_A, "A", "address"},
886 {T_NS, "NS", "name server"},
887 {T_MD, "MD", "mail destination (deprecated)"},
888 {T_MF, "MF", "mail forwarder (deprecated)"},
889 {T_CNAME, "CNAME", "canonical name"},
890 {T_SOA, "SOA", "start of authority"},
891 {T_MB, "MB", "mailbox"},
892 {T_MG, "MG", "mail group member"},
893 {T_MR, "MR", "mail rename"},
894 {T_NULL, "NULL", "null"},
895 {T_WKS, "WKS", "well-known service (deprecated)"},
896 {T_PTR, "PTR", "domain name pointer"},
897 {T_HINFO, "HINFO", "host information"},
898 {T_MINFO, "MINFO", "mailbox information"},
899 {T_MX, "MX", "mail exchanger"},
900 {T_TXT, "TXT", "text"},
901 {T_RP, "RP", "responsible person"},
902 {T_AFSDB, "AFSDB", "DCE or AFS server"},
903 {T_X25, "X25", "X25 address"},
904 {T_ISDN, "ISDN", "ISDN address"},
905 {T_RT, "RT", "router"},
906 {T_NSAP, "NSAP", "nsap address"},
907 {T_NSAP_PTR, "NSAP_PTR", "domain name pointer"},
908 {T_SIG, "SIG", "signature"},
909 {T_KEY, "KEY", "key"},
910 {T_PX, "PX", "mapping information"},
911 {T_GPOS, "GPOS", "geographical position (withdrawn)"},
912 {T_AAAA, "AAAA", "IPv6 address"},
913 {T_LOC, "LOC", "location"},
914 {T_NXT, "NXT", "next valid name (unimplemented)"},
915 {T_EID, "EID", "endpoint identifier (unimplemented)"},
916 {T_NIMLOC, "NIMLOC", "NIMROD locator (unimplemented)"},
917 {T_SRV, "SRV", "server selection"},
918 {T_ATMA, "ATMA", "ATM address (unimplemented)"},
919 {T_IXFR, "IXFR", "incremental zone transfer"},
920 {T_AXFR, "AXFR", "zone transfer"},
921 {T_MAILB, "MAILB", "mailbox-related data (deprecated)"},
922 {T_MAILA, "MAILA", "mail agent (deprecated)"},
923 {T_UINFO, "UINFO", "user information (nonstandard)"},
924 {T_UID, "UID", "user ID (nonstandard)"},
925 {T_GID, "GID", "group ID (nonstandard)"},
926 {T_NAPTR, "NAPTR", "URN Naming Authority"},
927#ifdef ALLOW_T_UNSPEC
928 {T_UNSPEC, "UNSPEC", "unspecified data (nonstandard)"},
929#endif /* ALLOW_T_UNSPEC */
930 {T_ANY, "ANY", "\"any\""},
931 {0, NULL, NULL}
932};
933
934int
935__sym_ston(syms, name, success)
936 const struct res_sym *syms;
937 char *name;
938 int *success;
939{
940 for (; syms->name != 0; syms++) {
941 if (strcasecmp (name, syms->name) == 0) {
942 if (success)
943 *success = 1;
944 return (syms->number);
945 }
946 }
947 if (success)
948 *success = 0;
949 return (syms->number); /* The default value. */
950}
951
952const char *
953__sym_ntos(syms, number, success)
954 const struct res_sym *syms;
955 int number;
956 int *success;
957{
958 static char unname[20];
959
960 for (; syms->name != 0; syms++) {
961 if (number == syms->number) {
962 if (success)
963 *success = 1;
964 return (syms->name);
965 }
966 }
967
968 snprintf(unname, sizeof unname, "%d", number);
969 if (success)
970 *success = 0;
971 return (unname);
972}
973
974
975const char *
976__sym_ntop(syms, number, success)
977 const struct res_sym *syms;
978 int number;
979 int *success;
980{
981 static char unname[20];
982
983 for (; syms->name != 0; syms++) {
984 if (number == syms->number) {
985 if (success)
986 *success = 1;
987 return (syms->humanname);
988 }
989 }
990 snprintf(unname, sizeof unname, "%d", number);
991 if (success)
992 *success = 0;
993 return (unname);
994}
995
996/*
997 * Return a string for the type
998 */
999const char *
1000__p_type(type)
1001 int type;
1002{
1003 return (__sym_ntos (__p_type_syms, type, (int *)0));
1004}
1005
1006/*
1007 * Return a mnemonic for class
1008 */
1009const char *
1010__p_class(class)
1011 int class;
1012{
1013 return (__sym_ntos (__p_class_syms, class, (int *)0));
1014}
1015
1016/*
1017 * Return a mnemonic for an option
1018 */
1019const char *
1020__p_option(option)
1021 u_long option;
1022{
1023 static char nbuf[40];
1024
1025 switch (option) {
1026 case RES_INIT: return "init";
1027 case RES_DEBUG: return "debug";
1028 case RES_AAONLY: return "aaonly(unimpl)";
1029 case RES_USEVC: return "usevc";
1030 case RES_PRIMARY: return "primry(unimpl)";
1031 case RES_IGNTC: return "igntc";
1032 case RES_RECURSE: return "recurs";
1033 case RES_DEFNAMES: return "defnam";
1034 case RES_STAYOPEN: return "styopn";
1035 case RES_DNSRCH: return "dnsrch";
1036 case RES_INSECURE1: return "insecure1";
1037 case RES_INSECURE2: return "insecure2";
1038 case RES_USE_INET6: return "inet6";
1039 case RES_USE_EDNS0: return "edns0";
1040 default:
1041 snprintf(nbuf, sizeof nbuf, "?0x%lx?", (u_long)option);
1042 return (nbuf);
1043 }
1044}
1045
1046/*
1047 * Return a mnemonic for a time to live
1048 */
1049const char *
1050p_time(value)
1051 u_int32_t value;
1052{
1053 static char nbuf[40];
1054 char *ebuf;
1055 int secs, mins, hours, days;
1056 register char *p;
1057 int tmp;
1058
1059 if (value == 0) {
1060 strlcpy(nbuf, "0 secs", sizeof nbuf);
1061 return (nbuf);
1062 }
1063
1064 secs = value % 60;
1065 value /= 60;
1066 mins = value % 60;
1067 value /= 60;
1068 hours = value % 24;
1069 value /= 24;
1070 days = value;
1071 value = 0;
1072
1073#define PLURALIZE(x) x, (x == 1) ? "" : "s"
1074 p = nbuf;
1075 ebuf = nbuf + sizeof(nbuf);
1076 if (days) {
1077 if ((tmp = snprintf(p, ebuf - p, "%d day%s",
1078 PLURALIZE(days))) >= ebuf - nbuf || tmp < 0)
1079 goto full;
1080 p += tmp;
1081 }
1082 if (hours) {
1083 if (days)
1084 *p++ = ' ';
1085 if (p >= ebuf)
1086 goto full;
1087 if ((tmp = snprintf(p, ebuf - p, "%d hour%s",
1088 PLURALIZE(hours))) >= ebuf - nbuf || tmp < 0)
1089 goto full;
1090 p += tmp;
1091 }
1092 if (mins) {
1093 if (days || hours)
1094 *p++ = ' ';
1095 if (p >= ebuf)
1096 goto full;
1097 if ((tmp = snprintf(p, ebuf - p, "%d min%s",
1098 PLURALIZE(mins))) >= ebuf - nbuf || tmp < 0)
1099 goto full;
1100 p += tmp;
1101 }
1102 if (secs || ! (days || hours || mins)) {
1103 if (days || hours || mins)
1104 *p++ = ' ';
1105 if (p >= ebuf)
1106 goto full;
1107 if ((tmp = snprintf(p, ebuf - p, "%d sec%s",
1108 PLURALIZE(secs))) >= ebuf - nbuf || tmp < 0)
1109 goto full;
1110 }
1111 return (nbuf);
1112full:
1113 p = nbuf + sizeof(nbuf) - 4;
1114 *p++ = '.';
1115 *p++ = '.';
1116 *p++ = '.';
1117 *p++ = '\0';
1118 return (nbuf);
1119}
1120
1121/*
1122 * routines to convert between on-the-wire RR format and zone file format.
1123 * Does not contain conversion to/from decimal degrees; divide or multiply
1124 * by 60*60*1000 for that.
1125 */
1126
1127static unsigned int poweroften[10] = {1, 10, 100, 1000, 10000, 100000,
1128 1000000,10000000,100000000,1000000000};
1129
1130/* takes an XeY precision/size value, returns a string representation. */
1131static const char *
1132precsize_ntoa(prec)
1133 u_int8_t prec;
1134{
1135 static char retbuf[sizeof "90000000.00"];
1136 unsigned long val;
1137 int mantissa, exponent;
1138
1139 mantissa = (int)((prec >> 4) & 0x0f) % 10;
1140 exponent = (int)((prec >> 0) & 0x0f) % 10;
1141
1142 val = mantissa * poweroften[exponent];
1143
1144 (void) snprintf(retbuf, sizeof retbuf, "%ld.%.2ld", val/100, val%100);
1145 return (retbuf);
1146}
1147
1148/* converts ascii size/precision X * 10**Y(cm) to 0xXY. moves pointer. */
1149static u_int8_t
1150precsize_aton(strptr)
1151 char **strptr;
1152{
1153 unsigned int mval = 0, cmval = 0;
1154 u_int8_t retval = 0;
1155 register char *cp;
1156 register int exponent;
1157 register int mantissa;
1158
1159 cp = *strptr;
1160
1161 while (isdigit(*cp))
1162 mval = mval * 10 + (*cp++ - '0');
1163
1164 if (*cp == '.') { /* centimeters */
1165 cp++;
1166 if (isdigit(*cp)) {
1167 cmval = (*cp++ - '0') * 10;
1168 if (isdigit(*cp)) {
1169 cmval += (*cp++ - '0');
1170 }
1171 }
1172 }
1173 cmval = (mval * 100) + cmval;
1174
1175 for (exponent = 0; exponent < 9; exponent++)
1176 if (cmval < poweroften[exponent+1])
1177 break;
1178
1179 mantissa = cmval / poweroften[exponent];
1180 if (mantissa > 9)
1181 mantissa = 9;
1182
1183 retval = (mantissa << 4) | exponent;
1184
1185 *strptr = cp;
1186
1187 return (retval);
1188}
1189
1190/* converts ascii lat/lon to unsigned encoded 32-bit number. moves pointer. */
1191static u_int32_t
1192latlon2ul(latlonstrptr,which)
1193 char **latlonstrptr;
1194 int *which;
1195{
1196 register char *cp;
1197 u_int32_t retval;
1198 int deg = 0, min = 0, secs = 0, secsfrac = 0;
1199
1200 cp = *latlonstrptr;
1201
1202 while (isdigit(*cp))
1203 deg = deg * 10 + (*cp++ - '0');
1204
1205 while (isspace(*cp))
1206 cp++;
1207
1208 if (!(isdigit(*cp)))
1209 goto fndhemi;
1210
1211 while (isdigit(*cp))
1212 min = min * 10 + (*cp++ - '0');
1213
1214 while (isspace(*cp))
1215 cp++;
1216
1217 if (!(isdigit(*cp)))
1218 goto fndhemi;
1219
1220 while (isdigit(*cp))
1221 secs = secs * 10 + (*cp++ - '0');
1222
1223 if (*cp == '.') { /* decimal seconds */
1224 cp++;
1225 if (isdigit(*cp)) {
1226 secsfrac = (*cp++ - '0') * 100;
1227 if (isdigit(*cp)) {
1228 secsfrac += (*cp++ - '0') * 10;
1229 if (isdigit(*cp)) {
1230 secsfrac += (*cp++ - '0');
1231 }
1232 }
1233 }
1234 }
1235
1236 while (!isspace(*cp)) /* if any trailing garbage */
1237 cp++;
1238
1239 while (isspace(*cp))
1240 cp++;
1241
1242 fndhemi:
1243 switch (*cp) {
1244 case 'N': case 'n':
1245 case 'E': case 'e':
1246 retval = ((unsigned)1<<31)
1247 + (((((deg * 60) + min) * 60) + secs) * 1000)
1248 + secsfrac;
1249 break;
1250 case 'S': case 's':
1251 case 'W': case 'w':
1252 retval = ((unsigned)1<<31)
1253 - (((((deg * 60) + min) * 60) + secs) * 1000)
1254 - secsfrac;
1255 break;
1256 default:
1257 retval = 0; /* invalid value -- indicates error */
1258 break;
1259 }
1260
1261 switch (*cp) {
1262 case 'N': case 'n':
1263 case 'S': case 's':
1264 *which = 1; /* latitude */
1265 break;
1266 case 'E': case 'e':
1267 case 'W': case 'w':
1268 *which = 2; /* longitude */
1269 break;
1270 default:
1271 *which = 0; /* error */
1272 break;
1273 }
1274
1275 cp++; /* skip the hemisphere */
1276
1277 while (!isspace(*cp)) /* if any trailing garbage */
1278 cp++;
1279
1280 while (isspace(*cp)) /* move to next field */
1281 cp++;
1282
1283 *latlonstrptr = cp;
1284
1285 return (retval);
1286}
1287
1288/* converts a zone file representation in a string to an RDATA on-the-wire
1289 * representation. */
1290int
1291loc_aton(ascii, binary)
1292 const char *ascii;
1293 u_char *binary;
1294{
1295 const char *maxcp;
1296 u_char *bcp;
1297 char *cp;
1298
1299 u_int32_t latit = 0, longit = 0, alt = 0;
1300 u_int32_t lltemp1 = 0, lltemp2 = 0;
1301 int altmeters = 0, altfrac = 0, altsign = 1;
1302 u_int8_t hp = 0x16; /* default = 1e6 cm = 10000.00m = 10km */
1303 u_int8_t vp = 0x13; /* default = 1e3 cm = 10.00m */
1304 u_int8_t siz = 0x12; /* default = 1e2 cm = 1.00m */
1305 int which1 = 0, which2 = 0;
1306
1307 cp = (char *)ascii;
1308 maxcp = cp + strlen(ascii);
1309
1310 lltemp1 = latlon2ul(&cp, &which1);
1311
1312 lltemp2 = latlon2ul(&cp, &which2);
1313
1314 switch (which1 + which2) {
1315 case 3: /* 1 + 2, the only valid combination */
1316 if ((which1 == 1) && (which2 == 2)) { /* normal case */
1317 latit = lltemp1;
1318 longit = lltemp2;
1319 } else if ((which1 == 2) && (which2 == 1)) { /* reversed */
1320 longit = lltemp1;
1321 latit = lltemp2;
1322 } else { /* some kind of brokenness */
1323 return (0);
1324 }
1325 break;
1326 default: /* we didn't get one of each */
1327 return (0);
1328 }
1329
1330 /* altitude */
1331 if (*cp == '-') {
1332 altsign = -1;
1333 cp++;
1334 }
1335
1336 if (*cp == '+')
1337 cp++;
1338
1339 while (isdigit(*cp))
1340 altmeters = altmeters * 10 + (*cp++ - '0');
1341
1342 if (*cp == '.') { /* decimal meters */
1343 cp++;
1344 if (isdigit(*cp)) {
1345 altfrac = (*cp++ - '0') * 10;
1346 if (isdigit(*cp)) {
1347 altfrac += (*cp++ - '0');
1348 }
1349 }
1350 }
1351
1352 alt = (10000000 + (altsign * (altmeters * 100 + altfrac)));
1353
1354 while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
1355 cp++;
1356
1357 while (isspace(*cp) && (cp < maxcp))
1358 cp++;
1359
1360 if (cp >= maxcp)
1361 goto defaults;
1362
1363 siz = precsize_aton(&cp);
1364
1365 while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
1366 cp++;
1367
1368 while (isspace(*cp) && (cp < maxcp))
1369 cp++;
1370
1371 if (cp >= maxcp)
1372 goto defaults;
1373
1374 hp = precsize_aton(&cp);
1375
1376 while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
1377 cp++;
1378
1379 while (isspace(*cp) && (cp < maxcp))
1380 cp++;
1381
1382 if (cp >= maxcp)
1383 goto defaults;
1384
1385 vp = precsize_aton(&cp);
1386
1387 defaults:
1388
1389 bcp = binary;
1390 *bcp++ = (u_int8_t) 0; /* version byte */
1391 *bcp++ = siz;
1392 *bcp++ = hp;
1393 *bcp++ = vp;
1394 PUTLONG(latit,bcp);
1395 PUTLONG(longit,bcp);
1396 PUTLONG(alt,bcp);
1397
1398 return (16); /* size of RR in octets */
1399}
1400
1401const char *
1402loc_ntoa(binary, ascii)
1403 const u_char *binary;
1404 char *ascii;
1405{
1406 return loc_ntoal(binary, ascii, 255);
1407}
1408
1409/* takes an on-the-wire LOC RR and formats it in a human readable format. */
1410static const char *
1411loc_ntoal(binary, ascii, ascii_len)
1412 const u_char *binary;
1413 char *ascii;
1414 int ascii_len;
1415{
1416 static char *error = "?";
1417 register const u_char *cp = binary;
1418
1419 int latdeg, latmin, latsec, latsecfrac;
1420 int longdeg, longmin, longsec, longsecfrac;
1421 char northsouth, eastwest;
1422 int altmeters, altfrac, altsign;
1423
1424 const int referencealt = 100000 * 100;
1425
1426 int32_t latval, longval, altval;
1427 u_int32_t templ;
1428 u_int8_t sizeval, hpval, vpval, versionval;
1429
1430 char *sizestr, *hpstr, *vpstr;
1431
1432 versionval = *cp++;
1433
1434 if (versionval) {
1435 snprintf(ascii, ascii_len, "; error: unknown LOC RR version");
1436 return (ascii);
1437 }
1438
1439 sizeval = *cp++;
1440
1441 hpval = *cp++;
1442 vpval = *cp++;
1443
1444 GETLONG(templ, cp);
1445 latval = (templ - ((unsigned)1<<31));
1446
1447 GETLONG(templ, cp);
1448 longval = (templ - ((unsigned)1<<31));
1449
1450 GETLONG(templ, cp);
1451 if (templ < referencealt) { /* below WGS 84 spheroid */
1452 altval = referencealt - templ;
1453 altsign = -1;
1454 } else {
1455 altval = templ - referencealt;
1456 altsign = 1;
1457 }
1458
1459 if (latval < 0) {
1460 northsouth = 'S';
1461 latval = -latval;
1462 } else
1463 northsouth = 'N';
1464
1465 latsecfrac = latval % 1000;
1466 latval = latval / 1000;
1467 latsec = latval % 60;
1468 latval = latval / 60;
1469 latmin = latval % 60;
1470 latval = latval / 60;
1471 latdeg = latval;
1472
1473 if (longval < 0) {
1474 eastwest = 'W';
1475 longval = -longval;
1476 } else
1477 eastwest = 'E';
1478
1479 longsecfrac = longval % 1000;
1480 longval = longval / 1000;
1481 longsec = longval % 60;
1482 longval = longval / 60;
1483 longmin = longval % 60;
1484 longval = longval / 60;
1485 longdeg = longval;
1486
1487 altfrac = altval % 100;
1488 altmeters = (altval / 100) * altsign;
1489
1490 if ((sizestr = strdup(precsize_ntoa(sizeval))) == NULL)
1491 sizestr = error;
1492 if ((hpstr = strdup(precsize_ntoa(hpval))) == NULL)
1493 hpstr = error;
1494 if ((vpstr = strdup(precsize_ntoa(vpval))) == NULL)
1495 vpstr = error;
1496
1497 snprintf(ascii, ascii_len,
1498 "%d %.2d %.2d.%.3d %c %d %.2d %.2d.%.3d %c %d.%.2dm %sm %sm %sm",
1499 latdeg, latmin, latsec, latsecfrac, northsouth,
1500 longdeg, longmin, longsec, longsecfrac, eastwest,
1501 altmeters, altfrac, sizestr, hpstr, vpstr);
1502
1503 if (sizestr != error)
1504 free(sizestr);
1505 if (hpstr != error)
1506 free(hpstr);
1507 if (vpstr != error)
1508 free(vpstr);
1509
1510 return (ascii);
1511}
1512
1513
1514/* Return the number of DNS hierarchy levels in the name. */
1515int
1516__dn_count_labels(name)
1517 char *name;
1518{
1519 int i, len, count;
1520
1521 len = strlen(name);
1522
1523 for(i = 0, count = 0; i < len; i++) {
1524 if (name[i] == '.')
1525 count++;
1526 }
1527
1528 /* don't count initial wildcard */
1529 if (name[0] == '*')
1530 if (count)
1531 count--;
1532
1533 /* don't count the null label for root. */
1534 /* if terminating '.' not found, must adjust */
1535 /* count to include last label */
1536 if (len > 0 && name[len-1] != '.')
1537 count++;
1538 return (count);
1539}
1540
1541
1542/*
1543 * Make dates expressed in seconds-since-Jan-1-1970 easy to read.
1544 * SIG records are required to be printed like this, by the Secure DNS RFC.
1545 */
1546char *
1547__p_secstodate (secs)
1548 unsigned long secs;
1549{
1550 static char output[15]; /* YYYYMMDDHHMMSS and null */
1551 time_t clock = secs;
1552 struct tm *time;
1553
1554 time = gmtime(&clock);
1555 time->tm_year += 1900;
1556 time->tm_mon += 1;
1557 snprintf(output, sizeof output, "%04d%02d%02d%02d%02d%02d",
1558 time->tm_year, time->tm_mon, time->tm_mday,
1559 time->tm_hour, time->tm_min, time->tm_sec);
1560 return (output);
1561}
diff --git a/src/lib/libc/net/res_init.c b/src/lib/libc/net/res_init.c
new file mode 100644
index 0000000000..9c73958883
--- /dev/null
+++ b/src/lib/libc/net/res_init.c
@@ -0,0 +1,650 @@
1/* $OpenBSD: res_init.c,v 1.29 2003/06/02 20:18:36 millert 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. 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#ifndef INET6
55#define INET6
56#endif
57
58#if defined(LIBC_SCCS) && !defined(lint)
59#if 0
60static char sccsid[] = "@(#)res_init.c 8.1 (Berkeley) 6/7/93";
61static char rcsid[] = "$From: res_init.c,v 8.7 1996/09/28 06:51:07 vixie Exp $";
62#else
63static char rcsid[] = "$OpenBSD: res_init.c,v 1.29 2003/06/02 20:18: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 <sys/socket.h>
70#include <sys/time.h>
71#include <netinet/in.h>
72#include <arpa/inet.h>
73#include <arpa/nameser.h>
74
75#include <stdio.h>
76#include <ctype.h>
77#include <resolv.h>
78#include <unistd.h>
79#include <stdlib.h>
80#include <string.h>
81#ifdef INET6
82#include <netdb.h>
83#endif /* INET6 */
84
85#include "thread_private.h"
86
87/*-------------------------------------- info about "sortlist" --------------
88 * Marc Majka 1994/04/16
89 * Allan Nathanson 1994/10/29 (BIND 4.9.3.x)
90 *
91 * NetInfo resolver configuration directory support.
92 *
93 * Allow a NetInfo directory to be created in the hierarchy which
94 * contains the same information as the resolver configuration file.
95 *
96 * - The local domain name is stored as the value of the "domain" property.
97 * - The Internet address(es) of the name server(s) are stored as values
98 * of the "nameserver" property.
99 * - The name server addresses are stored as values of the "nameserver"
100 * property.
101 * - The search list for host-name lookup is stored as values of the
102 * "search" property.
103 * - The sortlist comprised of IP address netmask pairs are stored as
104 * values of the "sortlist" property. The IP address and optional netmask
105 * should be separated by a slash (/) or ampersand (&) character.
106 * - Internal resolver variables can be set from the value of the "options"
107 * property.
108 */
109
110static void res_setoptions(char *, char *);
111
112#ifdef RESOLVSORT
113static const char sort_mask[] = "/&";
114#define ISSORTMASK(ch) (strchr(sort_mask, ch) != NULL)
115static u_int32_t net_mask(struct in_addr);
116#endif
117
118/*
119 * Resolver state default settings.
120 */
121volatile struct _thread_private_key_struct __THREAD_KEY_NAME(_res) = {
122 PTHREAD_ONCE_INIT, 0
123};
124
125struct __res_state _res
126# if defined(__BIND_RES_TEXT)
127 = { RES_TIMEOUT, } /* Motorola, et al. */
128# endif
129 ;
130#ifdef INET6
131volatile struct _thread_private_key_struct __THREAD_KEY_NAME(_res_ext) = {
132 PTHREAD_ONCE_INIT, 0
133};
134
135struct __res_state_ext _res_ext;
136#endif /* INET6 */
137
138/*
139 * Set up default settings. If the configuration file exist, the values
140 * there will have precedence. Otherwise, the server address is set to
141 * INADDR_ANY and the default domain name comes from the gethostname().
142 *
143 * An interrim version of this code (BIND 4.9, pre-4.4BSD) used 127.0.0.1
144 * rather than INADDR_ANY ("0.0.0.0") as the default name server address
145 * since it was noted that INADDR_ANY actually meant ``the first interface
146 * you "ifconfig"'d at boot time'' and if this was a SLIP or PPP interface,
147 * it had to be "up" in order for you to reach your own name server. It
148 * was later decided that since the recommended practice is to always
149 * install local static routes through 127.0.0.1 for all your network
150 * interfaces, that we could solve this problem without a code change.
151 *
152 * The configuration file should always be used, since it is the only way
153 * to specify a default domain. If you are running a server on your local
154 * machine, you should say "nameserver 0.0.0.0" or "nameserver 127.0.0.1"
155 * in the configuration file.
156 *
157 * Return 0 if completes successfully, -1 on error
158 */
159int
160res_init()
161{
162 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
163#ifdef INET6
164 struct __res_state_ext *_res_extp = _THREAD_PRIVATE(_res_ext, _res_ext,
165 &_res_ext);
166#endif
167 register FILE *fp;
168 register char *cp, **pp;
169 register int n;
170 char buf[BUFSIZ];
171 int nserv = 0; /* number of nameserver records read from file */
172 int haveenv = 0;
173 int havesearch = 0;
174 size_t len;
175#ifdef RESOLVSORT
176 int nsort = 0;
177 char *net;
178#endif
179#ifndef RFC1535
180 int dots;
181#endif
182
183 /*
184 * These three fields used to be statically initialized. This made
185 * it hard to use this code in a shared library. It is necessary,
186 * now that we're doing dynamic initialization here, that we preserve
187 * the old semantics: if an application modifies one of these three
188 * fields of _res before res_init() is called, res_init() will not
189 * alter them. Of course, if an application is setting them to
190 * _zero_ before calling res_init(), hoping to override what used
191 * to be the static default, we can't detect it and unexpected results
192 * will follow. Zero for any of these fields would make no sense,
193 * so one can safely assume that the applications were already getting
194 * unexpected results.
195 *
196 * _res.options is tricky since some apps were known to diddle the bits
197 * before res_init() was first called. We can't replicate that semantic
198 * with dynamic initialization (they may have turned bits off that are
199 * set in RES_DEFAULT). Our solution is to declare such applications
200 * "broken". They could fool us by setting RES_INIT but none do (yet).
201 */
202 if (!_resp->retrans)
203 _resp->retrans = RES_TIMEOUT;
204 if (!_resp->retry)
205 _resp->retry = 4;
206 if (!(_resp->options & RES_INIT))
207 _resp->options = RES_DEFAULT;
208
209#ifdef USELOOPBACK
210 _resp->nsaddr.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1);
211#else
212 _resp->nsaddr.sin_addr.s_addr = INADDR_ANY;
213#endif
214 _resp->nsaddr.sin_family = AF_INET;
215 _resp->nsaddr.sin_port = htons(NAMESERVER_PORT);
216 _resp->nsaddr.sin_len = sizeof(struct sockaddr_in);
217#ifdef INET6
218 if (sizeof(_res_extp->nsaddr) >= _resp->nsaddr.sin_len)
219 memcpy(&_res_extp->nsaddr, &_resp->nsaddr, _resp->nsaddr.sin_len);
220#endif
221 _resp->nscount = 1;
222 _resp->ndots = 1;
223 _resp->pfcode = 0;
224 strlcpy(_resp->lookups, "f", sizeof _resp->lookups);
225
226 /* Allow user to override the local domain definition */
227 if (issetugid() == 0 && (cp = getenv("LOCALDOMAIN")) != NULL) {
228 strlcpy(_resp->defdname, cp, sizeof(_resp->defdname));
229 haveenv++;
230
231 /*
232 * Set search list to be blank-separated strings
233 * from rest of env value. Permits users of LOCALDOMAIN
234 * to still have a search list, and anyone to set the
235 * one that they want to use as an individual (even more
236 * important now that the rfc1535 stuff restricts searches)
237 */
238 cp = _resp->defdname;
239 pp = _resp->dnsrch;
240 *pp++ = cp;
241 for (n = 0; *cp && pp < _resp->dnsrch + MAXDNSRCH; cp++) {
242 if (*cp == '\n') /* silly backwards compat */
243 break;
244 else if (*cp == ' ' || *cp == '\t') {
245 *cp = 0;
246 n = 1;
247 } else if (n) {
248 *pp++ = cp;
249 n = 0;
250 havesearch = 1;
251 }
252 }
253 /* null terminate last domain if there are excess */
254 while (*cp != '\0' && *cp != ' ' && *cp != '\t' && *cp != '\n')
255 cp++;
256 *cp = '\0';
257 *pp++ = 0;
258 }
259
260#define MATCH(line, name) \
261 (!strncmp(line, name, sizeof(name) - 1) && \
262 (line[sizeof(name) - 1] == ' ' || \
263 line[sizeof(name) - 1] == '\t'))
264
265 if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) {
266 strlcpy(_resp->lookups, "bf", sizeof _resp->lookups);
267
268 /* read the config file */
269 buf[0] = '\0';
270 while ((cp = fgetln(fp, &len)) != NULL) {
271 /* skip lines that are too long or zero length */
272 if (len >= sizeof(buf) || len == 0)
273 continue;
274 (void)memcpy(buf, cp, len);
275 buf[len] = '\0';
276 /* skip comments */
277 if ((cp = strpbrk(buf, ";#")) != NULL)
278 *cp = '\0';
279 if (buf[0] == '\0')
280 continue;
281 /* read default domain name */
282 if (MATCH(buf, "domain")) {
283 if (haveenv) /* skip if have from environ */
284 continue;
285 cp = buf + sizeof("domain") - 1;
286 while (*cp == ' ' || *cp == '\t')
287 cp++;
288 if ((*cp == '\0') || (*cp == '\n'))
289 continue;
290 strlcpy(_resp->defdname, cp, sizeof(_resp->defdname));
291 if ((cp = strpbrk(_resp->defdname, " \t\n")) != NULL)
292 *cp = '\0';
293 havesearch = 0;
294 continue;
295 }
296 /* lookup types */
297 if (MATCH(buf, "lookup")) {
298 char *sp = NULL;
299
300 bzero(_resp->lookups, sizeof _resp->lookups);
301 cp = buf + sizeof("lookup") - 1;
302 for (n = 0;; cp++) {
303 if (n == MAXDNSLUS)
304 break;
305 if ((*cp == '\0') || (*cp == '\n')) {
306 if (sp) {
307 if (*sp=='y' || *sp=='b' || *sp=='f')
308 _resp->lookups[n++] = *sp;
309 sp = NULL;
310 }
311 break;
312 } else if ((*cp == ' ') || (*cp == '\t') || (*cp == ',')) {
313 if (sp) {
314 if (*sp=='y' || *sp=='b' || *sp=='f')
315 _resp->lookups[n++] = *sp;
316 sp = NULL;
317 }
318 } else if (sp == NULL)
319 sp = cp;
320 }
321 continue;
322 }
323 /* set search list */
324 if (MATCH(buf, "search")) {
325 if (haveenv) /* skip if have from environ */
326 continue;
327 cp = buf + sizeof("search") - 1;
328 while (*cp == ' ' || *cp == '\t')
329 cp++;
330 if ((*cp == '\0') || (*cp == '\n'))
331 continue;
332 strlcpy(_resp->defdname, cp, sizeof(_resp->defdname));
333 if ((cp = strchr(_resp->defdname, '\n')) != NULL)
334 *cp = '\0';
335 /*
336 * Set search list to be blank-separated strings
337 * on rest of line.
338 */
339 cp = _resp->defdname;
340 pp = _resp->dnsrch;
341 *pp++ = cp;
342 for (n = 0; *cp && pp < _resp->dnsrch + MAXDNSRCH; cp++) {
343 if (*cp == ' ' || *cp == '\t') {
344 *cp = 0;
345 n = 1;
346 } else if (n) {
347 *pp++ = cp;
348 n = 0;
349 }
350 }
351 /* null terminate last domain if there are excess */
352 while (*cp != '\0' && *cp != ' ' && *cp != '\t')
353 cp++;
354 *cp = '\0';
355 *pp++ = 0;
356 havesearch = 1;
357 continue;
358 }
359 /* read nameservers to query */
360 if (MATCH(buf, "nameserver") && nserv < MAXNS) {
361#ifdef INET6
362 char *q;
363 struct addrinfo hints, *res;
364 char pbuf[NI_MAXSERV];
365#else
366 struct in_addr a;
367#endif /* INET6 */
368
369 cp = buf + sizeof("nameserver") - 1;
370 while (*cp == ' ' || *cp == '\t')
371 cp++;
372#ifdef INET6
373 if ((*cp == '\0') || (*cp == '\n'))
374 continue;
375 for (q = cp; *q; q++) {
376 if (isspace(*q)) {
377 *q = '\0';
378 break;
379 }
380 }
381 memset(&hints, 0, sizeof(hints));
382 hints.ai_flags = AI_NUMERICHOST;
383 hints.ai_socktype = SOCK_DGRAM;
384 snprintf(pbuf, sizeof(pbuf), "%u", NAMESERVER_PORT);
385 res = NULL;
386 if (getaddrinfo(cp, pbuf, &hints, &res) == 0 &&
387 res->ai_next == NULL) {
388 if (res->ai_addrlen <= sizeof(_res_extp->nsaddr_list[nserv])) {
389 memcpy(&_res_extp->nsaddr_list[nserv], res->ai_addr,
390 res->ai_addrlen);
391 } else {
392 memset(&_res_extp->nsaddr_list[nserv], 0,
393 sizeof(_res_extp->nsaddr_list[nserv]));
394 }
395 if (res->ai_addrlen <= sizeof(_resp->nsaddr_list[nserv])) {
396 memcpy(&_resp->nsaddr_list[nserv], res->ai_addr,
397 res->ai_addrlen);
398 } else {
399 memset(&_resp->nsaddr_list[nserv], 0,
400 sizeof(_resp->nsaddr_list[nserv]));
401 }
402 nserv++;
403 }
404 if (res)
405 freeaddrinfo(res);
406#else /* INET6 */
407 if ((*cp != '\0') && (*cp != '\n') && inet_aton(cp, &a)) {
408 _resp->nsaddr_list[nserv].sin_addr = a;
409 _resp->nsaddr_list[nserv].sin_family = AF_INET;
410 _resp->nsaddr_list[nserv].sin_port =
411 htons(NAMESERVER_PORT);
412 _resp->nsaddr_list[nserv].sin_len =
413 sizeof(struct sockaddr_in);
414 nserv++;
415 }
416#endif /* INET6 */
417 continue;
418 }
419#ifdef RESOLVSORT
420 if (MATCH(buf, "sortlist")) {
421 struct in_addr a;
422#ifdef INET6
423 struct in6_addr a6;
424 int m, i;
425 u_char *u;
426#endif /* INET6 */
427
428 cp = buf + sizeof("sortlist") - 1;
429 while (nsort < MAXRESOLVSORT) {
430 while (*cp == ' ' || *cp == '\t')
431 cp++;
432 if (*cp == '\0' || *cp == '\n' || *cp == ';')
433 break;
434 net = cp;
435 while (*cp && !ISSORTMASK(*cp) && *cp != ';' &&
436 isascii(*cp) && !isspace(*cp))
437 cp++;
438 n = *cp;
439 *cp = 0;
440 if (inet_aton(net, &a)) {
441 _resp->sort_list[nsort].addr = a;
442 if (ISSORTMASK(n)) {
443 *cp++ = n;
444 net = cp;
445 while (*cp && *cp != ';' &&
446 isascii(*cp) && !isspace(*cp))
447 cp++;
448 n = *cp;
449 *cp = 0;
450 if (inet_aton(net, &a)) {
451 _resp->sort_list[nsort].mask = a.s_addr;
452 } else {
453 _resp->sort_list[nsort].mask =
454 net_mask(_resp->sort_list[nsort].addr);
455 }
456 } else {
457 _resp->sort_list[nsort].mask =
458 net_mask(_resp->sort_list[nsort].addr);
459 }
460#ifdef INET6
461 _res_extp->sort_list[nsort].af = AF_INET;
462 _res_extp->sort_list[nsort].addr.ina =
463 _resp->sort_list[nsort].addr;
464 _res_extp->sort_list[nsort].mask.ina.s_addr =
465 _resp->sort_list[nsort].mask;
466#endif /* INET6 */
467 nsort++;
468 }
469#ifdef INET6
470 else if (inet_pton(AF_INET6, net, &a6) == 1) {
471 _res_extp->sort_list[nsort].af = AF_INET6;
472 _res_extp->sort_list[nsort].addr.in6a = a6;
473 u = (u_char *)&_res_extp->sort_list[nsort].mask.in6a;
474 *cp++ = n;
475 net = cp;
476 while (*cp && *cp != ';' &&
477 isascii(*cp) && !isspace(*cp))
478 cp++;
479 m = n;
480 n = *cp;
481 *cp = 0;
482 switch (m) {
483 case '/':
484 m = atoi(net);
485 break;
486 case '&':
487 if (inet_pton(AF_INET6, net, u) == 1) {
488 m = -1;
489 break;
490 }
491 /*FALLTHRU*/
492 default:
493 m = sizeof(struct in6_addr) * NBBY;
494 break;
495 }
496 if (m >= 0) {
497 for (i = 0; i < sizeof(struct in6_addr); i++) {
498 if (m <= 0) {
499 *u = 0;
500 } else {
501 m -= NBBY;
502 *u = (u_char)~0;
503 if (m < 0)
504 *u <<= -m;
505 }
506 u++;
507 }
508 }
509 nsort++;
510 }
511#endif /* INET6 */
512 *cp = n;
513 }
514 continue;
515 }
516#endif
517 if (MATCH(buf, "options")) {
518 res_setoptions(buf + sizeof("options") - 1, "conf");
519 continue;
520 }
521 }
522 if (nserv > 1)
523 _resp->nscount = nserv;
524#ifdef RESOLVSORT
525 _resp->nsort = nsort;
526#endif
527 (void) fclose(fp);
528 }
529 if (_resp->defdname[0] == 0 &&
530 gethostname(buf, sizeof(_resp->defdname) - 1) == 0 &&
531 (cp = strchr(buf, '.')) != NULL)
532 {
533 strlcpy(_resp->defdname, cp + 1,
534 sizeof(_resp->defdname));
535 }
536
537 /* find components of local domain that might be searched */
538 if (havesearch == 0) {
539 pp = _resp->dnsrch;
540 *pp++ = _resp->defdname;
541 *pp = NULL;
542
543#ifndef RFC1535
544 dots = 0;
545 for (cp = _resp->defdname; *cp; cp++)
546 dots += (*cp == '.');
547
548 cp = _resp->defdname;
549 while (pp < _resp->dnsrch + MAXDFLSRCH) {
550 if (dots < LOCALDOMAINPARTS)
551 break;
552 cp = strchr(cp, '.') + 1; /* we know there is one */
553 *pp++ = cp;
554 dots--;
555 }
556 *pp = NULL;
557#ifdef DEBUG
558 if (_resp->options & RES_DEBUG) {
559 printf(";; res_init()... default dnsrch list:\n");
560 for (pp = _resp->dnsrch; *pp; pp++)
561 printf(";;\t%s\n", *pp);
562 printf(";;\t..END..\n");
563 }
564#endif /* DEBUG */
565#endif /* !RFC1535 */
566 }
567
568 if (issetugid())
569 _resp->options |= RES_NOALIASES;
570 else if ((cp = getenv("RES_OPTIONS")) != NULL)
571 res_setoptions(cp, "env");
572 _resp->options |= RES_INIT;
573 return (0);
574}
575
576/* ARGSUSED */
577static void
578res_setoptions(options, source)
579 char *options, *source;
580{
581 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
582 char *cp = options;
583 char *endp;
584 long l;
585
586#ifdef DEBUG
587 if (_resp->options & RES_DEBUG)
588 printf(";; res_setoptions(\"%s\", \"%s\")...\n",
589 options, source);
590#endif
591 while (*cp) {
592 /* skip leading and inner runs of spaces */
593 while (*cp == ' ' || *cp == '\t')
594 cp++;
595 /* search for and process individual options */
596 if (!strncmp(cp, "ndots:", sizeof("ndots:") - 1)) {
597 char *p = cp + sizeof("ndots:") - 1;
598 l = strtol(p, &endp, 10);
599 if (l >= 0 && endp != p &&
600 (*endp = '\0' || isspace(*endp))) {
601 if (l <= RES_MAXNDOTS)
602 _resp->ndots = l;
603 else
604 _resp->ndots = RES_MAXNDOTS;
605#ifdef DEBUG
606 if (_resp->options & RES_DEBUG)
607 printf(";;\tndots=%u\n", _resp->ndots);
608#endif
609 }
610 } else if (!strncmp(cp, "debug", sizeof("debug") - 1)) {
611#ifdef DEBUG
612 if (!(_resp->options & RES_DEBUG)) {
613 printf(";; res_setoptions(\"%s\", \"%s\")..\n",
614 options, source);
615 _resp->options |= RES_DEBUG;
616 }
617 printf(";;\tdebug\n");
618#endif
619 } else if (!strncmp(cp, "inet6", sizeof("inet6") - 1)) {
620 _resp->options |= RES_USE_INET6;
621 } else if (!strncmp(cp, "insecure1", sizeof("insecure1") - 1)) {
622 _resp->options |= RES_INSECURE1;
623 } else if (!strncmp(cp, "insecure2", sizeof("insecure2") - 1)) {
624 _resp->options |= RES_INSECURE2;
625 } else if (!strncmp(cp, "edns0", sizeof("edns0") - 1)) {
626 _resp->options |= RES_USE_EDNS0;
627 } else {
628 /* XXX - print a warning here? */
629 }
630 /* skip to next run of spaces */
631 while (*cp && *cp != ' ' && *cp != '\t')
632 cp++;
633 }
634}
635
636#ifdef RESOLVSORT
637/* XXX - should really support CIDR which means explicit masks always. */
638static u_int32_t
639net_mask(in) /* XXX - should really use system's version of this */
640 struct in_addr in;
641{
642 register u_int32_t i = ntohl(in.s_addr);
643
644 if (IN_CLASSA(i))
645 return (htonl(IN_CLASSA_NET));
646 else if (IN_CLASSB(i))
647 return (htonl(IN_CLASSB_NET));
648 return (htonl(IN_CLASSC_NET));
649}
650#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..82aa2796c2
--- /dev/null
+++ b/src/lib/libc/net/res_mkquery.c
@@ -0,0 +1,242 @@
1/* $OpenBSD: res_mkquery.c,v 1.14 2003/06/02 20:18: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. 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)
55#if 0
56static char sccsid[] = "@(#)res_mkquery.c 8.1 (Berkeley) 6/4/93";
57static char rcsid[] = "$From: res_mkquery.c,v 8.5 1996/08/27 08:33:28 vixie Exp $";
58#else
59static char rcsid[] = "$OpenBSD: res_mkquery.c,v 1.14 2003/06/02 20:18:36 millert Exp $";
60#endif
61#endif /* LIBC_SCCS and not lint */
62
63#include <sys/types.h>
64#include <sys/param.h>
65#include <netinet/in.h>
66#include <arpa/nameser.h>
67
68#include <stdio.h>
69#include <netdb.h>
70#include <resolv.h>
71#include <string.h>
72
73#include "thread_private.h"
74
75/*
76 * Form all types of queries.
77 * Returns the size of the result or -1.
78 */
79/* ARGSUSED */
80int
81res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen)
82 int op; /* opcode of query */
83 const char *dname; /* domain name */
84 int class, type; /* class and type of query */
85 const u_char *data; /* resource record data */
86 int datalen; /* length of data */
87 const u_char *newrr_in; /* new rr for modify or append */
88 u_char *buf; /* buffer to put query */
89 int buflen; /* size of buffer */
90{
91 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
92 register HEADER *hp;
93 register u_char *cp, *ep;
94 register int n;
95 u_char *dnptrs[20], **dpp, **lastdnptr;
96
97 if ((_resp->options & RES_INIT) == 0 && res_init() == -1) {
98 h_errno = NETDB_INTERNAL;
99 return (-1);
100 }
101#ifdef DEBUG
102 if (_resp->options & RES_DEBUG)
103 printf(";; res_mkquery(%d, %s, %d, %d)\n",
104 op, dname, class, type);
105#endif
106 /*
107 * Initialize header fields.
108 *
109 * A special random number generator is used to create non predictable
110 * and non repeating ids over a long period. It also avoids reuse
111 * by switching between two distinct number cycles.
112 */
113
114 if ((buf == NULL) || (buflen < HFIXEDSZ))
115 return (-1);
116 bzero(buf, HFIXEDSZ);
117 hp = (HEADER *) buf;
118 _resp->id = res_randomid();
119 hp->id = htons(_resp->id);
120 hp->opcode = op;
121 hp->rd = (_resp->options & RES_RECURSE) != 0;
122 hp->rcode = NOERROR;
123 cp = buf + HFIXEDSZ;
124 ep = buf + buflen;
125 dpp = dnptrs;
126 *dpp++ = buf;
127 *dpp++ = NULL;
128 lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0];
129 /*
130 * perform opcode specific processing
131 */
132 switch (op) {
133 case QUERY: /*FALLTHROUGH*/
134 case NS_NOTIFY_OP:
135 if (ep - cp < QFIXEDSZ)
136 return (-1);
137 if ((n = dn_comp(dname, cp, ep - cp - QFIXEDSZ, dnptrs,
138 lastdnptr)) < 0)
139 return (-1);
140 cp += n;
141 __putshort(type, cp);
142 cp += INT16SZ;
143 __putshort(class, cp);
144 cp += INT16SZ;
145 hp->qdcount = htons(1);
146 if (op == QUERY || data == NULL)
147 break;
148 /*
149 * Make an additional record for completion domain.
150 */
151 if (ep - cp < RRFIXEDSZ)
152 return (-1);
153 n = dn_comp((char *)data, cp, ep - cp - RRFIXEDSZ, dnptrs,
154 lastdnptr);
155 if (n < 0)
156 return (-1);
157 cp += n;
158 __putshort(T_NULL, cp);
159 cp += INT16SZ;
160 __putshort(class, cp);
161 cp += INT16SZ;
162 __putlong(0, cp);
163 cp += INT32SZ;
164 __putshort(0, cp);
165 cp += INT16SZ;
166 hp->arcount = htons(1);
167 break;
168
169 case IQUERY:
170 /*
171 * Initialize answer section
172 */
173 if (ep - cp < 1 + RRFIXEDSZ + datalen)
174 return (-1);
175 *cp++ = '\0'; /* no domain name */
176 __putshort(type, cp);
177 cp += INT16SZ;
178 __putshort(class, cp);
179 cp += INT16SZ;
180 __putlong(0, cp);
181 cp += INT32SZ;
182 __putshort(datalen, cp);
183 cp += INT16SZ;
184 if (datalen) {
185 bcopy(data, cp, datalen);
186 cp += datalen;
187 }
188 hp->ancount = htons(1);
189 break;
190
191 default:
192 return (-1);
193 }
194 return (cp - buf);
195}
196
197/* attach OPT pseudo-RR, as documented in RFC2671 (EDNS0). */
198int
199res_opt(n0, buf, buflen, anslen)
200 int n0;
201 u_char *buf; /* buffer to put query */
202 int buflen; /* size of buffer */
203 int anslen; /* answer buffer length */
204{
205 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
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 (_resp->options & RES_USE_DNSSEC) {
227#ifdef DEBUG
228 if (_resp->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..3cdb7a7477
--- /dev/null
+++ b/src/lib/libc/net/res_query.c
@@ -0,0 +1,407 @@
1/* $OpenBSD: res_query.c,v 1.21 2003/06/02 20:18:36 millert 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. 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)
55#if 0
56static char sccsid[] = "@(#)res_query.c 8.1 (Berkeley) 6/4/93";
57static char rcsid[] = "$From: res_query.c,v 8.9 1996/09/22 00:13:28 vixie Exp $";
58#else
59static char rcsid[] = "$OpenBSD: res_query.c,v 1.21 2003/06/02 20:18:36 millert Exp $";
60#endif
61#endif /* LIBC_SCCS and not lint */
62
63#include <sys/types.h>
64#include <sys/param.h>
65#include <netinet/in.h>
66#include <arpa/inet.h>
67#include <arpa/nameser.h>
68
69#include <stdio.h>
70#include <netdb.h>
71#include <resolv.h>
72#include <ctype.h>
73#include <errno.h>
74#include <stdlib.h>
75#include <string.h>
76#include <unistd.h>
77
78#include "thread_private.h"
79
80#if PACKETSZ > 1024
81#define MAXPACKET PACKETSZ
82#else
83#define MAXPACKET 1024
84#endif
85
86const char *hostalias(const char *);
87int h_errno;
88extern int res_opt(int, u_char *, int, int);
89
90/*
91 * Formulate a normal query, send, and await answer.
92 * Returned answer is placed in supplied buffer "answer".
93 * Perform preliminary check of answer, returning success only
94 * if no error is indicated and the answer count is nonzero.
95 * Return the size of the response on success, -1 on error.
96 * Error number is left in h_errno.
97 *
98 * Caller must parse answer and determine whether it answers the question.
99 */
100int
101res_query(name, class, type, answer, anslen)
102 const char *name; /* domain name */
103 int class, type; /* class and type of query */
104 u_char *answer; /* buffer to put answer */
105 int anslen; /* size of answer buffer */
106{
107 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
108 u_char buf[MAXPACKET];
109 register HEADER *hp = (HEADER *) answer;
110 int n;
111
112 hp->rcode = NOERROR; /* default */
113
114 if ((_resp->options & RES_INIT) == 0 && res_init() == -1) {
115 h_errno = NETDB_INTERNAL;
116 return (-1);
117 }
118#ifdef DEBUG
119 if (_resp->options & RES_DEBUG)
120 printf(";; res_query(%s, %d, %d)\n", name, class, type);
121#endif
122
123 n = res_mkquery(QUERY, name, class, type, NULL, 0, NULL,
124 buf, sizeof(buf));
125 if (n > 0 && ((_resp->options & RES_USE_EDNS0) ||
126 (_resp->options & RES_USE_DNSSEC))) {
127 n = res_opt(n, buf, sizeof(buf), anslen);
128 }
129
130 if (n <= 0) {
131#ifdef DEBUG
132 if (_resp->options & RES_DEBUG)
133 printf(";; res_query: mkquery failed\n");
134#endif
135 h_errno = NO_RECOVERY;
136 return (n);
137 }
138 n = res_send(buf, n, answer, anslen);
139 if (n < 0) {
140#ifdef DEBUG
141 if (_resp->options & RES_DEBUG)
142 printf(";; res_query: send error\n");
143#endif
144 h_errno = TRY_AGAIN;
145 return (n);
146 }
147
148 if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
149#ifdef DEBUG
150 if (_resp->options & RES_DEBUG)
151 printf(";; rcode = %u, ancount=%u\n", hp->rcode,
152 ntohs(hp->ancount));
153#endif
154 switch (hp->rcode) {
155 case NXDOMAIN:
156 h_errno = HOST_NOT_FOUND;
157 break;
158 case SERVFAIL:
159 h_errno = TRY_AGAIN;
160 break;
161 case NOERROR:
162 h_errno = NO_DATA;
163 break;
164 case FORMERR:
165 case NOTIMP:
166 case REFUSED:
167 default:
168 h_errno = NO_RECOVERY;
169 break;
170 }
171 return (-1);
172 }
173 return (n);
174}
175
176/*
177 * Formulate a normal query, send, and retrieve answer in supplied buffer.
178 * Return the size of the response on success, -1 on error.
179 * If enabled, implement search rules until answer or unrecoverable failure
180 * is detected. Error code, if any, is left in h_errno.
181 */
182int
183res_search(name, class, type, answer, anslen)
184 const char *name; /* domain name */
185 int class, type; /* class and type of query */
186 u_char *answer; /* buffer to put answer */
187 int anslen; /* size of answer */
188{
189 register const char *cp, * const *domain;
190 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
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 ((_resp->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 >= _resp->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 && (_resp->options & RES_DEFNAMES)) ||
235 (dots && !trailing_dot && (_resp->options & RES_DNSRCH))) {
236 int done = 0;
237
238 for (domain = (const char * const *)_resp->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 (!(_resp->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 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
330 char nbuf[MAXDNAME*2+1+1];
331 const char *longname = nbuf;
332 int n;
333
334 if ((_resp->options & RES_INIT) == 0 && res_init() == -1) {
335 h_errno = NETDB_INTERNAL;
336 return (-1);
337 }
338#ifdef DEBUG
339 if (_resp->options & RES_DEBUG)
340 printf(";; res_querydomain(%s, %s, %d, %d)\n",
341 name, domain?domain:"<Nil>", class, type);
342#endif
343 if (domain == NULL) {
344 /*
345 * Check for trailing '.';
346 * copy without '.' if present.
347 */
348 n = strlen(name) - 1;
349 if (n != (0 - 1) && name[n] == '.' && n < sizeof(nbuf) - 1) {
350 bcopy(name, nbuf, n);
351 nbuf[n] = '\0';
352 } else
353 longname = name;
354 } else
355 snprintf(nbuf, sizeof nbuf, "%.*s.%.*s",
356 MAXDNAME, name, MAXDNAME, domain);
357
358 return (res_query(longname, class, type, answer, anslen));
359}
360
361const char *
362hostalias(name)
363 register const char *name;
364{
365 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
366 register char *cp1, *cp2;
367 FILE *fp;
368 char *file;
369 char buf[BUFSIZ];
370 static char abuf[MAXDNAME];
371 size_t len;
372
373 if (_resp->options & RES_NOALIASES)
374 return (NULL);
375 file = getenv("HOSTALIASES");
376 if (issetugid() != 0 || file == NULL || (fp = fopen(file, "r")) == NULL)
377 return (NULL);
378 setbuf(fp, NULL);
379 while ((cp1 = fgetln(fp, &len)) != NULL) {
380 if (cp1[len-1] == '\n')
381 len--;
382 if (len >= sizeof(buf) || len == 0)
383 continue;
384 (void)memcpy(buf, cp1, len);
385 buf[len] = '\0';
386
387 for (cp1 = buf; *cp1 && !isspace(*cp1); ++cp1)
388 ;
389 if (!*cp1)
390 break;
391 *cp1 = '\0';
392 if (!strcasecmp(buf, name)) {
393 while (isspace(*++cp1))
394 ;
395 if (!*cp1)
396 break;
397 for (cp2 = cp1 + 1; *cp2 && !isspace(*cp2); ++cp2)
398 ;
399 *cp2 = '\0';
400 strlcpy(abuf, cp1, sizeof(abuf));
401 fclose(fp);
402 return (abuf);
403 }
404 }
405 fclose(fp);
406 return (NULL);
407}
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..c456a92d32
--- /dev/null
+++ b/src/lib/libc/net/res_send.c
@@ -0,0 +1,898 @@
1/* $OpenBSD: res_send.c,v 1.15 2003/06/02 20:18:36 millert 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. 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#ifndef INET6
55#define INET6
56#endif
57
58#if defined(LIBC_SCCS) && !defined(lint)
59#if 0
60static char sccsid[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93";
61static char rcsid[] = "$From: res_send.c,v 8.12 1996/10/08 04:51:06 vixie Exp $";
62#else
63static char rcsid[] = "$OpenBSD: res_send.c,v 1.15 2003/06/02 20:18:36 millert Exp $";
64#endif
65#endif /* LIBC_SCCS and not lint */
66
67 /* change this to "0"
68 * if you talk to a lot
69 * of multi-homed SunOS
70 * ("broken") name servers.
71 */
72#define CHECK_SRVR_ADDR 1 /* XXX - should be in options.h */
73
74/*
75 * Send query to name server and wait for reply.
76 */
77
78#include <sys/types.h>
79#include <sys/param.h>
80#include <sys/time.h>
81#include <sys/socket.h>
82#include <sys/uio.h>
83#include <netinet/in.h>
84#include <arpa/nameser.h>
85#include <arpa/inet.h>
86
87#include <stdio.h>
88#include <netdb.h>
89#include <errno.h>
90#include <resolv.h>
91#include <stdlib.h>
92#include <string.h>
93#include <unistd.h>
94
95#include "thread_private.h"
96
97static int s = -1; /* socket used for communications */
98static int connected = 0; /* is the socket connected */
99static int vc = 0; /* is the socket a virtual ciruit? */
100static int af = 0; /* address family of socket */
101
102#ifndef FD_SET
103/* XXX - should be in portability.h */
104#define NFDBITS 32
105#define FD_SETSIZE 32
106#define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
107#define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
108#define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
109#define FD_ZERO(p) bzero((char *)(p), sizeof(*(p)))
110#endif
111
112#define CAN_RECONNECT 1
113
114#ifndef DEBUG
115# define Dprint(cond, args) /*empty*/
116# define DprintQ(cond, args, query, size) /*empty*/
117# define Aerror(file, string, error, address) /*empty*/
118# define Perror(file, string, error) /*empty*/
119#else
120# define Dprint(cond, args) if (cond) {fprintf args;} else {}
121# define DprintQ(cond, args, query, size) if (cond) {\
122 fprintf args;\
123 __fp_nquery(query, size, stdout);\
124 } else {}
125static char abuf[NI_MAXHOST];
126static char pbuf[NI_MAXSERV];
127static void Aerror(FILE *, char *, int, struct sockaddr *);
128static void Perror(FILE *, char *, int);
129
130 static void
131 Aerror(file, string, error, address)
132 FILE *file;
133 char *string;
134 int error;
135 struct sockaddr *address;
136 {
137 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
138 int save = errno;
139
140 if (_resp->options & RES_DEBUG) {
141 if (getnameinfo(address, address->sa_len, abuf, sizeof(abuf),
142 pbuf, sizeof(pbuf),
143 NI_NUMERICHOST|NI_NUMERICSERV|NI_WITHSCOPEID) != 0) {
144 strlcpy(abuf, "?", sizeof(abuf));
145 strlcpy(pbuf, "?", sizeof(pbuf));
146 }
147 fprintf(file, "res_send: %s ([%s].%s): %s\n",
148 string, abuf, pbuf, strerror(error));
149 }
150 errno = save;
151 }
152 static void
153 Perror(file, string, error)
154 FILE *file;
155 char *string;
156 int error;
157 {
158 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
159 int save = errno;
160
161 if (_resp->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 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
199 struct __res_state_ext *_res_extp = _THREAD_PRIVATE(_res_ext, _res_ext,
200 &_res_ext);
201
202 if (!_resp->nsaddr_list[n].sin_family) {
203 /*
204 * - _res_extp->nsaddr_list[n] holds an address that is larger
205 * than struct sockaddr, and
206 * - user code did not update _resp->nsaddr_list[n].
207 */
208 return (struct sockaddr *)&_res_extp->nsaddr_list[n];
209 } else {
210 /*
211 * - user code updated _res.nsaddr_list[n], or
212 * - _resp->nsaddr_list[n] has the same content as
213 * _res_extp->nsaddr_list[n].
214 */
215 return (struct sockaddr *)&_resp->nsaddr_list[n];
216 }
217}
218#else
219#define get_nsaddr(n) ((struct sockaddr *)&_resp->nsaddr_list[(n)])
220#endif
221
222/* int
223 * res_isourserver(ina)
224 * looks up "ina" in _resp->ns_addr_list[]
225 * returns:
226 * 0 : not found
227 * >0 : found
228 * author:
229 * paul vixie, 29may94
230 */
231int
232res_isourserver(inp)
233 const struct sockaddr_in *inp;
234{
235 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
236#ifdef INET6
237 const struct sockaddr_in6 *in6p = (const struct sockaddr_in6 *)inp;
238 const struct sockaddr_in6 *srv6;
239#endif
240 const struct sockaddr_in *srv;
241 int ns, ret;
242
243 ret = 0;
244 switch (inp->sin_family) {
245#ifdef INET6
246 case AF_INET6:
247 for (ns = 0; ns < _resp->nscount; ns++) {
248 srv6 = (struct sockaddr_in6 *)get_nsaddr(ns);
249 if (srv6->sin6_family == in6p->sin6_family &&
250 srv6->sin6_port == in6p->sin6_port &&
251 srv6->sin6_scope_id == in6p->sin6_scope_id &&
252 (IN6_IS_ADDR_UNSPECIFIED(&srv6->sin6_addr) ||
253 IN6_ARE_ADDR_EQUAL(&srv6->sin6_addr,
254 &in6p->sin6_addr))) {
255 ret++;
256 break;
257 }
258 }
259 break;
260#endif
261 case AF_INET:
262 for (ns = 0; ns < _resp->nscount; ns++) {
263 srv = (struct sockaddr_in *)get_nsaddr(ns);
264 if (srv->sin_family == inp->sin_family &&
265 srv->sin_port == inp->sin_port &&
266 (srv->sin_addr.s_addr == INADDR_ANY ||
267 srv->sin_addr.s_addr == inp->sin_addr.s_addr)) {
268 ret++;
269 break;
270 }
271 }
272 break;
273 }
274 return (ret);
275}
276
277/* int
278 * res_nameinquery(name, type, class, buf, eom)
279 * look for (name,type,class) in the query section of packet (buf,eom)
280 * returns:
281 * -1 : format error
282 * 0 : not found
283 * >0 : found
284 * author:
285 * paul vixie, 29may94
286 */
287int
288res_nameinquery(name, type, class, buf, eom)
289 const char *name;
290 register int type, class;
291 const u_char *buf, *eom;
292{
293 register const u_char *cp = buf + HFIXEDSZ;
294 int qdcount = ntohs(((HEADER*)buf)->qdcount);
295
296 while (qdcount-- > 0) {
297 char tname[MAXDNAME+1];
298 register int n, ttype, tclass;
299
300 n = dn_expand(buf, eom, cp, tname, sizeof tname);
301 if (n < 0)
302 return (-1);
303 cp += n;
304 ttype = _getshort(cp); cp += INT16SZ;
305 tclass = _getshort(cp); cp += INT16SZ;
306 if (ttype == type &&
307 tclass == class &&
308 strcasecmp(tname, name) == 0)
309 return (1);
310 }
311 return (0);
312}
313
314/* int
315 * res_queriesmatch(buf1, eom1, buf2, eom2)
316 * is there a 1:1 mapping of (name,type,class)
317 * in (buf1,eom1) and (buf2,eom2)?
318 * returns:
319 * -1 : format error
320 * 0 : not a 1:1 mapping
321 * >0 : is a 1:1 mapping
322 * author:
323 * paul vixie, 29may94
324 */
325int
326res_queriesmatch(buf1, eom1, buf2, eom2)
327 const u_char *buf1, *eom1;
328 const u_char *buf2, *eom2;
329{
330 register const u_char *cp = buf1 + HFIXEDSZ;
331 int qdcount = ntohs(((HEADER*)buf1)->qdcount);
332
333 if (qdcount != ntohs(((HEADER*)buf2)->qdcount))
334 return (0);
335 while (qdcount-- > 0) {
336 char tname[MAXDNAME+1];
337 register int n, ttype, tclass;
338
339 n = dn_expand(buf1, eom1, cp, tname, sizeof tname);
340 if (n < 0)
341 return (-1);
342 cp += n;
343 ttype = _getshort(cp); cp += INT16SZ;
344 tclass = _getshort(cp); cp += INT16SZ;
345 if (!res_nameinquery(tname, ttype, tclass, buf2, eom2))
346 return (0);
347 }
348 return (1);
349}
350
351int
352res_send(buf, buflen, ans, anssiz)
353 const u_char *buf;
354 int buflen;
355 u_char *ans;
356 int anssiz;
357{
358 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
359 HEADER *hp = (HEADER *) buf;
360 HEADER *anhp = (HEADER *) ans;
361 int gotsomewhere, connreset, terrno, try, v_circuit, resplen, ns;
362 register int n;
363 u_int badns; /* XXX NSMAX can't exceed #/bits in this var */
364
365 if ((_resp->options & RES_INIT) == 0 && res_init() == -1) {
366 /* errno should have been set by res_init() in this case. */
367 return (-1);
368 }
369 DprintQ((_resp->options & RES_DEBUG) || (_resp->pfcode & RES_PRF_QUERY),
370 (stdout, ";; res_send()\n"), buf, buflen);
371 v_circuit = (_resp->options & RES_USEVC) || buflen > PACKETSZ;
372 gotsomewhere = 0;
373 connreset = 0;
374 terrno = ETIMEDOUT;
375 badns = 0;
376
377 /*
378 * Send request, RETRY times, or until successful
379 */
380 for (try = 0; try < _resp->retry; try++) {
381 for (ns = 0; ns < _resp->nscount; ns++) {
382 struct sockaddr *nsap = get_nsaddr(ns);
383 socklen_t salen;
384
385 if (nsap->sa_len)
386 salen = nsap->sa_len;
387#ifdef INET6
388 else if (nsap->sa_family == AF_INET6)
389 salen = sizeof(struct sockaddr_in6);
390#endif
391 else if (nsap->sa_family == AF_INET)
392 salen = sizeof(struct sockaddr_in);
393 else
394 salen = 0; /*unknown, die on connect*/
395
396 same_ns:
397 if (badns & (1 << ns)) {
398 res_close();
399 goto next_ns;
400 }
401
402 if (Qhook) {
403 int done = 0, loops = 0;
404
405 do {
406 res_sendhookact act;
407
408 act = (*Qhook)((struct sockaddr_in **)&nsap,
409 &buf, &buflen,
410 ans, anssiz, &resplen);
411 switch (act) {
412 case res_goahead:
413 done = 1;
414 break;
415 case res_nextns:
416 res_close();
417 goto next_ns;
418 case res_done:
419 return (resplen);
420 case res_modified:
421 /* give the hook another try */
422 if (++loops < 42) /*doug adams*/
423 break;
424 /*FALLTHROUGH*/
425 case res_error:
426 /*FALLTHROUGH*/
427 default:
428 return (-1);
429 }
430 } while (!done);
431 }
432
433 Dprint((_resp->options & RES_DEBUG) &&
434 getnameinfo(nsap, salen, abuf, sizeof(abuf),
435 NULL, 0, NI_NUMERICHOST | NI_WITHSCOPEID) == 0,
436 (stdout, ";; Querying server (# %d) address = %s\n",
437 ns + 1, abuf));
438
439 if (v_circuit) {
440 int truncated;
441 struct iovec iov[2];
442 u_short len;
443 u_char *cp;
444
445 /*
446 * Use virtual circuit;
447 * at most one attempt per server.
448 */
449 try = _resp->retry;
450 truncated = 0;
451 if ((s < 0) || (!vc) || (af != nsap->sa_family)) {
452 if (s >= 0)
453 res_close();
454
455 af = nsap->sa_family;
456 s = socket(af, SOCK_STREAM, 0);
457 if (s < 0) {
458 terrno = errno;
459 Perror(stderr, "socket(vc)", errno);
460#if 0
461 return (-1);
462#else
463 badns |= (1 << ns);
464 res_close();
465 goto next_ns;
466#endif
467 }
468 errno = 0;
469 if (connect(s, nsap, salen) < 0) {
470 terrno = errno;
471 Aerror(stderr, "connect/vc",
472 errno, nsap);
473 badns |= (1 << ns);
474 res_close();
475 goto next_ns;
476 }
477 vc = 1;
478 }
479 /*
480 * Send length & message
481 */
482 putshort((u_short)buflen, (u_char*)&len);
483 iov[0].iov_base = (caddr_t)&len;
484 iov[0].iov_len = INT16SZ;
485 iov[1].iov_base = (caddr_t)buf;
486 iov[1].iov_len = buflen;
487 if (writev(s, iov, 2) != (INT16SZ + buflen)) {
488 terrno = errno;
489 Perror(stderr, "write failed", errno);
490 badns |= (1 << ns);
491 res_close();
492 goto next_ns;
493 }
494 /*
495 * Receive length & response
496 */
497read_len:
498 cp = ans;
499 len = INT16SZ;
500 while ((n = read(s, (char *)cp, (int)len)) > 0) {
501 cp += n;
502 if ((len -= n) <= 0)
503 break;
504 }
505 if (n <= 0) {
506 terrno = errno;
507 Perror(stderr, "read failed", errno);
508 res_close();
509 /*
510 * A long running process might get its TCP
511 * connection reset if the remote server was
512 * restarted. Requery the server instead of
513 * trying a new one. When there is only one
514 * server, this means that a query might work
515 * instead of failing. We only allow one reset
516 * per query to prevent looping.
517 */
518 if (terrno == ECONNRESET && !connreset) {
519 connreset = 1;
520 res_close();
521 goto same_ns;
522 }
523 res_close();
524 goto next_ns;
525 }
526 resplen = _getshort(ans);
527 if (resplen > anssiz) {
528 Dprint(_resp->options & RES_DEBUG,
529 (stdout, ";; response truncated\n")
530 );
531 truncated = 1;
532 len = anssiz;
533 } else
534 len = resplen;
535 cp = ans;
536 while (len != 0 &&
537 (n = read(s, (char *)cp, (int)len)) > 0) {
538 cp += n;
539 len -= n;
540 }
541 if (n <= 0) {
542 terrno = errno;
543 Perror(stderr, "read(vc)", errno);
544 res_close();
545 goto next_ns;
546 }
547 if (truncated) {
548 /*
549 * Flush rest of answer
550 * so connection stays in synch.
551 */
552 anhp->tc = 1;
553 len = resplen - anssiz;
554 while (len != 0) {
555 char junk[PACKETSZ];
556
557 n = (len > sizeof(junk)
558 ? sizeof(junk)
559 : len);
560 if ((n = read(s, junk, n)) > 0)
561 len -= n;
562 else
563 break;
564 }
565 }
566 /*
567 * The calling applicating has bailed out of
568 * a previous call and failed to arrange to have
569 * the circuit closed or the server has got
570 * itself confused. Anyway drop the packet and
571 * wait for the correct one.
572 */
573 if (hp->id != anhp->id) {
574 DprintQ((_resp->options & RES_DEBUG) ||
575 (_resp->pfcode & RES_PRF_REPLY),
576 (stdout, ";; old answer (unexpected):\n"),
577 ans, (resplen>anssiz)?anssiz:resplen);
578 goto read_len;
579 }
580 } else {
581 /*
582 * Use datagrams.
583 */
584 struct timeval timeout;
585 fd_set *dsmaskp;
586 struct sockaddr_storage from;
587 socklen_t fromlen;
588
589 if ((s < 0) || vc || (af != nsap->sa_family)) {
590 if (vc)
591 res_close();
592 af = nsap->sa_family;
593 s = socket(af, SOCK_DGRAM, 0);
594 if (s < 0) {
595#if !CAN_RECONNECT
596 bad_dg_sock:
597#endif
598 terrno = errno;
599 Perror(stderr, "socket(dg)", errno);
600#if 0
601 return (-1);
602#else
603 badns |= (1 << ns);
604 res_close();
605 goto next_ns;
606#endif
607 }
608#ifdef IPV6_MINMTU
609 if (af == AF_INET6) {
610 const int yes = 1;
611 (void)setsockopt(s, IPPROTO_IPV6,
612 IPV6_USE_MIN_MTU, &yes,
613 sizeof(yes));
614 }
615#endif
616 connected = 0;
617 }
618 /*
619 * On a 4.3BSD+ machine (client and server,
620 * actually), sending to a nameserver datagram
621 * port with no nameserver will cause an
622 * ICMP port unreachable message to be returned.
623 * If our datagram socket is "connected" to the
624 * server, we get an ECONNREFUSED error on the next
625 * socket operation, and select returns if the
626 * error message is received. We can thus detect
627 * the absence of a nameserver without timing out.
628 * If we have sent queries to at least two servers,
629 * however, we don't want to remain connected,
630 * as we wish to receive answers from the first
631 * server to respond.
632 */
633 if (!(_resp->options & RES_INSECURE1) &&
634 (_resp->nscount == 1 || (try == 0 && ns == 0))) {
635 /*
636 * Connect only if we are sure we won't
637 * receive a response from another server.
638 */
639 if (!connected) {
640 if (connect(s, nsap, salen) < 0) {
641 Aerror(stderr,
642 "connect(dg)",
643 errno, nsap);
644 badns |= (1 << ns);
645 res_close();
646 goto next_ns;
647 }
648 connected = 1;
649 }
650 if (send(s, (char*)buf, buflen, 0) != buflen) {
651 Perror(stderr, "send", errno);
652 badns |= (1 << ns);
653 res_close();
654 goto next_ns;
655 }
656 } else {
657 /*
658 * Disconnect if we want to listen
659 * for responses from more than one server.
660 */
661 if (connected) {
662#if CAN_RECONNECT
663#ifdef INET6
664 /* XXX: any errornous address */
665#endif /* INET6 */
666 struct sockaddr_in no_addr;
667
668 no_addr.sin_family = AF_INET;
669 no_addr.sin_addr.s_addr = INADDR_ANY;
670 no_addr.sin_port = 0;
671 (void) connect(s,
672 (struct sockaddr *)
673 &no_addr,
674 sizeof(no_addr));
675#else
676 int s1 = socket(af, SOCK_DGRAM,0);
677 if (s1 < 0)
678 goto bad_dg_sock;
679 (void) dup2(s1, s);
680 (void) close(s1);
681 Dprint(_resp->options & RES_DEBUG,
682 (stdout, ";; new DG socket\n"))
683#endif
684#ifdef IPV6_MINMTU
685 if (af == AF_INET6) {
686 const int yes = 1;
687 (void)setsockopt(s, IPPROTO_IPV6,
688 IPV6_USE_MIN_MTU, &yes,
689 sizeof(yes));
690 }
691#endif
692 connected = 0;
693 errno = 0;
694 }
695 if (sendto(s, (char*)buf, buflen, 0,
696 nsap, salen) != buflen) {
697 Aerror(stderr, "sendto", errno, nsap);
698 badns |= (1 << ns);
699 res_close();
700 goto next_ns;
701 }
702 }
703
704 /*
705 * Wait for reply
706 */
707 timeout.tv_sec = (_resp->retrans << try);
708 if (try > 0)
709 timeout.tv_sec /= _resp->nscount;
710 if ((long) timeout.tv_sec <= 0)
711 timeout.tv_sec = 1;
712 timeout.tv_usec = 0;
713 wait:
714 dsmaskp = (fd_set *)calloc(howmany(s+1, NFDBITS),
715 sizeof(fd_mask));
716 if (dsmaskp == NULL) {
717 res_close();
718 goto next_ns;
719 }
720 FD_SET(s, dsmaskp);
721 n = select(s+1, dsmaskp, (fd_set *)NULL,
722 (fd_set *)NULL, &timeout);
723 free(dsmaskp);
724 if (n < 0) {
725 if (errno == EINTR)
726 goto wait;
727 Perror(stderr, "select", errno);
728 res_close();
729 goto next_ns;
730 }
731 if (n == 0) {
732 /*
733 * timeout
734 */
735 Dprint(_resp->options & RES_DEBUG,
736 (stdout, ";; timeout\n"));
737 gotsomewhere = 1;
738 res_close();
739 goto next_ns;
740 }
741 errno = 0;
742 fromlen = sizeof(from);
743 resplen = recvfrom(s, (char*)ans, anssiz, 0,
744 (struct sockaddr *)&from, &fromlen);
745 if (resplen <= 0) {
746 Perror(stderr, "recvfrom", errno);
747 res_close();
748 goto next_ns;
749 }
750 gotsomewhere = 1;
751 if (hp->id != anhp->id) {
752 /*
753 * response from old query, ignore it.
754 * XXX - potential security hazard could
755 * be detected here.
756 */
757 DprintQ((_resp->options & RES_DEBUG) ||
758 (_resp->pfcode & RES_PRF_REPLY),
759 (stdout, ";; old answer:\n"),
760 ans, (resplen>anssiz)?anssiz:resplen);
761 goto wait;
762 }
763#if CHECK_SRVR_ADDR
764 if (!(_resp->options & RES_INSECURE1) &&
765 !res_isourserver((struct sockaddr_in *)&from)) {
766 /*
767 * response from wrong server? ignore it.
768 * XXX - potential security hazard could
769 * be detected here.
770 */
771 DprintQ((_resp->options & RES_DEBUG) ||
772 (_resp->pfcode & RES_PRF_REPLY),
773 (stdout, ";; not our server:\n"),
774 ans, (resplen>anssiz)?anssiz:resplen);
775 goto wait;
776 }
777#endif
778 if (!(_resp->options & RES_INSECURE2) &&
779 !res_queriesmatch(buf, buf + buflen,
780 ans, ans + anssiz)) {
781 /*
782 * response contains wrong query? ignore it.
783 * XXX - potential security hazard could
784 * be detected here.
785 */
786 DprintQ((_resp->options & RES_DEBUG) ||
787 (_resp->pfcode & RES_PRF_REPLY),
788 (stdout, ";; wrong query name:\n"),
789 ans, (resplen>anssiz)?anssiz:resplen);
790 goto wait;
791 }
792 if (anhp->rcode == SERVFAIL ||
793 anhp->rcode == NOTIMP ||
794 anhp->rcode == REFUSED) {
795 DprintQ(_resp->options & RES_DEBUG,
796 (stdout, "server rejected query:\n"),
797 ans, (resplen>anssiz)?anssiz:resplen);
798 badns |= (1 << ns);
799 res_close();
800 /* don't retry if called from dig */
801 if (!_resp->pfcode)
802 goto next_ns;
803 }
804 if (!(_resp->options & RES_IGNTC) && anhp->tc) {
805 /*
806 * get rest of answer;
807 * use TCP with same server.
808 */
809 Dprint(_resp->options & RES_DEBUG,
810 (stdout, ";; truncated answer\n"));
811 v_circuit = 1;
812 res_close();
813 goto same_ns;
814 }
815 } /*if vc/dg*/
816 Dprint((_resp->options & RES_DEBUG) ||
817 ((_resp->pfcode & RES_PRF_REPLY) &&
818 (_resp->pfcode & RES_PRF_HEAD1)),
819 (stdout, ";; got answer:\n"));
820 DprintQ((_resp->options & RES_DEBUG) ||
821 (_resp->pfcode & RES_PRF_REPLY),
822 (stdout, "%s", ""),
823 ans, (resplen>anssiz)?anssiz:resplen);
824 /*
825 * If using virtual circuits, we assume that the first server
826 * is preferred over the rest (i.e. it is on the local
827 * machine) and only keep that one open.
828 * If we have temporarily opened a virtual circuit,
829 * or if we haven't been asked to keep a socket open,
830 * close the socket.
831 */
832 if ((v_circuit && (!(_resp->options & RES_USEVC) || ns != 0)) ||
833 !(_resp->options & RES_STAYOPEN)) {
834 res_close();
835 }
836 if (Rhook) {
837 int done = 0, loops = 0;
838
839 do {
840 res_sendhookact act;
841
842 act = (*Rhook)((struct sockaddr_in *)nsap,
843 buf, buflen,
844 ans, anssiz, &resplen);
845 switch (act) {
846 case res_goahead:
847 case res_done:
848 done = 1;
849 break;
850 case res_nextns:
851 res_close();
852 goto next_ns;
853 case res_modified:
854 /* give the hook another try */
855 if (++loops < 42) /*doug adams*/
856 break;
857 /*FALLTHROUGH*/
858 case res_error:
859 /*FALLTHROUGH*/
860 default:
861 return (-1);
862 }
863 } while (!done);
864
865 }
866 return (resplen);
867 next_ns: ;
868 } /*foreach ns*/
869 } /*foreach retry*/
870 res_close();
871 if (!v_circuit) {
872 if (!gotsomewhere)
873 errno = ECONNREFUSED; /* no nameservers found */
874 else
875 errno = ETIMEDOUT; /* no answer obtained */
876 } else
877 errno = terrno;
878 return (-1);
879}
880
881/*
882 * This routine is for closing the socket if a virtual circuit is used and
883 * the program wants to close it. This provides support for endhostent()
884 * which expects to close the socket.
885 *
886 * This routine is not expected to be user visible.
887 */
888void
889res_close()
890{
891 if (s >= 0) {
892 (void) close(s);
893 s = -1;
894 connected = 0;
895 vc = 0;
896 af = 0;
897 }
898}
diff --git a/src/lib/libc/net/resolver.3 b/src/lib/libc/net/resolver.3
new file mode 100644
index 0000000000..577420e9f1
--- /dev/null
+++ b/src/lib/libc/net/resolver.3
@@ -0,0 +1,341 @@
1.\" $OpenBSD: resolver.3,v 1.17 2003/08/08 09:26:02 jmc 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. Neither the name of the University nor the names of its contributors
15.\" may be used to endorse or promote products derived from this software
16.\" without specific prior written permission.
17.\"
18.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28.\" SUCH DAMAGE.
29.\"
30.Dd June 4, 1993
31.Dt RESOLVER 3
32.Os
33.Sh NAME
34.Nm res_query ,
35.Nm res_search ,
36.Nm res_mkquery ,
37.Nm res_send ,
38.Nm res_init ,
39.Nm dn_comp ,
40.Nm dn_expand
41.Nd resolver routines
42.Sh SYNOPSIS
43.Fd #include <sys/types.h>
44.Fd #include <netinet/in.h>
45.Fd #include <arpa/nameser.h>
46.Fd #include <resolv.h>
47.Ft int
48.Fo res_query
49.Fa "char *dname"
50.Fa "int class"
51.Fa "int type"
52.Fa "u_char *answer"
53.Fa "int anslen"
54.Fc
55.Ft int
56.Fo res_search
57.Fa "char *dname"
58.Fa "int class"
59.Fa "int type"
60.Fa "u_char *answer"
61.Fa "int anslen"
62.Fc
63.Ft int
64.Fo res_mkquery
65.Fa "int op"
66.Fa "char *dname"
67.Fa "int class"
68.Fa "int type"
69.Fa "char *data"
70.Fa "int datalen"
71.Fa "struct rrec *newrr"
72.Fa "char *buf"
73.Fa "int buflen"
74.Fc
75.Ft int
76.Fo res_send
77.Fa "char *msg"
78.Fa "int msglen"
79.Fa "char *answer"
80.Fa "int anslen"
81.Fc
82.Ft int
83.Fn res_init "void"
84.Ft int
85.Fo dn_comp
86.Fa "char *exp_dn"
87.Fa "char *comp_dn"
88.Fa "int length"
89.Fa "char **dnptrs"
90.Fa "char **lastdnptr"
91.Fc
92.Ft int
93.Fo dn_expand
94.Fa "u_char *msg"
95.Fa "u_char *eomorig"
96.Fa "u_char *comp_dn"
97.Fa "u_char *exp_dn"
98.Fa "int length"
99.Fc
100.Sh DESCRIPTION
101These routines are used for making, sending, and interpreting
102query and reply messages with Internet domain name servers.
103.Pp
104Global configuration and state information that is used by the
105resolver routines is kept in the structure
106.Li _res .
107Most of the values have reasonable defaults and can be ignored.
108Options stored in
109.Li _res.options
110are defined in
111.Aq Pa resolv.h
112and are as follows.
113Options are stored as a simple bit mask containing the bitwise
114.Tn OR
115of the options enabled.
116.Bl -tag -width RES_USE_INET6
117.It Dv RES_INIT
118True if the initial name server address and default domain name are
119initialized (i.e.,
120.Fn res_init
121has been called).
122.It Dv RES_DEBUG
123Print debugging messages.
124.It Dv RES_AAONLY
125Accept authoritative answers only.
126With this option,
127.Fn res_send
128should continue until it finds an authoritative answer or finds an error.
129Currently this is not implemented.
130.It Dv RES_USEVC
131Use
132.Tn TCP
133connections for queries instead of
134.Tn UDP
135datagrams.
136.It Dv RES_STAYOPEN
137Used with
138.Dv RES_USEVC
139to keep the
140.Tn TCP
141connection open between queries.
142This is useful only in programs that regularly do many queries.
143.Tn UDP
144should be the normal mode used.
145.It Dv RES_IGNTC
146Unused currently (ignore truncation errors, i.e., don't retry with
147.Tn TCP ) .
148.It Dv RES_RECURSE
149Set the recursion-desired bit in queries.
150This is the default.
151.Pf ( Fn res_send
152does not do iterative queries and expects the name server
153to handle recursion.)
154.It Dv RES_DEFNAMES
155If set,
156.Fn res_search
157will append the default domain name to single-component names
158(those that do not contain a dot).
159This option is enabled by default.
160.It Dv RES_DNSRCH
161If this option is set,
162.Fn res_search
163will search for host names in the current domain and in parent domains; see
164.Xr hostname 7 .
165This is used by the standard host lookup routine
166.Xr gethostbyname 3 .
167This option is enabled by default.
168.It Dv RES_USE_INET6
169Enables support for IPv6-only applications.
170This causes IPv4 addresses to be returned as an IPv4 mapped address.
171For example, 10.1.1.1 will be returned as ::ffff:10.1.1.1.
172The option is not meaningful on
173.Ox .
174.El
175.Pp
176The
177.Fn res_init
178routine reads the configuration file (if any; see
179.Xr resolv.conf 5 )
180to get the default domain name, search list, and the Internet address
181of the local name server(s).
182If no server is configured, the host running
183the resolver is tried.
184The current domain name is defined by the hostname
185if not specified in the configuration file;
186it can be overridden by the environment variable
187.Ev LOCALDOMAIN .
188This environment variable may contain several blank-separated
189tokens if you wish to override the
190.Fa search list
191on a per-process basis.
192This is similar to the
193.Fa search
194command in the configuration file.
195Another environment variable
196.Ev RES_OPTIONS
197can be set to override certain internal resolver options which
198are otherwise set by changing fields in the
199.Fa _res
200structure or are inherited from the configuration file's
201.Fa options
202command.
203The syntax of the
204.Ev RES_OPTIONS
205environment variable is explained in
206.Xr resolv.conf 5 .
207Initialization normally occurs on the first call
208to one of the following routines.
209.Pp
210The
211.Fn res_query
212function provides an interface to the server query mechanism.
213It constructs a query, sends it to the local server,
214awaits a response, and makes preliminary checks on the reply.
215The query requests information of the specified
216.Fa type
217and
218.Fa class
219for the specified fully qualified domain name
220.Fa dname .
221The reply message is left in the
222.Fa answer
223buffer with length
224.Fa anslen
225supplied by the caller.
226.Pp
227The
228.Fn res_search
229routine makes a query and awaits a response like
230.Fn res_query ,
231but in addition, it implements the default and search rules controlled by the
232.Dv RES_DEFNAMES
233and
234.Dv RES_DNSRCH
235options.
236It returns the first successful reply.
237.Pp
238The remaining routines are lower-level routines used by
239.Fn res_query .
240The
241.Fn res_mkquery
242function constructs a standard query message and places it in
243.Fa buf .
244It returns the size of the query, or \-1 if the query is larger than
245.Fa buflen .
246The query type
247.Fa op
248is usually
249.Dv QUERY ,
250but can be any of the query types defined in
251.Aq Pa arpa/nameser.h .
252The domain name for the query is given by
253.Fa dname .
254.Fa newrr
255is currently unused but is intended for making update messages.
256.Pp
257The
258.Fn res_send
259routine sends a pre-formatted query and returns an answer.
260It will call
261.Fn res_init
262if
263.Dv RES_INIT
264is not set, send the query to the local name server, and
265handle timeouts and retries.
266The length of the reply message is returned, or \-1 if there were errors.
267.Pp
268The
269.Fn dn_comp
270function compresses the domain name
271.Fa exp_dn
272and stores it in
273.Fa comp_dn .
274The size of the compressed name is returned or \-1 if there were errors.
275The size of the array pointed to by
276.Fa comp_dn
277is given by
278.Fa length .
279The compression uses an array of pointers
280.Fa dnptrs
281to previously compressed names in the current message.
282The first pointer points
283to the beginning of the message and the list ends with
284.Dv NULL .
285The limit to the array is specified by
286.Fa lastdnptr .
287A side effect of
288.Fn dn_comp
289is to update the list of pointers for labels inserted into the message
290as the name is compressed.
291If
292.Em dnptr
293is
294.Dv NULL ,
295names are not compressed.
296If
297.Fa lastdnptr
298is
299.Dv NULL ,
300the list of labels is not updated.
301.Pp
302The
303.Fn dn_expand
304entry expands the compressed domain name
305.Fa comp_dn
306to a full domain name
307The compressed name is contained in a query or reply message;
308.Fa msg
309is a pointer to the beginning of the message.
310The uncompressed name is placed in the buffer indicated by
311.Fa exp_dn
312which is of size
313.Fa length .
314The size of compressed name is returned or \-1 if there was an error.
315.Sh FILES
316.Bl -tag -width Pa
317/etc/resolv.conf
318configuration file
319see
320.Xr resolv.conf 5 .
321.El
322.Sh SEE ALSO
323.Xr gethostbyname 3 ,
324.Xr resolv.conf 5 ,
325.Xr hostname 7 ,
326.Xr named 8
327.Pp
328.%T RFC 1032 ,
329.%T RFC 1033 ,
330.%T RFC 1034 ,
331.%T RFC 1035 ,
332.%T RFC 1535 ,
333.%T RFC 974
334.Rs
335.%T "Name Server Operations Guide for BIND"
336.Re
337.Sh HISTORY
338The
339.Nm
340function appeared in
341.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..6e4698e3be
--- /dev/null
+++ b/src/lib/libc/net/rresvport.c
@@ -0,0 +1,113 @@
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. Neither the name of the University nor the names of its contributors
15 * may be used to endorse or promote products derived from this software
16 * without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31#if defined(LIBC_SCCS) && !defined(lint)
32static char *rcsid = "$OpenBSD: rresvport.c,v 1.6 2003/06/03 02:11:35 deraadt Exp $";
33#endif /* LIBC_SCCS and not lint */
34
35#include <sys/param.h>
36#include <sys/socket.h>
37#include <sys/stat.h>
38
39#include <netinet/in.h>
40#include <arpa/inet.h>
41
42#include <signal.h>
43#include <fcntl.h>
44#include <netdb.h>
45#include <unistd.h>
46#include <pwd.h>
47#include <errno.h>
48#include <stdio.h>
49#include <ctype.h>
50#include <string.h>
51#include <syslog.h>
52#include <stdlib.h>
53#include <netgroup.h>
54
55int
56rresvport(alport)
57 int *alport;
58{
59 return rresvport_af(alport, AF_INET);
60}
61
62
63int
64rresvport_af(alport, af)
65 int *alport;
66 int af;
67{
68 struct sockaddr_storage ss;
69 struct sockaddr *sa;
70 u_int16_t *portp;
71 int s;
72
73 bzero(&ss, sizeof ss);
74 sa = (struct sockaddr *)&ss;
75
76 switch (af) {
77 case AF_INET:
78 sa->sa_len = sizeof(struct sockaddr_in);
79 portp = &((struct sockaddr_in *)sa)->sin_port;
80 break;
81 case AF_INET6:
82 sa->sa_len = sizeof(struct sockaddr_in6);
83 portp = &((struct sockaddr_in6 *)sa)->sin6_port;
84 break;
85 default:
86 errno = EPFNOSUPPORT;
87 return (-1);
88 }
89 sa->sa_family = af;
90
91 s = socket(af, SOCK_STREAM, 0);
92 if (s < 0)
93 return (-1);
94
95 *portp = htons(*alport);
96 if (*alport < IPPORT_RESERVED - 1) {
97 if (bind(s, sa, sa->sa_len) >= 0)
98 return (s);
99 if (errno != EADDRINUSE) {
100 (void)close(s);
101 return (-1);
102 }
103 }
104
105 *portp = 0;
106 sa->sa_family = af;
107 if (bindresvport_sa(s, sa) == -1) {
108 (void)close(s);
109 return (-1);
110 }
111 *alport = ntohs(*portp);
112 return (s);
113}
diff --git a/src/lib/libc/net/rthdr.c b/src/lib/libc/net/rthdr.c
new file mode 100644
index 0000000000..366ca9e6ba
--- /dev/null
+++ b/src/lib/libc/net/rthdr.c
@@ -0,0 +1,228 @@
1/* $OpenBSD: rthdr.c,v 1.6 2003/06/11 02:54: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 +
51 sizeof(struct ip6_rthdr0)));
52 default:
53 return (0);
54 }
55}
56
57struct cmsghdr *
58inet6_rthdr_init(bp, type)
59 void *bp;
60 int type;
61{
62 struct cmsghdr *ch = (struct cmsghdr *)bp;
63 struct ip6_rthdr *rthdr;
64
65 rthdr = (struct ip6_rthdr *)CMSG_DATA(ch);
66
67 ch->cmsg_level = IPPROTO_IPV6;
68 ch->cmsg_type = IPV6_RTHDR;
69
70 switch (type) {
71 case IPV6_RTHDR_TYPE_0:
72 ch->cmsg_len = CMSG_LEN(sizeof(struct ip6_rthdr0));
73 bzero(rthdr, sizeof(struct ip6_rthdr0));
74 rthdr->ip6r_type = IPV6_RTHDR_TYPE_0;
75 return (ch);
76 default:
77 return (NULL);
78 }
79}
80
81int
82inet6_rthdr_add(cmsg, addr, flags)
83 struct cmsghdr *cmsg;
84 const struct in6_addr *addr;
85 u_int flags;
86{
87 struct ip6_rthdr *rthdr;
88
89 rthdr = (struct ip6_rthdr *)CMSG_DATA(cmsg);
90
91 switch (rthdr->ip6r_type) {
92 case IPV6_RTHDR_TYPE_0:
93 {
94 struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr;
95 if (flags != IPV6_RTHDR_LOOSE)
96 return (-1);
97 if (rt0->ip6r0_segleft == 23)
98 return (-1);
99 rt0->ip6r0_segleft++;
100 bcopy(addr, (caddr_t)rt0 + ((rt0->ip6r0_len + 1) << 3),
101 sizeof(struct in6_addr));
102 rt0->ip6r0_len += sizeof(struct in6_addr) >> 3;
103 cmsg->cmsg_len = CMSG_LEN((rt0->ip6r0_len + 1) << 3);
104 break;
105 }
106 default:
107 return (-1);
108 }
109
110 return (0);
111}
112
113int
114inet6_rthdr_lasthop(cmsg, flags)
115 struct cmsghdr *cmsg;
116 unsigned int flags;
117{
118 struct ip6_rthdr *rthdr;
119
120 rthdr = (struct ip6_rthdr *)CMSG_DATA(cmsg);
121
122 switch (rthdr->ip6r_type) {
123 case IPV6_RTHDR_TYPE_0:
124 {
125 struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr;
126 if (flags != IPV6_RTHDR_LOOSE)
127 return (-1);
128 if (rt0->ip6r0_segleft > 23)
129 return (-1);
130 break;
131 }
132 default:
133 return (-1);
134 }
135
136 return (0);
137}
138
139#if 0
140int
141inet6_rthdr_reverse(in, out)
142 const struct cmsghdr *in;
143 struct cmsghdr *out;
144{
145
146 return (-1);
147}
148#endif
149
150int
151inet6_rthdr_segments(cmsg)
152 const struct cmsghdr *cmsg;
153{
154 struct ip6_rthdr *rthdr;
155
156 rthdr = (struct ip6_rthdr *)CMSG_DATA(cmsg);
157
158 switch (rthdr->ip6r_type) {
159 case IPV6_RTHDR_TYPE_0:
160 {
161 struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr;
162
163 if (rt0->ip6r0_len % 2 || 46 < rt0->ip6r0_len)
164 return (-1);
165
166 return (rt0->ip6r0_len * 8) / sizeof(struct in6_addr);
167 }
168
169 default:
170 return (-1);
171 }
172}
173
174struct in6_addr *
175inet6_rthdr_getaddr(cmsg, index)
176 struct cmsghdr *cmsg;
177 int index;
178{
179 struct ip6_rthdr *rthdr;
180
181 rthdr = (struct ip6_rthdr *)CMSG_DATA(cmsg);
182
183 switch (rthdr->ip6r_type) {
184 case IPV6_RTHDR_TYPE_0:
185 {
186 struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr;
187 int naddr;
188
189 if (rt0->ip6r0_len % 2 || 46 < rt0->ip6r0_len)
190 return NULL;
191 naddr = (rt0->ip6r0_len * 8) / sizeof(struct in6_addr);
192 if (index <= 0 || naddr < index)
193 return NULL;
194 return ((struct in6_addr *)(rt0 + 1)) + index;
195 }
196
197 default:
198 return NULL;
199 }
200}
201
202int
203inet6_rthdr_getflags(cmsg, index)
204 const struct cmsghdr *cmsg;
205 int index;
206{
207 struct ip6_rthdr *rthdr;
208
209 rthdr = (struct ip6_rthdr *)CMSG_DATA(cmsg);
210
211 switch (rthdr->ip6r_type) {
212 case IPV6_RTHDR_TYPE_0:
213 {
214 struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr;
215 int naddr;
216
217 if (rt0->ip6r0_len % 2 || 46 < rt0->ip6r0_len)
218 return (-1);
219 naddr = (rt0->ip6r0_len * 8) / sizeof(struct in6_addr);
220 if (index < 0 || naddr < index)
221 return (-1);
222 return IPV6_RTHDR_LOOSE;
223 }
224
225 default:
226 return (-1);
227 }
228}
diff --git a/src/lib/libc/net/send.c b/src/lib/libc/net/send.c
new file mode 100644
index 0000000000..8a7cc74e2d
--- /dev/null
+++ b/src/lib/libc/net/send.c
@@ -0,0 +1,46 @@
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. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char rcsid[] = "$OpenBSD: send.c,v 1.3 2003/06/02 20:18:36 millert Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <sys/types.h>
35#include <sys/socket.h>
36
37#include <stddef.h>
38
39ssize_t
40send(s, msg, len, flags)
41 int s, flags;
42 size_t len;
43 const void *msg;
44{
45 return (sendto(s, msg, len, flags, NULL, 0));
46}
diff --git a/src/lib/libc/net/sethostent.c b/src/lib/libc/net/sethostent.c
new file mode 100644
index 0000000000..2a8df101d4
--- /dev/null
+++ b/src/lib/libc/net/sethostent.c
@@ -0,0 +1,61 @@
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. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char rcsid[] = "$OpenBSD: sethostent.c,v 1.6 2003/06/02 20:18:36 millert Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <sys/param.h>
35#include <netinet/in.h>
36#include <arpa/nameser.h>
37#include <netdb.h>
38#include <resolv.h>
39
40#include "thread_private.h"
41
42void
43sethostent(stayopen)
44 int stayopen;
45{
46 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
47
48 if ((_resp->options & RES_INIT) == 0 && res_init() == -1)
49 return;
50 if (stayopen)
51 _resp->options |= RES_STAYOPEN | RES_USEVC;
52}
53
54void
55endhostent()
56{
57 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
58
59 _resp->options &= ~(RES_STAYOPEN | RES_USEVC);
60 res_close();
61}
diff --git a/src/lib/libc/net/vars6.c b/src/lib/libc/net/vars6.c
new file mode 100644
index 0000000000..a22d49d047
--- /dev/null
+++ b/src/lib/libc/net/vars6.c
@@ -0,0 +1,42 @@
1/* $OpenBSD: vars6.c,v 1.2 2003/05/10 10:56:47 jmc 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 constant 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