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.inc90
-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.3122
-rw-r--r--src/lib/libc/net/ethers.c232
-rw-r--r--src/lib/libc/net/freeaddrinfo.c50
-rw-r--r--src/lib/libc/net/gai_strerror.393
-rw-r--r--src/lib/libc/net/gai_strerror.c76
-rw-r--r--src/lib/libc/net/getaddrinfo.3445
-rw-r--r--src/lib/libc/net/getaddrinfo.c1781
-rw-r--r--src/lib/libc/net/gethostbyname.3297
-rw-r--r--src/lib/libc/net/gethostnamadr.c1126
-rw-r--r--src/lib/libc/net/getifaddrs.3158
-rw-r--r--src/lib/libc/net/getifaddrs.c277
-rw-r--r--src/lib/libc/net/getnameinfo.3270
-rw-r--r--src/lib/libc/net/getnameinfo.c353
-rw-r--r--src/lib/libc/net/getnetbyaddr.c47
-rw-r--r--src/lib/libc/net/getnetbyname.c54
-rw-r--r--src/lib/libc/net/getnetent.3140
-rw-r--r--src/lib/libc/net/getnetent.c121
-rw-r--r--src/lib/libc/net/getnetnamadr.c384
-rw-r--r--src/lib/libc/net/getproto.c59
-rw-r--r--src/lib/libc/net/getprotoent.3213
-rw-r--r--src/lib/libc/net/getprotoent.c166
-rw-r--r--src/lib/libc/net/getprotoname.c67
-rw-r--r--src/lib/libc/net/getrrsetbyname.3166
-rw-r--r--src/lib/libc/net/getrrsetbyname.c514
-rw-r--r--src/lib/libc/net/getservbyname.c70
-rw-r--r--src/lib/libc/net/getservbyport.c64
-rw-r--r--src/lib/libc/net/getservent.3220
-rw-r--r--src/lib/libc/net/getservent.c168
-rw-r--r--src/lib/libc/net/herror.c106
-rw-r--r--src/lib/libc/net/htonl.c21
-rw-r--r--src/lib/libc/net/htons.c21
-rw-r--r--src/lib/libc/net/if_indextoname.3144
-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.3438
-rw-r--r--src/lib/libc/net/inet6_rthdr_space.3308
-rw-r--r--src/lib/libc/net/inet_addr.c171
-rw-r--r--src/lib/libc/net/inet_lnaof.c51
-rw-r--r--src/lib/libc/net/inet_makeaddr.c54
-rw-r--r--src/lib/libc/net/inet_net.3183
-rw-r--r--src/lib/libc/net/inet_net_ntop.c135
-rw-r--r--src/lib/libc/net/inet_net_pton.c191
-rw-r--r--src/lib/libc/net/inet_neta.c80
-rw-r--r--src/lib/libc/net/inet_netof.c50
-rw-r--r--src/lib/libc/net/inet_network.c84
-rw-r--r--src/lib/libc/net/inet_ntoa.c51
-rw-r--r--src/lib/libc/net/inet_ntop.c195
-rw-r--r--src/lib/libc/net/inet_pton.c207
-rw-r--r--src/lib/libc/net/ip6opt.c371
-rw-r--r--src/lib/libc/net/ipx.3122
-rw-r--r--src/lib/libc/net/ipx_addr.c213
-rw-r--r--src/lib/libc/net/ipx_ntoa.c46
-rw-r--r--src/lib/libc/net/link_addr.3127
-rw-r--r--src/lib/libc/net/linkaddr.c148
-rw-r--r--src/lib/libc/net/net_addrcmp.391
-rw-r--r--src/lib/libc/net/net_addrcmp.c63
-rw-r--r--src/lib/libc/net/nsap_addr.c94
-rw-r--r--src/lib/libc/net/ntohl.c21
-rw-r--r--src/lib/libc/net/ntohs.c21
-rw-r--r--src/lib/libc/net/rcmd.3266
-rw-r--r--src/lib/libc/net/rcmd.c687
-rw-r--r--src/lib/libc/net/rcmdsh.396
-rw-r--r--src/lib/libc/net/rcmdsh.c186
-rw-r--r--src/lib/libc/net/recv.c40
-rw-r--r--src/lib/libc/net/res_comp.c474
-rw-r--r--src/lib/libc/net/res_data.c105
-rw-r--r--src/lib/libc/net/res_debug.c1394
-rw-r--r--src/lib/libc/net/res_debug_syms.c189
-rw-r--r--src/lib/libc/net/res_init.c666
-rw-r--r--src/lib/libc/net/res_mkquery.c232
-rw-r--r--src/lib/libc/net/res_query.c398
-rw-r--r--src/lib/libc/net/res_random.c228
-rw-r--r--src/lib/libc/net/res_send.c870
-rw-r--r--src/lib/libc/net/resolver.3354
-rw-r--r--src/lib/libc/net/rresvport.c107
-rw-r--r--src/lib/libc/net/rthdr.c215
-rw-r--r--src/lib/libc/net/send.c40
-rw-r--r--src/lib/libc/net/sethostent.c57
-rw-r--r--src/lib/libc/net/vars6.c42
84 files changed, 19462 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..db2738f868
--- /dev/null
+++ b/src/lib/libc/net/Makefile.inc
@@ -0,0 +1,90 @@
1# $OpenBSD: Makefile.inc,v 1.42 2005/10/02 14:48:48 jmc 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 linkaddr.c net_addrcmp.c nsap_addr.c \
16 rcmd.c rresvport.c recv.c res_comp.c res_data.c res_debug.c \
17 res_debug_syms.c \
18 res_init.c res_mkquery.c res_query.c res_random.c res_send.c send.c \
19 sethostent.c ethers.c rcmdsh.c
20
21# IPv6
22SRCS+= ip6opt.c rthdr.c vars6.c
23
24# machine-dependent net sources
25# m-d Makefile.inc must include sources for:
26# htonl() htons() ntohl() ntohs()
27
28.include "${LIBCSRCDIR}/arch/${MACHINE_ARCH}/net/Makefile.inc"
29
30MAN+= byteorder.3 ethers.3 gai_strerror.3 getaddrinfo.3 gethostbyname.3 \
31 getifaddrs.3 getnameinfo.3 getnetent.3 getprotoent.3 \
32 getrrsetbyname.3 getservent.3 if_indextoname.3 inet.3 \
33 inet_net.3 inet6_option_space.3 inet6_rthdr_space.3 \
34 ipx.3 link_addr.3 net_addrcmp.3 \
35 rcmd.3 rcmdsh.3 resolver.3
36
37MLINKS+=byteorder.3 htonl.3 byteorder.3 htons.3 byteorder.3 ntohl.3 \
38 byteorder.3 ntohs.3 byteorder.3 htobe16.3 byteorder.3 htobe32.3 \
39 byteorder.3 htobe64.3 byteorder.3 betoh16.3 byteorder.3 betoh32.3 \
40 byteorder.3 betoh64.3 byteorder.3 htole16.3 byteorder.3 htole32.3 \
41 byteorder.3 htole64.3 byteorder.3 letoh16.3 byteorder.3 letoh32.3 \
42 byteorder.3 letoh64.3 byteorder.3 swap16.3 byteorder.3 swap32.3 \
43 byteorder.3 swap64.3
44MLINKS+=ethers.3 ether_aton.3 ethers.3 ether_hostton.3 ethers.3 ether_line.3 \
45 ethers.3 ether_ntoa.3 ethers.3 ether_ntohost.3
46MLINKS+=getaddrinfo.3 freeaddrinfo.3
47MLINKS+=gethostbyname.3 endhostent.3 gethostbyname.3 gethostbyaddr.3 \
48 gethostbyname.3 sethostent.3 gethostbyname.3 gethostent.3 \
49 gethostbyname.3 herror.3 gethostbyname.3 gethostbyname2.3 \
50 gethostbyname.3 hstrerror.3
51MLINKS+=getifaddrs.3 freeifaddrs.3
52MLINKS+=getnetent.3 endnetent.3 getnetent.3 getnetbyaddr.3 \
53 getnetent.3 getnetbyname.3 getnetent.3 setnetent.3
54MLINKS+=getprotoent.3 endprotoent.3 getprotoent.3 getprotobyname.3 \
55 getprotoent.3 getprotobynumber.3 getprotoent.3 setprotoent.3 \
56 getprotoent.3 getprotoent_r.3 getprotoent.3 getprotobyname_r.3 \
57 getprotoent.3 getprotobynumber_r.3 getprotoent.3 setprotoent_r.3 \
58 getprotoent.3 endprotoent_r.3
59MLINKS+=getservent.3 endservent.3 getservent.3 getservbyname.3 \
60 getservent.3 getservbyport.3 getservent.3 setservent.3 \
61 getservent.3 getservent_r.3 getservent.3 getservbyname_r.3 \
62 getservent.3 getservbyport_r.3 setservent.3 setservent_r.3 \
63 setservent.3 endservent_r.3
64MLINKS+= if_indextoname.3 if_nametoindex.3 if_indextoname.3 if_nameindex.3 \
65 if_indextoname.3 if_freenameindex.3
66MLINKS+=inet.3 addr.3 inet.3 inet_addr.3 inet.3 inet_aton.3 \
67 inet.3 inet_lnaof.3 inet.3 inet_makeaddr.3 inet.3 inet_netof.3 \
68 inet.3 inet_network.3 inet.3 inet_ntoa.3 inet.3 network.3 \
69 inet.3 ntoa.3 inet.3 inet_ntop.3 inet.3 inet_pton.3
70MLINKS+=inet_net.3 inet_net_ntop.3 inet_net.3 inet_net_pton.3
71MLINKS+=link_addr.3 link_ntoa.3
72MLINKS+=ipx.3 ipx_addr.3 ipx.3 ipx_ntoa.3
73MLINKS+=rcmd.3 iruserok.3 rcmd.3 rresvport.3 rcmd.3 ruserok.3 \
74 rcmd.3 rresvport_af.3 rcmd.3 rcmd_af.3 rcmd.3 iruserok_sa.3
75MLINKS+=resolver.3 dn_comp.3 resolver.3 dn_expand.3 resolver.3 res_init.3 \
76 resolver.3 res_mkquery.3 resolver.3 res_send.3 resolver.3 res_query.3 \
77 resolver.3 res_search.3
78MLINKS+=getrrsetbyname.3 freerrset.3
79MLINKS+=inet6_option_space.3 inet6_option_init.3 \
80 inet6_option_space.3 inet6_option_append.3 \
81 inet6_option_space.3 inet6_option_alloc.3 \
82 inet6_option_space.3 inet6_option_next.3 \
83 inet6_option_space.3 inet6_option_find.3
84MLINKS+=inet6_rthdr_space.3 inet6_rthdr_init.3 \
85 inet6_rthdr_space.3 inet6_rthdr_add.3 \
86 inet6_rthdr_space.3 inet6_rthdr_lasthop.3 \
87 inet6_rthdr_space.3 inet6_rthdr_reverse.3 \
88 inet6_rthdr_space.3 inet6_rthdr_segments.3 \
89 inet6_rthdr_space.3 inet6_rthdr_getaddr.3 \
90 inet6_rthdr_space.3 inet6_rthdr_getflags.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..e548958617
--- /dev/null
+++ b/src/lib/libc/net/byteorder.3
@@ -0,0 +1,206 @@
1.\" $OpenBSD: byteorder.3,v 1.14 2005/07/22 04:50:51 jaredy 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 convert 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, or 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..fac9c590e3
--- /dev/null
+++ b/src/lib/libc/net/ethers.3
@@ -0,0 +1,122 @@
1.\" $OpenBSD: ethers.3,v 1.18 2005/12/30 20:45:59 claudio 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_ntohost ,
12.Nm ether_hostton ,
13.Nm ether_line
14.Nd get ethers entry
15.Sh SYNOPSIS
16.Fd #include <sys/types.h>
17.Fd #include <sys/socket.h>
18.Fd #include <net/if.h>
19.Fd #include <netinet/in.h>
20.Fd #include <netinet/if_ether.h>
21.Ft char *
22.Fn ether_ntoa "struct ether_addr *e"
23.Ft struct ether_addr *
24.Fn ether_aton "const char *s"
25.Ft int
26.Fn ether_ntohost "char *hostname" "struct ether_addr *e"
27.Ft int
28.Fn ether_hostton "const char *hostname" "struct ether_addr *e"
29.Ft int
30.Fn ether_line "const char *l" "struct ether_addr *e" "char *hostname"
31.Sh DESCRIPTION
32Ethernet addresses are represented by the
33following structure:
34.Bd -literal -offset indent
35struct ether_addr {
36 u_int8_t ether_addr_octet[6];
37};
38.Ed
39.Pp
40The
41.Fn ether_ntoa
42function converts this structure into an
43.Tn ASCII
44string of the form
45.Dq xx:xx:xx:xx:xx:xx ,
46consisting of 6 hexadecimal numbers separated
47by colons.
48It returns a pointer to a static buffer that is reused for each call.
49The
50.Fn ether_aton
51converts an
52.Tn ASCII
53string of the same form and to a structure
54containing the 6 octets of the address.
55It returns a pointer to a static structure that is reused for each call.
56.Pp
57The
58.Fn ether_ntohost
59and
60.Fn ether_hostton
61functions interrogate the database mapping host names to Ethernet
62addresses,
63.Pa /etc/ethers .
64The
65.Fn ether_ntohost
66function looks up the given Ethernet address and writes the associated
67host name into the character buffer passed.
68This buffer should be
69.Dv MAXHOSTNAMELEN
70characters in size.
71The
72.Fn ether_hostton
73function looks up the given host name and writes the associated
74Ethernet address into the structure passed.
75Both functions return
76zero if they find the requested host name or address, and \-1 if not.
77.Pp
78Each call reads
79.Pa /etc/ethers
80from the beginning; if a
81.Ql +
82appears alone on a line in the file, then
83.Fn ether_hostton
84will consult the
85.Pa ethers.byname
86YP map, and
87.Fn ether_ntohost
88will consult the
89.Pa ethers.byaddr
90YP map.
91.Pp
92The
93.Fn ether_line
94function parses a line from the
95.Pa /etc/ethers
96file and fills in the passed
97.Li struct ether_addr
98and character buffer with the Ethernet address and host name on the line.
99It returns zero if the line was successfully parsed and \-1 if not.
100The character buffer should be
101.Dv MAXHOSTNAMELEN
102characters in size.
103.Sh FILES
104.Bl -tag -width /etc/ethers -compact
105.It Pa /etc/ethers
106.El
107.Sh SEE ALSO
108.Xr ethers 5
109.Sh HISTORY
110The
111.Fn ether_ntoa ,
112.Fn ether_aton ,
113.Fn ether_ntohost ,
114.Fn ether_hostton ,
115and
116.Fn ether_line
117functions were adopted from SunOS and appeared in
118.Nx 0.9 b.
119.Sh BUGS
120The data space used by these functions is static; if future use
121requires the data, it should be copied before any subsequent calls to
122these 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..d4243ff1da
--- /dev/null
+++ b/src/lib/libc/net/ethers.c
@@ -0,0 +1,232 @@
1/* $OpenBSD: ethers.c,v 1.20 2005/08/06 20:30:03 espie 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#include <sys/types.h>
26#include <sys/socket.h>
27#include <net/if.h>
28#include <netinet/in.h>
29#include <netinet/if_ether.h>
30#include <sys/param.h>
31#include <paths.h>
32#include <errno.h>
33#include <stdio.h>
34#include <stdlib.h>
35#include <string.h>
36#include <ctype.h>
37#ifdef YP
38#include <rpcsvc/ypclnt.h>
39#endif
40
41#ifndef _PATH_ETHERS
42#define _PATH_ETHERS "/etc/ethers"
43#endif
44
45static char * _ether_aton(const char *, struct ether_addr *);
46
47char *
48ether_ntoa(struct ether_addr *e)
49{
50 static char a[] = "xx:xx:xx:xx:xx:xx";
51
52 (void)snprintf(a, sizeof a, "%02x:%02x:%02x:%02x:%02x:%02x",
53 e->ether_addr_octet[0], e->ether_addr_octet[1],
54 e->ether_addr_octet[2], e->ether_addr_octet[3],
55 e->ether_addr_octet[4], e->ether_addr_octet[5]);
56
57 return (a);
58}
59
60static char *
61_ether_aton(const char *s, struct ether_addr *e)
62{
63 int i;
64 long l;
65 char *pp;
66
67 while (isspace(*s))
68 s++;
69
70 /* expect 6 hex octets separated by ':' or space/NUL if last octet */
71 for (i = 0; i < 6; i++) {
72 l = strtol(s, &pp, 16);
73 if (pp == s || l > 0xFF || l < 0)
74 return (NULL);
75 if (!(*pp == ':' || (i == 5 && (isspace(*pp) || *pp == '\0'))))
76 return (NULL);
77 e->ether_addr_octet[i] = (u_char)l;
78 s = pp + 1;
79 }
80
81 /* return character after the octets ala strtol(3) */
82 return (pp);
83}
84
85struct ether_addr *
86ether_aton(const char *s)
87{
88 static struct ether_addr n;
89
90 return (_ether_aton(s, &n) ? &n : NULL);
91}
92
93int
94ether_ntohost(char *hostname, struct ether_addr *e)
95{
96 FILE *f;
97 char buf[BUFSIZ+1], *p;
98 size_t len;
99 struct ether_addr try;
100#ifdef YP
101 char trybuf[sizeof("xx:xx:xx:xx:xx:xx")];
102 int trylen;
103#endif
104
105#ifdef YP
106 snprintf(trybuf, sizeof trybuf, "%x:%x:%x:%x:%x:%x",
107 e->ether_addr_octet[0], e->ether_addr_octet[1],
108 e->ether_addr_octet[2], e->ether_addr_octet[3],
109 e->ether_addr_octet[4], e->ether_addr_octet[5]);
110 trylen = strlen(trybuf);
111#endif
112
113 f = fopen(_PATH_ETHERS, "r");
114 if (f == NULL)
115 return (-1);
116 while ((p = fgetln(f, &len)) != NULL) {
117 if (p[len-1] == '\n')
118 len--;
119 if (len > sizeof(buf) - 2)
120 continue;
121 (void)memcpy(buf, p, len);
122 buf[len] = '\n'; /* code assumes newlines later on */
123 buf[len+1] = '\0';
124#ifdef YP
125 /* A + in the file means try YP now. */
126 if (!strncmp(buf, "+\n", sizeof(buf))) {
127 char *ypbuf, *ypdom;
128 int ypbuflen;
129
130 if (yp_get_default_domain(&ypdom))
131 continue;
132 if (yp_match(ypdom, "ethers.byaddr", trybuf,
133 trylen, &ypbuf, &ypbuflen))
134 continue;
135 if (ether_line(ypbuf, &try, hostname) == 0) {
136 free(ypbuf);
137 (void)fclose(f);
138 return (0);
139 }
140 free(ypbuf);
141 continue;
142 }
143#endif
144 if (ether_line(buf, &try, hostname) == 0 &&
145 memcmp((void *)&try, (void *)e, sizeof(try)) == 0) {
146 (void)fclose(f);
147 return (0);
148 }
149 }
150 (void)fclose(f);
151 errno = ENOENT;
152 return (-1);
153}
154
155int
156ether_hostton(const char *hostname, struct ether_addr *e)
157{
158 FILE *f;
159 char buf[BUFSIZ+1], *p;
160 char try[MAXHOSTNAMELEN];
161 size_t len;
162#ifdef YP
163 int hostlen = strlen(hostname);
164#endif
165
166 f = fopen(_PATH_ETHERS, "r");
167 if (f==NULL)
168 return (-1);
169
170 while ((p = fgetln(f, &len)) != NULL) {
171 if (p[len-1] == '\n')
172 len--;
173 if (len > sizeof(buf) - 2)
174 continue;
175 memcpy(buf, p, len);
176 buf[len] = '\n'; /* code assumes newlines later on */
177 buf[len+1] = '\0';
178#ifdef YP
179 /* A + in the file means try YP now. */
180 if (!strncmp(buf, "+\n", sizeof(buf))) {
181 char *ypbuf, *ypdom;
182 int ypbuflen;
183
184 if (yp_get_default_domain(&ypdom))
185 continue;
186 if (yp_match(ypdom, "ethers.byname", hostname, hostlen,
187 &ypbuf, &ypbuflen))
188 continue;
189 if (ether_line(ypbuf, e, try) == 0) {
190 free(ypbuf);
191 (void)fclose(f);
192 return (0);
193 }
194 free(ypbuf);
195 continue;
196 }
197#endif
198 if (ether_line(buf, e, try) == 0 && strcmp(hostname, try) == 0) {
199 (void)fclose(f);
200 return (0);
201 }
202 }
203 (void)fclose(f);
204 errno = ENOENT;
205 return (-1);
206}
207
208int
209ether_line(const char *line, struct ether_addr *e, char *hostname)
210{
211 char *p;
212 size_t n;
213
214 /* Parse "xx:xx:xx:xx:xx:xx" */
215 if ((p = _ether_aton(line, e)) == NULL || (*p != ' ' && *p != '\t'))
216 goto bad;
217
218 /* Now get the hostname */
219 while (isspace(*p))
220 p++;
221 if (*p == '\0')
222 goto bad;
223 n = strcspn(p, " \t\n");
224 if (n >= MAXHOSTNAMELEN)
225 goto bad;
226 strlcpy(hostname, p, n + 1);
227 return (0);
228
229bad:
230 errno = EINVAL;
231 return (-1);
232}
diff --git a/src/lib/libc/net/freeaddrinfo.c b/src/lib/libc/net/freeaddrinfo.c
new file mode 100644
index 0000000000..58702d0b18
--- /dev/null
+++ b/src/lib/libc/net/freeaddrinfo.c
@@ -0,0 +1,50 @@
1/* $OpenBSD: freeaddrinfo.c,v 1.6 2005/03/25 13:24:11 otto Exp $ */
2
3/*
4 * Copyright (c) 1996, 1997, 1998, 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#include <stdlib.h>
36#include <netdb.h>
37
38void
39freeaddrinfo(struct addrinfo *ai)
40{
41 struct addrinfo *p;
42
43 do {
44 p = ai;
45 ai = ai->ai_next;
46 if (p->ai_canonname)
47 free(p->ai_canonname);
48 free((void *)p);
49 } while (ai);
50}
diff --git a/src/lib/libc/net/gai_strerror.3 b/src/lib/libc/net/gai_strerror.3
new file mode 100644
index 0000000000..d0a636ee03
--- /dev/null
+++ b/src/lib/libc/net/gai_strerror.3
@@ -0,0 +1,93 @@
1.\" $OpenBSD: gai_strerror.3,v 1.5 2005/01/06 03:50:46 itojun Exp $
2.\" $KAME: gai_strerror.3,v 1.1 2005/01/05 03:04:47 itojun Exp $
3.\"
4.\" Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
5.\" Copyright (C) 2000, 2001 Internet Software Consortium.
6.\"
7.\" Permission to use, copy, modify, and distribute this software for any
8.\" purpose with or without fee is hereby granted, provided that the above
9.\" copyright notice and this permission notice appear in all copies.
10.\"
11.\" THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12.\" REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13.\" AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14.\" INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15.\" LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16.\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17.\" PERFORMANCE OF THIS SOFTWARE.
18.\"
19.Dd December 20, 2004
20.Dt GAI_STRERROR 3
21.Os
22.Sh NAME
23.Nm gai_strerror
24.Nd get error message string from EAI_xxx error code
25.Sh SYNOPSIS
26.Fd #include <sys/types.h>
27.Fd #include <sys/socket.h>
28.Fd #include <netdb.h>
29.Ft "const char *"
30.Fn gai_strerror "int ecode"
31.Sh DESCRIPTION
32The
33.Fn gai_strerror
34function returns an error message string corresponding to the error code
35returned by
36.Xr getaddrinfo 3
37or
38.Xr getnameinfo 3 .
39.Pp
40The following error codes and their meaning are defined in
41.Aq Pa netdb.h :
42.Pp
43.Bl -tag -width "EAI_ADDRFAMILYXX" -offset indent -compact
44.It Dv EAI_ADDRFAMILY
45address family for
46.Fa hostname
47not supported
48.It Dv EAI_AGAIN
49temporary failure in name resolution
50.It Dv EAI_BADFLAGS
51invalid value for
52.Fa ai_flags
53.It Dv EAI_BADHINTS
54invalid value for
55.Fa hints
56.It Dv EAI_FAIL
57non-recoverable failure in name resolution
58.It Dv EAI_FAMILY
59.Fa ai_family
60not supported.
61.It Dv EAI_MEMORY
62memory allocation failure
63.It Dv EAI_NODATA
64no address associated with
65.Fa hostname
66.It Dv EAI_NONAME
67.Fa hostname
68or
69.Fa servname
70not provided, or not known
71.It Dv EAI_PROTOCOL
72resolved protocol is unknown
73.It Dv EAI_SERVICE
74.Fa servname
75not supported for
76.Fa ai_socktype
77.It Dv EAI_SOCKTYPE
78.Fa ai_socktype
79not supported
80.It Dv EAI_SYSTEM
81system error returned in
82.Va errno
83.El
84.Sh RETURN VALUES
85.Fn gai_strerror
86returns a pointer to the error message string corresponding to
87.Fa ecode .
88If
89.Fa ecode
90is out of range, an implementation-specific error message string is returned.
91.Sh SEE ALSO
92.Xr getaddrinfo 3 ,
93.Xr getnameinfo 3
diff --git a/src/lib/libc/net/gai_strerror.c b/src/lib/libc/net/gai_strerror.c
new file mode 100644
index 0000000000..767bc2f7e8
--- /dev/null
+++ b/src/lib/libc/net/gai_strerror.c
@@ -0,0 +1,76 @@
1/* $OpenBSD: gai_strerror.c,v 1.6 2004/12/20 22:35:32 millert 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
41const char *
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..12a0d8ce12
--- /dev/null
+++ b/src/lib/libc/net/getaddrinfo.3
@@ -0,0 +1,445 @@
1.\" $OpenBSD: getaddrinfo.3,v 1.43 2005/11/15 19:35:31 otto Exp $
2.\" $KAME: getaddrinfo.3,v 1.36 2005/01/05 03:23:05 itojun Exp $
3.\"
4.\" Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
5.\" Copyright (C) 2000, 2001 Internet Software Consortium.
6.\"
7.\" Permission to use, copy, modify, and distribute this software for any
8.\" purpose with or without fee is hereby granted, provided that the above
9.\" copyright notice and this permission notice appear in all copies.
10.\"
11.\" THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12.\" REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13.\" AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14.\" INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15.\" LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16.\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17.\" PERFORMANCE OF THIS SOFTWARE.
18.\"
19.Dd December 20, 2004
20.Dt GETADDRINFO 3
21.Os
22.Sh NAME
23.Nm getaddrinfo ,
24.Nm freeaddrinfo
25.Nd host and service name to socket address structure
26.Sh SYNOPSIS
27.Fd #include <sys/types.h>
28.Fd #include <sys/socket.h>
29.Fd #include <netdb.h>
30.Ft int
31.Fn getaddrinfo "const char *hostname" "const char *servname" \
32 "const struct addrinfo *hints" "struct addrinfo **res"
33.Ft void
34.Fn freeaddrinfo "struct addrinfo *ai"
35.Sh DESCRIPTION
36The
37.Fn getaddrinfo
38function is used to get a list of
39.Tn IP
40addresses and port numbers for host
41.Fa hostname
42and service
43.Fa servname .
44It is a replacement for and provides more flexibility than the
45.Xr gethostbyname 3
46and
47.Xr getservbyname 3
48functions.
49.Pp
50The
51.Fa hostname
52and
53.Fa servname
54arguments are either pointers to NUL-terminated strings or the null pointer.
55An acceptable value for
56.Fa hostname
57is either a valid host name or a numeric host address string consisting
58of a dotted decimal IPv4 address or an IPv6 address.
59The
60.Fa servname
61is either a decimal port number or a service name listed in
62.Xr services 5 .
63At least one of
64.Fa hostname
65and
66.Fa servname
67must be non-null.
68.Pp
69.Fa hints
70is an optional pointer to a
71.Li struct addrinfo ,
72as defined by
73.Aq Pa netdb.h :
74.Bd -literal
75struct addrinfo {
76 int ai_flags; /* input flags */
77 int ai_family; /* protocol family for socket */
78 int ai_socktype; /* socket type */
79 int ai_protocol; /* protocol for socket */
80 socklen_t ai_addrlen; /* length of socket-address */
81 struct sockaddr *ai_addr; /* socket-address for socket */
82 char *ai_canonname; /* canonical name for service location */
83 struct addrinfo *ai_next; /* pointer to next in list */
84};
85.Ed
86.Pp
87This structure can be used to provide hints concerning the type of socket
88that the caller supports or wishes to use.
89The caller can supply the following structure elements in
90.Fa hints :
91.Bl -tag -width "ai_socktypeXX"
92.It Fa ai_family
93The protocol family that should be used.
94When
95.Fa ai_family
96is set to
97.Dv PF_UNSPEC ,
98it means the caller will accept any protocol family supported by the
99operating system.
100.It Fa ai_socktype
101Denotes the type of socket that is wanted:
102.Dv SOCK_STREAM ,
103.Dv SOCK_DGRAM ,
104or
105.Dv SOCK_RAW .
106When
107.Fa ai_socktype
108is zero the caller will accept any socket type.
109.It Fa ai_protocol
110Indicates which transport protocol is desired,
111.Dv IPPROTO_UDP
112or
113.Dv IPPROTO_TCP .
114If
115.Fa ai_protocol
116is zero the caller will accept any protocol.
117.It Fa ai_flags
118.Fa ai_flags
119is formed by
120.Tn OR Ns 'ing
121the following values:
122.Bl -tag -width "AI_CANONNAMEXX"
123.It Dv AI_CANONNAME
124If the
125.Dv AI_CANONNAME
126bit is set, a successful call to
127.Fn getaddrinfo
128will return a NUL-terminated string containing the canonical name
129of the specified hostname in the
130.Fa ai_canonname
131element of the first
132.Li addrinfo
133structure returned.
134.It Dv AI_NUMERICHOST
135If the
136.Dv AI_NUMERICHOST
137bit is set, it indicates that
138.Fa hostname
139should be treated as a numeric string defining an IPv4 or IPv6 address
140and no name resolution should be attempted.
141.It Dv AI_PASSIVE
142If the
143.Dv AI_PASSIVE
144bit is set it indicates that the returned socket address structure
145is intended for use in a call to
146.Xr bind 2 .
147In this case, if the
148.Fa hostname
149argument is the null pointer, then the IP address portion of the
150socket address structure will be set to
151.Dv INADDR_ANY
152for an IPv4 address or
153.Dv IN6ADDR_ANY_INIT
154for an IPv6 address.
155.Pp
156If the
157.Dv AI_PASSIVE
158bit is not set, the returned socket address structure will be ready
159for use in a call to
160.Xr connect 2
161for a connection-oriented protocol or
162.Xr connect 2 ,
163.Xr sendto 2 ,
164or
165.Xr sendmsg 2
166if a connectionless protocol was chosen.
167The
168.Tn IP
169address portion of the socket address structure will be set to the
170loopback address if
171.Fa hostname
172is the null pointer and
173.Dv AI_PASSIVE
174is not set.
175.El
176.El
177.Pp
178All other elements of the
179.Li addrinfo
180structure passed via
181.Fa hints
182must be zero or the null pointer.
183.Pp
184If
185.Fa hints
186is the null pointer,
187.Fn getaddrinfo
188behaves as if the caller provided a
189.Li struct addrinfo
190with
191.Fa ai_family
192set to
193.Dv PF_UNSPEC
194and all other elements set to zero or
195.Dv NULL .
196.Pp
197After a successful call to
198.Fn getaddrinfo ,
199.Fa *res
200is a pointer to a linked list of one or more
201.Li addrinfo
202structures.
203The list can be traversed by following the
204.Fa ai_next
205pointer in each
206.Li addrinfo
207structure until a null pointer is encountered.
208The three members
209.Fa ai_family ,
210.Fa ai_socktype ,
211and
212.Fa ai_protocol
213in each returned
214.Li addrinfo
215structure are suitable for a call to
216.Xr socket 2 .
217For each
218.Li addrinfo
219structure in the list, the
220.Fa ai_addr
221member points to a filled-in socket address structure of length
222.Fa ai_addrlen .
223.Pp
224This implementation of
225.Fn getaddrinfo
226allows numeric IPv6 address notation with scope identifier,
227as documented in chapter 11 of draft-ietf-ipv6-scoping-arch-02.txt.
228By appending the percent character and scope identifier to addresses,
229one can fill the
230.Li sin6_scope_id
231field for addresses.
232This would make management of scoped addresses easier
233and allows cut-and-paste input of scoped addresses.
234.Pp
235At this moment the code supports only link-local addresses with the format.
236The scope identifier is hardcoded to the name of the hardware interface
237associated
238with the link
239.Po
240such as
241.Li ne0
242.Pc .
243An example is
244.Dq Li fe80::1%ne0 ,
245which means
246.Do
247.Li fe80::1
248on the link associated with the
249.Li ne0
250interface
251.Dc .
252.Pp
253The current implementation assumes a one-to-one relationship between
254the interface and link, which is not necessarily true from the specification.
255.Pp
256All of the information returned by
257.Fn getaddrinfo
258is dynamically allocated: the
259.Li addrinfo
260structures themselves as well as the socket address structures and
261the canonical host name strings included in the
262.Li addrinfo
263structures.
264.Pp
265Memory allocated for the dynamically allocated structures created by
266a successful call to
267.Fn getaddrinfo
268is released by the
269.Fn freeaddrinfo
270function.
271The
272.Fa ai
273pointer should be a
274.Li addrinfo
275structure created by a call to
276.Fn getaddrinfo .
277.Sh RETURN VALUES
278.Fn getaddrinfo
279returns zero on success or one of the error codes listed in
280.Xr gai_strerror 3
281if an error occurs.
282If an error occurs, no memory is allocated by
283.Fn getaddrinfo ,
284therefore it is not necessary to release the
285.Li addrinfo
286structure(s).
287.Sh EXAMPLES
288The following code tries to connect to
289.Dq Li www.kame.net
290service
291.Dq Li www
292via a stream socket.
293It loops through all the addresses available, regardless of address family.
294If the destination resolves to an IPv4 address, it will use an
295.Dv AF_INET
296socket.
297Similarly, if it resolves to IPv6, an
298.Dv AF_INET6
299socket is used.
300Observe that there is no hardcoded reference to a particular address family.
301The code works even if
302.Fn getaddrinfo
303returns addresses that are not IPv4/v6.
304.Bd -literal -offset indent
305struct addrinfo hints, *res, *res0;
306int error;
307int save_errno;
308int s;
309const char *cause = NULL;
310
311memset(&hints, 0, sizeof(hints));
312hints.ai_family = PF_UNSPEC;
313hints.ai_socktype = SOCK_STREAM;
314error = getaddrinfo("www.kame.net", "www", &hints, &res0);
315if (error) {
316 errx(1, "%s", gai_strerror(error));
317 /*NOTREACHED*/
318}
319s = -1;
320for (res = res0; res; res = res->ai_next) {
321 s = socket(res->ai_family, res->ai_socktype,
322 res->ai_protocol);
323 if (s < 0) {
324 cause = "socket";
325 continue;
326 }
327
328 if (connect(s, res->ai_addr, res->ai_addrlen) < 0) {
329 cause = "connect";
330 save_errno = errno;
331 close(s);
332 errno = save_errno;
333 s = -1;
334 continue;
335 }
336
337 break; /* okay we got one */
338}
339if (s < 0) {
340 err(1, "%s", cause);
341 /*NOTREACHED*/
342}
343freeaddrinfo(res0);
344.Ed
345.Pp
346The following example tries to open a wildcard listening socket onto service
347.Dq Li www ,
348for all the address families available.
349.Bd -literal -offset indent
350struct addrinfo hints, *res, *res0;
351int error;
352int save_errno;
353int s[MAXSOCK];
354int nsock;
355const char *cause = NULL;
356
357memset(&hints, 0, sizeof(hints));
358hints.ai_family = PF_UNSPEC;
359hints.ai_socktype = SOCK_STREAM;
360hints.ai_flags = AI_PASSIVE;
361error = getaddrinfo(NULL, "www", &hints, &res0);
362if (error) {
363 errx(1, "%s", gai_strerror(error));
364 /*NOTREACHED*/
365}
366nsock = 0;
367for (res = res0; res && nsock < MAXSOCK; res = res->ai_next) {
368 s[nsock] = socket(res->ai_family, res->ai_socktype,
369 res->ai_protocol);
370 if (s[nsock] < 0) {
371 cause = "socket";
372 continue;
373 }
374
375 if (bind(s[nsock], res->ai_addr, res->ai_addrlen) < 0) {
376 cause = "bind";
377 save_errno = errno;
378 close(s[nsock]);
379 errno = save_errno;
380 continue;
381 }
382 (void) listen(s[nsock], 5);
383
384 nsock++;
385}
386if (nsock == 0) {
387 err(1, "%s", cause);
388 /*NOTREACHED*/
389}
390freeaddrinfo(res0);
391.Ed
392.Sh SEE ALSO
393.Xr bind 2 ,
394.Xr connect 2 ,
395.Xr send 2 ,
396.Xr socket 2 ,
397.Xr gai_strerror 3 ,
398.Xr gethostbyname 3 ,
399.Xr getnameinfo 3 ,
400.Xr getservbyname 3 ,
401.Xr resolver 3 ,
402.Xr hosts 5 ,
403.Xr resolv.conf 5 ,
404.Xr services 5 ,
405.Xr hostname 7 ,
406.Xr named 8
407.Rs
408.%A R. Gilligan
409.%A S. Thomson
410.%A J. Bound
411.%A J. McCann
412.%A W. Stevens
413.%T Basic Socket Interface Extensions for IPv6
414.%R RFC 3493
415.%D February 2003
416.Re
417.Rs
418.%A S. Deering
419.%A B. Haberman
420.%A T. Jinmei
421.%A E. Nordmark
422.%A B. Zill
423.%T "IPv6 Scoped Address Architecture"
424.%R internet draft
425.%N draft-ietf-ipv6-scoping-arch-02.txt
426.%O work in progress material
427.Re
428.Rs
429.%A Craig Metz
430.%T Protocol Independence Using the Sockets API
431.%B "Proceedings of the Freenix Track: 2000 USENIX Annual Technical Conference"
432.%D June 2000
433.Re
434.Sh STANDARDS
435The
436.Fn getaddrinfo
437function is defined by the
438.St -p1003.1g-2000
439draft specification and documented in
440.Dv "RFC 3493" ,
441.Dq Basic Socket Interface Extensions for IPv6 .
442.Sh BUGS
443The implementation of
444.Fn getaddrinfo
445is not thread-safe.
diff --git a/src/lib/libc/net/getaddrinfo.c b/src/lib/libc/net/getaddrinfo.c
new file mode 100644
index 0000000000..06ab8f2095
--- /dev/null
+++ b/src/lib/libc/net/getaddrinfo.c
@@ -0,0 +1,1781 @@
1/* $OpenBSD: getaddrinfo.c,v 1.56 2006/04/18 02:57:10 ray 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 <stdint.h>
95#include <stdlib.h>
96#include <stddef.h>
97#include <ctype.h>
98#include <unistd.h>
99#include <stdio.h>
100#include <errno.h>
101
102#include <syslog.h>
103#include <stdarg.h>
104
105#ifdef YP
106#include <rpc/rpc.h>
107#include <rpcsvc/yp.h>
108#include <rpcsvc/ypclnt.h>
109#include "ypinternal.h"
110#endif
111
112#include "thread_private.h"
113
114#define SUCCESS 0
115#define ANY 0
116#define YES 1
117#define NO 0
118
119static const char in_addrany[] = { 0, 0, 0, 0 };
120static const char in6_addrany[] = {
121 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
122};
123static const char in_loopback[] = { 127, 0, 0, 1 };
124static const char in6_loopback[] = {
125 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
126};
127
128static const struct afd {
129 int a_af;
130 int a_addrlen;
131 int a_socklen;
132 int a_off;
133 const char *a_addrany;
134 const char *a_loopback;
135 int a_scoped;
136} afdl [] = {
137#ifdef INET6
138 {PF_INET6, sizeof(struct in6_addr),
139 sizeof(struct sockaddr_in6),
140 offsetof(struct sockaddr_in6, sin6_addr),
141 in6_addrany, in6_loopback, 1},
142#endif
143 {PF_INET, sizeof(struct in_addr),
144 sizeof(struct sockaddr_in),
145 offsetof(struct sockaddr_in, sin_addr),
146 in_addrany, in_loopback, 0},
147 {0, 0, 0, 0, NULL, NULL, 0},
148};
149
150struct explore {
151 int e_af;
152 int e_socktype;
153 int e_protocol;
154 const char *e_protostr;
155 int e_wild;
156#define WILD_AF(ex) ((ex)->e_wild & 0x01)
157#define WILD_SOCKTYPE(ex) ((ex)->e_wild & 0x02)
158#define WILD_PROTOCOL(ex) ((ex)->e_wild & 0x04)
159};
160
161static const struct explore explore[] = {
162#if 0
163 { PF_LOCAL, 0, ANY, ANY, NULL, 0x01 },
164#endif
165#ifdef INET6
166 { PF_INET6, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
167 { PF_INET6, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
168 { PF_INET6, SOCK_RAW, ANY, NULL, 0x05 },
169#endif
170 { PF_INET, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
171 { PF_INET, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
172 { PF_INET, SOCK_RAW, ANY, NULL, 0x05 },
173 { PF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
174 { PF_UNSPEC, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
175 { PF_UNSPEC, SOCK_RAW, ANY, NULL, 0x05 },
176 { -1, 0, 0, NULL, 0 },
177};
178
179#ifdef INET6
180#define PTON_MAX 16
181#else
182#define PTON_MAX 4
183#endif
184
185#define MAXPACKET (64*1024)
186
187typedef union {
188 HEADER hdr;
189 u_char buf[MAXPACKET];
190} querybuf;
191
192struct res_target {
193 struct res_target *next;
194 const char *name; /* domain name */
195 int qclass, qtype; /* class and type of query */
196 u_char *answer; /* buffer to put answer */
197 int anslen; /* size of answer buffer */
198 int n; /* result length */
199};
200
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#ifdef INET6
217static int ip6_str2scopeid(char *, struct sockaddr_in6 *, u_int32_t *);
218#endif
219
220static void _sethtent(void);
221static void _endhtent(void);
222static struct addrinfo * _gethtent(const char *, const struct addrinfo *);
223static struct addrinfo *_files_getaddrinfo(const char *,
224 const struct addrinfo *);
225
226#ifdef YP
227static struct addrinfo *_yphostent(char *, const struct addrinfo *);
228static struct addrinfo *_yp_getaddrinfo(const char *,
229 const struct addrinfo *);
230#endif
231
232static struct addrinfo *getanswer(const querybuf *, int, const char *, int,
233 const struct addrinfo *);
234static int res_queryN(const char *, struct res_target *);
235static int res_searchN(const char *, struct res_target *);
236static int res_querydomainN(const char *, const char *, struct res_target *);
237static struct addrinfo *_dns_getaddrinfo(const char *, const struct addrinfo *);
238
239
240/* XXX macros that make external reference is BAD. */
241
242#define GET_AI(ai, afd, addr) \
243do { \
244 /* external reference: pai, error, and label free */ \
245 (ai) = get_ai(pai, (afd), (addr)); \
246 if ((ai) == NULL) { \
247 error = EAI_MEMORY; \
248 goto free; \
249 } \
250} while (/*CONSTCOND*/0)
251
252#define GET_PORT(ai, serv) \
253do { \
254 /* external reference: error and label free */ \
255 error = get_port((ai), (serv), 0); \
256 if (error != 0) \
257 goto free; \
258} while (/*CONSTCOND*/0)
259
260#define GET_CANONNAME(ai, str) \
261do { \
262 /* external reference: pai, error and label free */ \
263 error = get_canonname(pai, (ai), (str)); \
264 if (error != 0) \
265 goto free; \
266} while (/*CONSTCOND*/0)
267
268#define ERR(err) \
269do { \
270 /* external reference: error, and label bad */ \
271 error = (err); \
272 goto bad; \
273 /*NOTREACHED*/ \
274} while (/*CONSTCOND*/0)
275
276#define MATCH_FAMILY(x, y, w) \
277 ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == PF_UNSPEC || (y) == PF_UNSPEC)))
278#define MATCH(x, y, w) \
279 ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == ANY || (y) == ANY)))
280
281int
282getaddrinfo(const char *hostname, const char *servname,
283 const struct addrinfo *hints, struct addrinfo **res)
284{
285 struct addrinfo sentinel;
286 struct addrinfo *cur;
287 int error = 0;
288 struct addrinfo ai;
289 struct addrinfo ai0;
290 struct addrinfo *pai;
291 const struct explore *ex;
292
293 memset(&sentinel, 0, sizeof(sentinel));
294 cur = &sentinel;
295 pai = &ai;
296 pai->ai_flags = 0;
297 pai->ai_family = PF_UNSPEC;
298 pai->ai_socktype = ANY;
299 pai->ai_protocol = ANY;
300 pai->ai_addrlen = 0;
301 pai->ai_canonname = NULL;
302 pai->ai_addr = NULL;
303 pai->ai_next = NULL;
304
305 if (hostname == NULL && servname == NULL)
306 return EAI_NONAME;
307 if (hints) {
308 /* error check for hints */
309 if (hints->ai_addrlen || hints->ai_canonname ||
310 hints->ai_addr || hints->ai_next)
311 ERR(EAI_BADHINTS); /* xxx */
312 if (hints->ai_flags & ~AI_MASK)
313 ERR(EAI_BADFLAGS);
314 switch (hints->ai_family) {
315 case PF_UNSPEC:
316 case PF_INET:
317#ifdef INET6
318 case PF_INET6:
319#endif
320 break;
321 default:
322 ERR(EAI_FAMILY);
323 }
324 memcpy(pai, hints, sizeof(*pai));
325
326 /*
327 * if both socktype/protocol are specified, check if they
328 * are meaningful combination.
329 */
330 if (pai->ai_socktype != ANY && pai->ai_protocol != ANY) {
331 for (ex = explore; ex->e_af >= 0; ex++) {
332 if (pai->ai_family != ex->e_af)
333 continue;
334 if (ex->e_socktype == ANY)
335 continue;
336 if (ex->e_protocol == ANY)
337 continue;
338 if (pai->ai_socktype == ex->e_socktype
339 && pai->ai_protocol != ex->e_protocol) {
340 ERR(EAI_BADHINTS);
341 }
342 }
343 }
344 }
345
346 /*
347 * check for special cases. (1) numeric servname is disallowed if
348 * socktype/protocol are left unspecified. (2) servname is disallowed
349 * for raw and other inet{,6} sockets.
350 */
351 if (MATCH_FAMILY(pai->ai_family, PF_INET, 1)
352#ifdef PF_INET6
353 || MATCH_FAMILY(pai->ai_family, PF_INET6, 1)
354#endif
355 ) {
356 ai0 = *pai; /* backup *pai */
357
358 if (pai->ai_family == PF_UNSPEC) {
359#ifdef PF_INET6
360 pai->ai_family = PF_INET6;
361#else
362 pai->ai_family = PF_INET;
363#endif
364 }
365 error = get_portmatch(pai, servname);
366 if (error)
367 ERR(error);
368
369 *pai = ai0;
370 }
371
372 ai0 = *pai;
373
374 /* NULL hostname, or numeric hostname */
375 for (ex = explore; ex->e_af >= 0; ex++) {
376 *pai = ai0;
377
378 /* PF_UNSPEC entries are prepared for DNS queries only */
379 if (ex->e_af == PF_UNSPEC)
380 continue;
381
382 if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex)))
383 continue;
384 if (!MATCH(pai->ai_socktype, ex->e_socktype, WILD_SOCKTYPE(ex)))
385 continue;
386 if (!MATCH(pai->ai_protocol, ex->e_protocol, WILD_PROTOCOL(ex)))
387 continue;
388
389 if (pai->ai_family == PF_UNSPEC)
390 pai->ai_family = ex->e_af;
391 if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
392 pai->ai_socktype = ex->e_socktype;
393 if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
394 pai->ai_protocol = ex->e_protocol;
395
396 if (hostname == NULL)
397 error = explore_null(pai, servname, &cur->ai_next);
398 else
399 error = explore_numeric_scope(pai, hostname, servname,
400 &cur->ai_next);
401
402 if (error)
403 goto free;
404
405 while (cur && cur->ai_next)
406 cur = cur->ai_next;
407 }
408
409 /*
410 * XXX
411 * If numeric representation of AF1 can be interpreted as FQDN
412 * representation of AF2, we need to think again about the code below.
413 */
414 if (sentinel.ai_next)
415 goto good;
416
417 if (hostname == NULL)
418 ERR(EAI_NODATA);
419 if (pai->ai_flags & AI_NUMERICHOST)
420 ERR(EAI_NONAME);
421
422 /*
423 * hostname as alphabetical name.
424 * we would like to prefer AF_INET6 than AF_INET, so we'll make a
425 * outer loop by AFs.
426 */
427 for (ex = explore; ex->e_af >= 0; ex++) {
428 *pai = ai0;
429
430 /* require exact match for family field */
431 if (pai->ai_family != ex->e_af)
432 continue;
433
434 if (!MATCH(pai->ai_socktype, ex->e_socktype,
435 WILD_SOCKTYPE(ex))) {
436 continue;
437 }
438 if (!MATCH(pai->ai_protocol, ex->e_protocol,
439 WILD_PROTOCOL(ex))) {
440 continue;
441 }
442
443 if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
444 pai->ai_socktype = ex->e_socktype;
445 if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
446 pai->ai_protocol = ex->e_protocol;
447
448 error = explore_fqdn(pai, hostname, servname,
449 &cur->ai_next);
450
451 while (cur && cur->ai_next)
452 cur = cur->ai_next;
453 }
454
455 /* XXX */
456 if (sentinel.ai_next)
457 error = 0;
458
459 if (error)
460 goto free;
461 if (error == 0) {
462 if (sentinel.ai_next) {
463 good:
464 *res = sentinel.ai_next;
465 return SUCCESS;
466 } else
467 error = EAI_FAIL;
468 }
469 free:
470 bad:
471 if (sentinel.ai_next)
472 freeaddrinfo(sentinel.ai_next);
473 *res = NULL;
474 return error;
475}
476
477/*
478 * FQDN hostname, DNS lookup
479 */
480
481static int
482explore_fqdn(const struct addrinfo *pai, const char *hostname,
483 const char *servname, struct addrinfo **res)
484{
485 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
486 struct addrinfo *result;
487 struct addrinfo *cur;
488 int error = 0;
489 char lookups[MAXDNSLUS];
490 int i;
491 _THREAD_PRIVATE_MUTEX(_explore_mutex);
492
493 result = NULL;
494
495 /*
496 * if the servname does not match socktype/protocol, ignore it.
497 */
498 if (get_portmatch(pai, servname) != 0) {
499 return 0;
500 }
501
502 if (_res_init(0) == -1)
503 strlcpy(lookups, "f", sizeof lookups);
504 else {
505 bcopy(_resp->lookups, lookups, sizeof lookups);
506 if (lookups[0] == '\0')
507 strlcpy(lookups, "bf", sizeof lookups);
508 }
509
510 /*
511 * The yp/dns/files getaddrinfo functions are not thread safe.
512 * Protect them with a mutex.
513 */
514 _THREAD_PRIVATE_MUTEX_LOCK(_explore_mutex);
515 for (i = 0; i < MAXDNSLUS && result == NULL && lookups[i]; i++) {
516 switch (lookups[i]) {
517#ifdef YP
518 case 'y':
519 result = _yp_getaddrinfo(hostname, pai);
520 break;
521#endif
522 case 'b':
523 result = _dns_getaddrinfo(hostname, pai);
524 break;
525 case 'f':
526 result = _files_getaddrinfo(hostname, pai);
527 break;
528 }
529 }
530 _THREAD_PRIVATE_MUTEX_UNLOCK(_explore_mutex);
531 if (result) {
532 for (cur = result; cur; cur = cur->ai_next) {
533 GET_PORT(cur, servname);
534 /* canonname should be filled already */
535 }
536 *res = result;
537 return 0;
538 } else {
539 /* translate error code */
540 switch (h_errno) {
541 case NETDB_SUCCESS:
542 error = EAI_FAIL; /*XXX strange */
543 break;
544 case HOST_NOT_FOUND:
545 error = EAI_NODATA;
546 break;
547 case TRY_AGAIN:
548 error = EAI_AGAIN;
549 break;
550 case NO_RECOVERY:
551 error = EAI_FAIL;
552 break;
553 case NO_DATA:
554#if NO_ADDRESS != NO_DATA
555 case NO_ADDRESS:
556#endif
557 error = EAI_NODATA;
558 break;
559 default: /* unknown ones */
560 error = EAI_FAIL;
561 break;
562 }
563 }
564
565free:
566 if (result)
567 freeaddrinfo(result);
568 return error;
569}
570
571/*
572 * hostname == NULL.
573 * passive socket -> anyaddr (0.0.0.0 or ::)
574 * non-passive socket -> localhost (127.0.0.1 or ::1)
575 */
576static int
577explore_null(const struct addrinfo *pai, const char *servname,
578 struct addrinfo **res)
579{
580 int s;
581 const struct afd *afd;
582 struct addrinfo *cur;
583 struct addrinfo sentinel;
584 int error;
585
586 *res = NULL;
587 sentinel.ai_next = NULL;
588 cur = &sentinel;
589
590 /*
591 * filter out AFs that are not supported by the kernel
592 * XXX errno?
593 */
594 s = socket(pai->ai_family, SOCK_DGRAM, 0);
595 if (s < 0) {
596 if (errno != EMFILE)
597 return 0;
598 } else
599 close(s);
600
601 /*
602 * if the servname does not match socktype/protocol, ignore it.
603 */
604 if (get_portmatch(pai, servname) != 0)
605 return 0;
606
607 afd = find_afd(pai->ai_family);
608 if (afd == NULL)
609 return 0;
610
611 if (pai->ai_flags & AI_PASSIVE) {
612 GET_AI(cur->ai_next, afd, afd->a_addrany);
613 /* xxx meaningless?
614 * GET_CANONNAME(cur->ai_next, "anyaddr");
615 */
616 GET_PORT(cur->ai_next, servname);
617 } else {
618 GET_AI(cur->ai_next, afd, afd->a_loopback);
619 /* xxx meaningless?
620 * GET_CANONNAME(cur->ai_next, "localhost");
621 */
622 GET_PORT(cur->ai_next, servname);
623 }
624 cur = cur->ai_next;
625
626 *res = sentinel.ai_next;
627 return 0;
628
629free:
630 if (sentinel.ai_next)
631 freeaddrinfo(sentinel.ai_next);
632 return error;
633}
634
635/*
636 * numeric hostname
637 */
638static int
639explore_numeric(const struct addrinfo *pai, const char *hostname,
640 const char *servname, struct addrinfo **res, const char *canonname)
641{
642 const struct afd *afd;
643 struct addrinfo *cur;
644 struct addrinfo sentinel;
645 int error;
646 char pton[PTON_MAX];
647
648 *res = NULL;
649 sentinel.ai_next = NULL;
650 cur = &sentinel;
651
652 /*
653 * if the servname does not match socktype/protocol, ignore it.
654 */
655 if (get_portmatch(pai, servname) != 0)
656 return 0;
657
658 afd = find_afd(pai->ai_family);
659 if (afd == NULL)
660 return 0;
661
662 switch (afd->a_af) {
663#if 0 /*X/Open spec*/
664 case AF_INET:
665 if (inet_aton(hostname, (struct in_addr *)pton) == 1) {
666 if (pai->ai_family == afd->a_af ||
667 pai->ai_family == PF_UNSPEC /*?*/) {
668 GET_AI(cur->ai_next, afd, pton);
669 GET_PORT(cur->ai_next, servname);
670 if ((pai->ai_flags & AI_CANONNAME)) {
671 /*
672 * Set the numeric address itself as
673 * the canonical name, based on a
674 * clarification in rfc2553bis-03.
675 */
676 GET_CANONNAME(cur->ai_next, canonname);
677 }
678 while (cur && cur->ai_next)
679 cur = cur->ai_next;
680 } else
681 ERR(EAI_FAMILY); /*xxx*/
682 }
683 break;
684#endif
685 default:
686 if (inet_pton(afd->a_af, hostname, pton) == 1) {
687 if (pai->ai_family == afd->a_af ||
688 pai->ai_family == PF_UNSPEC /*?*/) {
689 GET_AI(cur->ai_next, afd, pton);
690 GET_PORT(cur->ai_next, servname);
691 if ((pai->ai_flags & AI_CANONNAME)) {
692 /*
693 * Set the numeric address itself as
694 * the canonical name, based on a
695 * clarification in rfc2553bis-03.
696 */
697 GET_CANONNAME(cur->ai_next, canonname);
698 }
699 while (cur && cur->ai_next)
700 cur = cur->ai_next;
701 } else
702 ERR(EAI_FAMILY); /*xxx*/
703 }
704 break;
705 }
706
707 *res = sentinel.ai_next;
708 return 0;
709
710free:
711bad:
712 if (sentinel.ai_next)
713 freeaddrinfo(sentinel.ai_next);
714 return error;
715}
716
717/*
718 * numeric hostname with scope
719 */
720static int
721explore_numeric_scope(const struct addrinfo *pai, const char *hostname,
722 const char *servname, struct addrinfo **res)
723{
724#if !defined(SCOPE_DELIMITER) || !defined(INET6)
725 return explore_numeric(pai, hostname, servname, res, hostname);
726#else
727 const struct afd *afd;
728 struct addrinfo *cur;
729 int error;
730 char *cp, *hostname2 = NULL, *scope, *addr;
731 struct sockaddr_in6 *sin6;
732
733 /*
734 * if the servname does not match socktype/protocol, ignore it.
735 */
736 if (get_portmatch(pai, servname) != 0)
737 return 0;
738
739 afd = find_afd(pai->ai_family);
740 if (afd == NULL)
741 return 0;
742
743 if (!afd->a_scoped)
744 return explore_numeric(pai, hostname, servname, res, hostname);
745
746 cp = strchr(hostname, SCOPE_DELIMITER);
747 if (cp == NULL)
748 return explore_numeric(pai, hostname, servname, res, hostname);
749
750 /*
751 * Handle special case of <scoped_address><delimiter><scope id>
752 */
753 hostname2 = strdup(hostname);
754 if (hostname2 == NULL)
755 return EAI_MEMORY;
756 /* terminate at the delimiter */
757 hostname2[cp - hostname] = '\0';
758 addr = hostname2;
759 scope = cp + 1;
760
761 error = explore_numeric(pai, addr, servname, res, hostname);
762 if (error == 0) {
763 u_int32_t scopeid;
764
765 for (cur = *res; cur; cur = cur->ai_next) {
766 if (cur->ai_family != AF_INET6)
767 continue;
768 sin6 = (struct sockaddr_in6 *)(void *)cur->ai_addr;
769 if (ip6_str2scopeid(scope, sin6, &scopeid) == -1) {
770 free(hostname2);
771 return(EAI_NODATA); /* XXX: is return OK? */
772 }
773 sin6->sin6_scope_id = scopeid;
774 }
775 }
776
777 free(hostname2);
778
779 return error;
780#endif
781}
782
783static int
784get_canonname(const struct addrinfo *pai, struct addrinfo *ai, const char *str)
785{
786 if ((pai->ai_flags & AI_CANONNAME) != 0) {
787 ai->ai_canonname = strdup(str);
788 if (ai->ai_canonname == NULL)
789 return EAI_MEMORY;
790 }
791 return 0;
792}
793
794static struct addrinfo *
795get_ai(const struct addrinfo *pai, const struct afd *afd, const char *addr)
796{
797 char *p;
798 struct addrinfo *ai;
799
800 ai = (struct addrinfo *)malloc(sizeof(struct addrinfo)
801 + (afd->a_socklen));
802 if (ai == NULL)
803 return NULL;
804
805 memcpy(ai, pai, sizeof(struct addrinfo));
806 ai->ai_addr = (struct sockaddr *)(void *)(ai + 1);
807 memset(ai->ai_addr, 0, (size_t)afd->a_socklen);
808 ai->ai_addr->sa_len = afd->a_socklen;
809 ai->ai_addrlen = afd->a_socklen;
810 ai->ai_addr->sa_family = ai->ai_family = afd->a_af;
811 p = (char *)(void *)(ai->ai_addr);
812 memcpy(p + afd->a_off, addr, (size_t)afd->a_addrlen);
813 return ai;
814}
815
816static int
817get_portmatch(const struct addrinfo *ai, const char *servname)
818{
819
820 /* get_port does not touch first argument. when matchonly == 1. */
821 /* LINTED const cast */
822 return get_port((struct addrinfo *)ai, servname, 1);
823}
824
825static int
826get_port(struct addrinfo *ai, const char *servname, int matchonly)
827{
828 const char *errstr, *proto;
829 struct servent *sp;
830 int port;
831 int allownumeric;
832 /* mutex is defined in getnameinfo.c */
833 extern void *__THREAD_NAME(serv_mutex);
834
835 if (servname == NULL)
836 return 0;
837 switch (ai->ai_family) {
838 case AF_INET:
839#ifdef AF_INET6
840 case AF_INET6:
841#endif
842 break;
843 default:
844 return 0;
845 }
846
847 switch (ai->ai_socktype) {
848 case SOCK_RAW:
849 return EAI_SERVICE;
850 case SOCK_DGRAM:
851 case SOCK_STREAM:
852 allownumeric = 1;
853 break;
854 case ANY:
855 allownumeric = 0;
856 break;
857 default:
858 return EAI_SOCKTYPE;
859 }
860
861 port = (int)strtonum(servname, 0, USHRT_MAX, &errstr);
862 if (!errstr) {
863 if (!allownumeric)
864 return EAI_SERVICE;
865 port = htons(port);
866 } else {
867 if (errno == ERANGE)
868 return EAI_SERVICE;
869 if (ai->ai_flags & AI_NUMERICSERV)
870 return EAI_NONAME;
871
872 switch (ai->ai_socktype) {
873 case SOCK_DGRAM:
874 proto = "udp";
875 break;
876 case SOCK_STREAM:
877 proto = "tcp";
878 break;
879 default:
880 proto = NULL;
881 break;
882 }
883
884 _THREAD_PRIVATE_MUTEX_LOCK(serv_mutex);
885 sp = getservbyname(servname, proto);
886 _THREAD_PRIVATE_MUTEX_UNLOCK(serv_mutex);
887 if (sp == NULL)
888 return EAI_SERVICE;
889 port = sp->s_port;
890 }
891
892 if (!matchonly) {
893 switch (ai->ai_family) {
894 case AF_INET:
895 ((struct sockaddr_in *)(void *)
896 ai->ai_addr)->sin_port = port;
897 break;
898#ifdef INET6
899 case AF_INET6:
900 ((struct sockaddr_in6 *)(void *)
901 ai->ai_addr)->sin6_port = port;
902 break;
903#endif
904 }
905 }
906
907 return 0;
908}
909
910static const struct afd *
911find_afd(int af)
912{
913 const struct afd *afd;
914
915 if (af == PF_UNSPEC)
916 return NULL;
917 for (afd = afdl; afd->a_af; afd++) {
918 if (afd->a_af == af)
919 return afd;
920 }
921 return NULL;
922}
923
924#ifdef INET6
925/* convert a string to a scope identifier. XXX: IPv6 specific */
926static int
927ip6_str2scopeid(char *scope, struct sockaddr_in6 *sin6, u_int32_t *scopeid)
928{
929 struct in6_addr *a6 = &sin6->sin6_addr;
930 const char *errstr;
931
932 /* empty scopeid portion is invalid */
933 if (*scope == '\0')
934 return -1;
935
936 if (IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6)) {
937 /*
938 * We currently assume a one-to-one mapping between links
939 * and interfaces, so we simply use interface indices for
940 * like-local scopes.
941 */
942 *scopeid = if_nametoindex(scope);
943 if (*scopeid == 0)
944 goto trynumeric;
945 return 0;
946 }
947
948 /* still unclear about literal, allow numeric only - placeholder */
949 if (IN6_IS_ADDR_SITELOCAL(a6) || IN6_IS_ADDR_MC_SITELOCAL(a6))
950 goto trynumeric;
951 if (IN6_IS_ADDR_MC_ORGLOCAL(a6))
952 goto trynumeric;
953 else
954 goto trynumeric; /* global */
955
956 /* try to convert to a numeric id as a last resort */
957 trynumeric:
958 *scopeid = (u_int32_t)strtonum(scope, 0, UINT32_MAX, &errstr);
959 if (errstr)
960 return (-1);
961 return (0);
962}
963#endif
964
965/* code duplicate with gethnamaddr.c */
966
967static const char AskedForGot[] =
968 "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
969static FILE *hostf = NULL;
970
971static struct addrinfo *
972getanswer(const querybuf *answer, int anslen, const char *qname, int qtype,
973 const struct addrinfo *pai)
974{
975 struct addrinfo sentinel, *cur;
976 struct addrinfo ai;
977 const struct afd *afd;
978 char *canonname;
979 const HEADER *hp;
980 const u_char *cp;
981 int n;
982 const u_char *eom;
983 char *bp, *ep;
984 int type, class, ancount, qdcount;
985 int haveanswer, had_error;
986 char tbuf[MAXDNAME];
987 int (*name_ok)(const char *);
988 char hostbuf[8*1024];
989
990 memset(&sentinel, 0, sizeof(sentinel));
991 cur = &sentinel;
992
993 canonname = NULL;
994 eom = answer->buf + anslen;
995 switch (qtype) {
996 case T_A:
997 case T_AAAA:
998 case T_ANY: /*use T_ANY only for T_A/T_AAAA lookup*/
999 name_ok = res_hnok;
1000 break;
1001 default:
1002 return (NULL); /* XXX should be abort() -- but that is illegal */
1003 }
1004 /*
1005 * find first satisfactory answer
1006 */
1007 hp = &answer->hdr;
1008 ancount = ntohs(hp->ancount);
1009 qdcount = ntohs(hp->qdcount);
1010 bp = hostbuf;
1011 ep = hostbuf + sizeof hostbuf;
1012 cp = answer->buf + HFIXEDSZ;
1013 if (qdcount != 1) {
1014 h_errno = NO_RECOVERY;
1015 return (NULL);
1016 }
1017 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
1018 if ((n < 0) || !(*name_ok)(bp)) {
1019 h_errno = NO_RECOVERY;
1020 return (NULL);
1021 }
1022 cp += n + QFIXEDSZ;
1023 if (qtype == T_A || qtype == T_AAAA || qtype == T_ANY) {
1024 /* res_send() has already verified that the query name is the
1025 * same as the one we sent; this just gets the expanded name
1026 * (i.e., with the succeeding search-domain tacked on).
1027 */
1028 n = strlen(bp) + 1; /* for the \0 */
1029 if (n >= MAXHOSTNAMELEN) {
1030 h_errno = NO_RECOVERY;
1031 return (NULL);
1032 }
1033 canonname = bp;
1034 bp += n;
1035 /* The qname can be abbreviated, but h_name is now absolute. */
1036 qname = canonname;
1037 }
1038 haveanswer = 0;
1039 had_error = 0;
1040 while (ancount-- > 0 && cp < eom && !had_error) {
1041 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
1042 if ((n < 0) || !(*name_ok)(bp)) {
1043 had_error++;
1044 continue;
1045 }
1046 cp += n; /* name */
1047 type = _getshort(cp);
1048 cp += INT16SZ; /* type */
1049 class = _getshort(cp);
1050 cp += INT16SZ + INT32SZ; /* class, TTL */
1051 n = _getshort(cp);
1052 cp += INT16SZ; /* len */
1053 if (class != C_IN) {
1054 /* XXX - debug? syslog? */
1055 cp += n;
1056 continue; /* XXX - had_error++ ? */
1057 }
1058 if ((qtype == T_A || qtype == T_AAAA || qtype == T_ANY) &&
1059 type == T_CNAME) {
1060 n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
1061 if ((n < 0) || !(*name_ok)(tbuf)) {
1062 had_error++;
1063 continue;
1064 }
1065 cp += n;
1066 /* Get canonical name. */
1067 n = strlen(tbuf) + 1; /* for the \0 */
1068 if (n > ep - bp || n >= MAXHOSTNAMELEN) {
1069 had_error++;
1070 continue;
1071 }
1072 strlcpy(bp, tbuf, ep - bp);
1073 canonname = bp;
1074 bp += n;
1075 continue;
1076 }
1077 if (qtype == T_ANY) {
1078 if (!(type == T_A || type == T_AAAA)) {
1079 cp += n;
1080 continue;
1081 }
1082 } else if (type != qtype) {
1083 if (type != T_KEY && type != T_SIG)
1084 syslog(LOG_NOTICE|LOG_AUTH,
1085 "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
1086 qname, p_class(C_IN), p_type(qtype),
1087 p_type(type));
1088 cp += n;
1089 continue; /* XXX - had_error++ ? */
1090 }
1091 switch (type) {
1092 case T_A:
1093 case T_AAAA:
1094 if (strcasecmp(canonname, bp) != 0) {
1095 syslog(LOG_NOTICE|LOG_AUTH,
1096 AskedForGot, canonname, bp);
1097 cp += n;
1098 continue; /* XXX - had_error++ ? */
1099 }
1100 if (type == T_A && n != INADDRSZ) {
1101 cp += n;
1102 continue;
1103 }
1104 if (type == T_AAAA && n != IN6ADDRSZ) {
1105 cp += n;
1106 continue;
1107 }
1108 if (type == T_AAAA) {
1109 struct in6_addr in6;
1110 memcpy(&in6, cp, IN6ADDRSZ);
1111 if (IN6_IS_ADDR_V4MAPPED(&in6)) {
1112 cp += n;
1113 continue;
1114 }
1115 }
1116 if (!haveanswer) {
1117 int nn;
1118
1119 canonname = bp;
1120 nn = strlen(bp) + 1; /* for the \0 */
1121 bp += nn;
1122 }
1123
1124 /* don't overwrite pai */
1125 ai = *pai;
1126 ai.ai_family = (type == T_A) ? AF_INET : AF_INET6;
1127 afd = find_afd(ai.ai_family);
1128 if (afd == NULL) {
1129 cp += n;
1130 continue;
1131 }
1132 cur->ai_next = get_ai(&ai, afd, (const char *)cp);
1133 if (cur->ai_next == NULL)
1134 had_error++;
1135 while (cur && cur->ai_next)
1136 cur = cur->ai_next;
1137 cp += n;
1138 break;
1139 default:
1140 abort(); /* XXX abort illegal in library */
1141 }
1142 if (!had_error)
1143 haveanswer++;
1144 }
1145 if (haveanswer) {
1146 if (!canonname)
1147 (void)get_canonname(pai, sentinel.ai_next, qname);
1148 else
1149 (void)get_canonname(pai, sentinel.ai_next, canonname);
1150 h_errno = NETDB_SUCCESS;
1151 return sentinel.ai_next;
1152 }
1153
1154 h_errno = NO_RECOVERY;
1155 return NULL;
1156}
1157
1158/*ARGSUSED*/
1159static struct addrinfo *
1160_dns_getaddrinfo(const char *name, const struct addrinfo *pai)
1161{
1162 struct addrinfo *ai;
1163 querybuf *buf, *buf2;
1164 struct addrinfo sentinel, *cur;
1165 struct res_target q, q2;
1166
1167 memset(&q, 0, sizeof(q));
1168 memset(&q2, 0, sizeof(q2));
1169 memset(&sentinel, 0, sizeof(sentinel));
1170 cur = &sentinel;
1171
1172 buf = malloc(sizeof(*buf));
1173 if (buf == NULL) {
1174 h_errno = NETDB_INTERNAL;
1175 return NULL;
1176 }
1177 buf2 = malloc(sizeof(*buf2));
1178 if (buf2 == NULL) {
1179 free(buf);
1180 h_errno = NETDB_INTERNAL;
1181 return NULL;
1182 }
1183
1184 switch (pai->ai_family) {
1185 case AF_UNSPEC:
1186 /* prefer IPv6 */
1187 q.qclass = C_IN;
1188 q.qtype = T_AAAA;
1189 q.answer = buf->buf;
1190 q.anslen = sizeof(buf->buf);
1191 q.next = &q2;
1192 q2.qclass = C_IN;
1193 q2.qtype = T_A;
1194 q2.answer = buf2->buf;
1195 q2.anslen = sizeof(buf2->buf);
1196 break;
1197 case AF_INET:
1198 q.qclass = C_IN;
1199 q.qtype = T_A;
1200 q.answer = buf->buf;
1201 q.anslen = sizeof(buf->buf);
1202 break;
1203 case AF_INET6:
1204 q.qclass = C_IN;
1205 q.qtype = T_AAAA;
1206 q.answer = buf->buf;
1207 q.anslen = sizeof(buf->buf);
1208 break;
1209 default:
1210 free(buf);
1211 free(buf2);
1212 return NULL;
1213 }
1214 if (res_searchN(name, &q) < 0) {
1215 free(buf);
1216 free(buf2);
1217 return NULL;
1218 }
1219 ai = getanswer(buf, q.n, q.name, q.qtype, pai);
1220 if (ai) {
1221 cur->ai_next = ai;
1222 while (cur && cur->ai_next)
1223 cur = cur->ai_next;
1224 }
1225 if (q.next) {
1226 ai = getanswer(buf2, q2.n, q2.name, q2.qtype, pai);
1227 if (ai)
1228 cur->ai_next = ai;
1229 }
1230 free(buf);
1231 free(buf2);
1232 return sentinel.ai_next;
1233}
1234
1235static FILE *hostf;
1236
1237static void
1238_sethtent(void)
1239{
1240 if (!hostf)
1241 hostf = fopen(_PATH_HOSTS, "r" );
1242 else
1243 rewind(hostf);
1244}
1245
1246static void
1247_endhtent(void)
1248{
1249 if (hostf) {
1250 (void) fclose(hostf);
1251 hostf = NULL;
1252 }
1253}
1254
1255static struct addrinfo *
1256_gethtent(const char *name, const struct addrinfo *pai)
1257{
1258 char *p;
1259 char *cp, *tname, *cname;
1260 struct addrinfo hints, *res0, *res;
1261 int error;
1262 const char *addr;
1263 char hostbuf[8*1024];
1264
1265 if (!hostf && !(hostf = fopen(_PATH_HOSTS, "r" )))
1266 return (NULL);
1267 again:
1268 if (!(p = fgets(hostbuf, sizeof hostbuf, hostf)))
1269 return (NULL);
1270 if (*p == '#')
1271 goto again;
1272 if (!(cp = strpbrk(p, "#\n")))
1273 goto again;
1274 *cp = '\0';
1275 if (!(cp = strpbrk(p, " \t")))
1276 goto again;
1277 *cp++ = '\0';
1278 addr = p;
1279 /* if this is not something we're looking for, skip it. */
1280 cname = NULL;
1281 while (cp && *cp) {
1282 if (*cp == ' ' || *cp == '\t') {
1283 cp++;
1284 continue;
1285 }
1286 if (!cname)
1287 cname = cp;
1288 tname = cp;
1289 if ((cp = strpbrk(cp, " \t")) != NULL)
1290 *cp++ = '\0';
1291 if (strcasecmp(name, tname) == 0)
1292 goto found;
1293 }
1294 goto again;
1295
1296found:
1297 hints = *pai;
1298 hints.ai_flags = AI_NUMERICHOST;
1299 error = getaddrinfo(addr, NULL, &hints, &res0);
1300 if (error)
1301 goto again;
1302 for (res = res0; res; res = res->ai_next) {
1303 /* cover it up */
1304 res->ai_flags = pai->ai_flags;
1305
1306 if (pai->ai_flags & AI_CANONNAME) {
1307 if (get_canonname(pai, res, cname) != 0) {
1308 freeaddrinfo(res0);
1309 goto again;
1310 }
1311 }
1312 }
1313 return res0;
1314}
1315
1316/*ARGSUSED*/
1317static struct addrinfo *
1318_files_getaddrinfo(const char *name, const struct addrinfo *pai)
1319{
1320 struct addrinfo sentinel, *cur;
1321 struct addrinfo *p;
1322
1323 memset(&sentinel, 0, sizeof(sentinel));
1324 cur = &sentinel;
1325
1326 _sethtent();
1327 while ((p = _gethtent(name, pai)) != NULL) {
1328 cur->ai_next = p;
1329 while (cur && cur->ai_next)
1330 cur = cur->ai_next;
1331 }
1332 _endhtent();
1333
1334 return sentinel.ai_next;
1335}
1336
1337#ifdef YP
1338static char *__ypdomain;
1339
1340/*ARGSUSED*/
1341static struct addrinfo *
1342_yphostent(char *line, const struct addrinfo *pai)
1343{
1344 struct addrinfo sentinel, *cur;
1345 struct addrinfo hints, *res, *res0;
1346 int error;
1347 char *p = line;
1348 const char *addr, *canonname;
1349 char *nextline;
1350 char *cp;
1351
1352 addr = canonname = NULL;
1353
1354 memset(&sentinel, 0, sizeof(sentinel));
1355 cur = &sentinel;
1356
1357nextline:
1358 /* terminate line */
1359 cp = strchr(p, '\n');
1360 if (cp) {
1361 *cp++ = '\0';
1362 nextline = cp;
1363 } else
1364 nextline = NULL;
1365
1366 cp = strpbrk(p, " \t");
1367 if (cp == NULL) {
1368 if (canonname == NULL)
1369 return (NULL);
1370 else
1371 goto done;
1372 }
1373 *cp++ = '\0';
1374
1375 addr = p;
1376
1377 while (cp && *cp) {
1378 if (*cp == ' ' || *cp == '\t') {
1379 cp++;
1380 continue;
1381 }
1382 if (!canonname)
1383 canonname = cp;
1384 if ((cp = strpbrk(cp, " \t")) != NULL)
1385 *cp++ = '\0';
1386 }
1387
1388 hints = *pai;
1389 hints.ai_flags = AI_NUMERICHOST;
1390 error = getaddrinfo(addr, NULL, &hints, &res0);
1391 if (error == 0) {
1392 for (res = res0; res; res = res->ai_next) {
1393 /* cover it up */
1394 res->ai_flags = pai->ai_flags;
1395
1396 if (pai->ai_flags & AI_CANONNAME)
1397 (void)get_canonname(pai, res, canonname);
1398 }
1399 } else
1400 res0 = NULL;
1401 if (res0) {
1402 cur->ai_next = res0;
1403 while (cur && cur->ai_next)
1404 cur = cur->ai_next;
1405 }
1406
1407 if (nextline) {
1408 p = nextline;
1409 goto nextline;
1410 }
1411
1412done:
1413 return sentinel.ai_next;
1414}
1415
1416/*ARGSUSED*/
1417static struct addrinfo *
1418_yp_getaddrinfo(const char *name, const struct addrinfo *pai)
1419{
1420 struct addrinfo sentinel, *cur;
1421 struct addrinfo *ai = NULL;
1422 static char *__ypcurrent;
1423 int __ypcurrentlen, r;
1424
1425 memset(&sentinel, 0, sizeof(sentinel));
1426 cur = &sentinel;
1427
1428 if (!__ypdomain) {
1429 if (_yp_check(&__ypdomain) == 0)
1430 return NULL;
1431 }
1432 if (__ypcurrent)
1433 free(__ypcurrent);
1434 __ypcurrent = NULL;
1435
1436 /* hosts.byname is only for IPv4 (Solaris8) */
1437 if (pai->ai_family == PF_UNSPEC || pai->ai_family == PF_INET) {
1438 r = yp_match(__ypdomain, "hosts.byname", name,
1439 (int)strlen(name), &__ypcurrent, &__ypcurrentlen);
1440 if (r == 0) {
1441 struct addrinfo ai4;
1442
1443 ai4 = *pai;
1444 ai4.ai_family = AF_INET;
1445 ai = _yphostent(__ypcurrent, &ai4);
1446 if (ai) {
1447 cur->ai_next = ai;
1448 while (cur && cur->ai_next)
1449 cur = cur->ai_next;
1450 }
1451 }
1452 }
1453
1454 /* ipnodes.byname can hold both IPv4/v6 */
1455 r = yp_match(__ypdomain, "ipnodes.byname", name,
1456 (int)strlen(name), &__ypcurrent, &__ypcurrentlen);
1457 if (r == 0) {
1458 ai = _yphostent(__ypcurrent, pai);
1459 if (ai) {
1460 cur->ai_next = ai;
1461 while (cur && cur->ai_next)
1462 cur = cur->ai_next;
1463 }
1464 }
1465
1466 return sentinel.ai_next;
1467}
1468#endif
1469
1470
1471/* resolver logic */
1472
1473extern const char *__hostalias(const char *);
1474extern int h_errno;
1475extern int res_opt(int, u_char *, int, int);
1476
1477/*
1478 * Formulate a normal query, send, and await answer.
1479 * Returned answer is placed in supplied buffer "answer".
1480 * Perform preliminary check of answer, returning success only
1481 * if no error is indicated and the answer count is nonzero.
1482 * Return the size of the response on success, -1 on error.
1483 * Error number is left in h_errno.
1484 *
1485 * Caller must parse answer and determine whether it answers the question.
1486 */
1487static int
1488res_queryN(const char *name, struct res_target *target)
1489{
1490 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
1491 u_char *buf;
1492 HEADER *hp;
1493 int n;
1494 struct res_target *t;
1495 int rcode;
1496 int ancount;
1497
1498 buf = malloc(MAXPACKET);
1499 if (buf == NULL) {
1500 h_errno = NETDB_INTERNAL;
1501 return (-1);
1502 }
1503
1504 rcode = NOERROR;
1505 ancount = 0;
1506
1507 if (_res_init(0) == -1) {
1508 h_errno = NETDB_INTERNAL;
1509 free(buf);
1510 return (-1);
1511 }
1512
1513 for (t = target; t; t = t->next) {
1514 int class, type;
1515 u_char *answer;
1516 int anslen;
1517
1518 hp = (HEADER *)(void *)t->answer;
1519 hp->rcode = NOERROR; /* default */
1520
1521 /* make it easier... */
1522 class = t->qclass;
1523 type = t->qtype;
1524 answer = t->answer;
1525 anslen = t->anslen;
1526#ifdef DEBUG
1527 if (_resp->options & RES_DEBUG)
1528 printf(";; res_query(%s, %d, %d)\n", name, class, type);
1529#endif
1530
1531 n = res_mkquery(QUERY, name, class, type, NULL, 0, NULL,
1532 buf, MAXPACKET);
1533 if (n > 0 && (_resp->options & RES_USE_EDNS0) != 0)
1534 n = res_opt(n, buf, MAXPACKET, anslen);
1535 if (n <= 0) {
1536#ifdef DEBUG
1537 if (_resp->options & RES_DEBUG)
1538 printf(";; res_query: mkquery failed\n");
1539#endif
1540 h_errno = NO_RECOVERY;
1541 free(buf);
1542 return (n);
1543 }
1544 n = res_send(buf, n, answer, anslen);
1545#if 0
1546 if (n < 0) {
1547#ifdef DEBUG
1548 if (_resp->options & RES_DEBUG)
1549 printf(";; res_query: send error\n");
1550#endif
1551 h_errno = TRY_AGAIN;
1552 free(buf);
1553 return (n);
1554 }
1555#endif
1556
1557 if (n < 0 || hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
1558 rcode = hp->rcode; /* record most recent error */
1559#ifdef DEBUG
1560 if (_resp->options & RES_DEBUG)
1561 printf(";; rcode = %u, ancount=%u\n", hp->rcode,
1562 ntohs(hp->ancount));
1563#endif
1564 continue;
1565 }
1566
1567 ancount += ntohs(hp->ancount);
1568
1569 t->n = n;
1570 }
1571
1572 if (ancount == 0) {
1573 switch (rcode) {
1574 case NXDOMAIN:
1575 h_errno = HOST_NOT_FOUND;
1576 break;
1577 case SERVFAIL:
1578 h_errno = TRY_AGAIN;
1579 break;
1580 case NOERROR:
1581 h_errno = NO_DATA;
1582 break;
1583 case FORMERR:
1584 case NOTIMP:
1585 case REFUSED:
1586 default:
1587 h_errno = NO_RECOVERY;
1588 break;
1589 }
1590 free(buf);
1591 return (-1);
1592 }
1593 free(buf);
1594 return (ancount);
1595}
1596
1597/*
1598 * Formulate a normal query, send, and retrieve answer in supplied buffer.
1599 * Return the size of the response on success, -1 on error.
1600 * If enabled, implement search rules until answer or unrecoverable failure
1601 * is detected. Error code, if any, is left in h_errno.
1602 */
1603static int
1604res_searchN(const char *name, struct res_target *target)
1605{
1606 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
1607 const char *cp, * const *domain;
1608 HEADER *hp = (HEADER *)(void *)target->answer; /*XXX*/
1609 u_int dots;
1610 int trailing_dot, ret, saved_herrno;
1611 int got_nodata = 0, got_servfail = 0, tried_as_is = 0;
1612
1613 if (_res_init(0) == -1) {
1614 h_errno = NETDB_INTERNAL;
1615 return (-1);
1616 }
1617
1618 errno = 0;
1619 h_errno = HOST_NOT_FOUND; /* default, if we never query */
1620 dots = 0;
1621 for (cp = name; *cp; cp++)
1622 dots += (*cp == '.');
1623 trailing_dot = 0;
1624 if (cp > name && *--cp == '.')
1625 trailing_dot++;
1626
1627 /*
1628 * if there aren't any dots, it could be a user-level alias
1629 */
1630 if (!dots && (cp = __hostalias(name)) != NULL)
1631 return (res_queryN(cp, target));
1632
1633 /*
1634 * If there are dots in the name already, let's just give it a try
1635 * 'as is'. The threshold can be set with the "ndots" option.
1636 */
1637 saved_herrno = -1;
1638 if (dots >= _resp->ndots) {
1639 ret = res_querydomainN(name, NULL, target);
1640 if (ret > 0)
1641 return (ret);
1642 saved_herrno = h_errno;
1643 tried_as_is++;
1644 }
1645
1646 /*
1647 * We do at least one level of search if
1648 * - there is no dot and RES_DEFNAME is set, or
1649 * - there is at least one dot, there is no trailing dot,
1650 * and RES_DNSRCH is set.
1651 */
1652 if ((!dots && (_resp->options & RES_DEFNAMES)) ||
1653 (dots && !trailing_dot && (_resp->options & RES_DNSRCH))) {
1654 int done = 0;
1655
1656 for (domain = (const char * const *)_resp->dnsrch;
1657 *domain && !done;
1658 domain++) {
1659
1660 ret = res_querydomainN(name, *domain, target);
1661 if (ret > 0)
1662 return (ret);
1663
1664 /*
1665 * If no server present, give up.
1666 * If name isn't found in this domain,
1667 * keep trying higher domains in the search list
1668 * (if that's enabled).
1669 * On a NO_DATA error, keep trying, otherwise
1670 * a wildcard entry of another type could keep us
1671 * from finding this entry higher in the domain.
1672 * If we get some other error (negative answer or
1673 * server failure), then stop searching up,
1674 * but try the input name below in case it's
1675 * fully-qualified.
1676 */
1677 if (errno == ECONNREFUSED) {
1678 h_errno = TRY_AGAIN;
1679 return (-1);
1680 }
1681
1682 switch (h_errno) {
1683 case NO_DATA:
1684 got_nodata++;
1685 /* FALLTHROUGH */
1686 case HOST_NOT_FOUND:
1687 /* keep trying */
1688 break;
1689 case TRY_AGAIN:
1690 if (hp->rcode == SERVFAIL) {
1691 /* try next search element, if any */
1692 got_servfail++;
1693 break;
1694 }
1695 /* FALLTHROUGH */
1696 default:
1697 /* anything else implies that we're done */
1698 done++;
1699 }
1700 /*
1701 * if we got here for some reason other than DNSRCH,
1702 * we only wanted one iteration of the loop, so stop.
1703 */
1704 if (!(_resp->options & RES_DNSRCH))
1705 done++;
1706 }
1707 }
1708
1709 /*
1710 * if we have not already tried the name "as is", do that now.
1711 * note that we do this regardless of how many dots were in the
1712 * name or whether it ends with a dot.
1713 */
1714 if (!tried_as_is) {
1715 ret = res_querydomainN(name, NULL, target);
1716 if (ret > 0)
1717 return (ret);
1718 }
1719
1720 /*
1721 * if we got here, we didn't satisfy the search.
1722 * if we did an initial full query, return that query's h_errno
1723 * (note that we wouldn't be here if that query had succeeded).
1724 * else if we ever got a nodata, send that back as the reason.
1725 * else send back meaningless h_errno, that being the one from
1726 * the last DNSRCH we did.
1727 */
1728 if (saved_herrno != -1)
1729 h_errno = saved_herrno;
1730 else if (got_nodata)
1731 h_errno = NO_DATA;
1732 else if (got_servfail)
1733 h_errno = TRY_AGAIN;
1734 return (-1);
1735}
1736
1737/*
1738 * Perform a call on res_query on the concatenation of name and domain,
1739 * removing a trailing dot from name if domain is NULL.
1740 */
1741static int
1742res_querydomainN(const char *name, const char *domain,
1743 struct res_target *target)
1744{
1745 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
1746 char nbuf[MAXDNAME];
1747 const char *longname = nbuf;
1748 size_t len;
1749
1750 if (_res_init(0) == -1) {
1751 h_errno = NETDB_INTERNAL;
1752 return (-1);
1753 }
1754#ifdef DEBUG
1755 if (_resp->options & RES_DEBUG)
1756 printf(";; res_querydomain(%s, %s)\n",
1757 name, domain?domain:"<Nil>");
1758#endif
1759 if (domain == NULL) {
1760 /*
1761 * Check for trailing '.';
1762 * copy without '.' if present.
1763 */
1764 len = strlcpy(nbuf, name, sizeof(nbuf));
1765 if (len >= sizeof(nbuf)) {
1766 h_errno = NO_RECOVERY;
1767 return (-1);
1768 }
1769 if (len > 0 && nbuf[len - 1] == '.')
1770 nbuf[len - 1] = '\0';
1771 } else {
1772 int i;
1773
1774 i = snprintf(nbuf, sizeof(nbuf), "%s.%s", name, domain);
1775 if (i < 0 || i >= sizeof(nbuf)) {
1776 h_errno = NO_RECOVERY;
1777 return (-1);
1778 }
1779 }
1780 return (res_queryN(longname, target));
1781}
diff --git a/src/lib/libc/net/gethostbyname.3 b/src/lib/libc/net/gethostbyname.3
new file mode 100644
index 0000000000..f3f3ea580f
--- /dev/null
+++ b/src/lib/libc/net/gethostbyname.3
@@ -0,0 +1,297 @@
1.\" $OpenBSD: gethostbyname.3,v 1.24 2005/07/22 04:50:51 jaredy 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.Vt 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 void *addr" "socklen_t 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 -offset indent
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 returned addresses */
88};
89#define h_addr h_addr_list[0] /* address, for backward compat */
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 null-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 occur when an address family other than
231.Dv AF_INET
232or
233.Dv AF_INET6
234is specified or when a resource is unable to be allocated.
235.It Dv NETDB_SUCCESS
236The function completed successfully.
237.El
238.Sh SEE ALSO
239.Xr getaddrinfo 3 ,
240.Xr getnameinfo 3 ,
241.Xr resolver 3 ,
242.Xr hosts 5 ,
243.Xr resolv.conf 5 ,
244.Xr hostname 7 ,
245.Xr named 8
246.Sh HISTORY
247The
248.Fn herror
249function appeared in
250.Bx 4.3 .
251The
252.Fn endhostent ,
253.Fn gethostbyaddr ,
254.Fn gethostbyname ,
255.Fn gethostent ,
256and
257.Fn sethostent
258functions appeared in
259.Bx 4.2 .
260.Sh CAVEATS
261If the search routines in
262.Xr resolv.conf 5
263decide to read the
264.Pa /etc/hosts
265file,
266.Fn gethostent
267and other functions will
268read the next line of the file,
269re-opening the file if necessary.
270.Pp
271The
272.Fn sethostent
273function opens and/or rewinds the file
274.Pa /etc/hosts .
275If the
276.Fa stayopen
277argument is non-zero, the file will not be closed after each call to
278.Fn gethostbyname ,
279.Fn gethostbyname2 ,
280or
281.Fn gethostbyaddr .
282.Pp
283The
284.Fn endhostent
285function closes the file.
286.Sh BUGS
287These functions use static data storage;
288if the data is needed for future use, it should be
289copied before any subsequent calls overwrite it.
290.Pp
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..d1c7d80df6
--- /dev/null
+++ b/src/lib/libc/net/gethostnamadr.c
@@ -0,0 +1,1126 @@
1/* $OpenBSD: gethostnamadr.c,v 1.68 2005/08/06 20:30:03 espie Exp $ */
2/*-
3 * Copyright (c) 1985, 1988, 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 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
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, and that
35 * the name of Digital Equipment Corporation not be used in advertising or
36 * publicity pertaining to distribution of the document or software without
37 * specific, written prior permission.
38 *
39 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
40 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
41 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
42 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
43 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
44 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
45 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
46 * SOFTWARE.
47 * -
48 * --Copyright--
49 */
50
51#include <sys/param.h>
52#include <sys/socket.h>
53#include <netinet/in.h>
54#include <arpa/inet.h>
55#include <arpa/nameser.h>
56#include <netdb.h>
57#include <resolv.h>
58#include <stdio.h>
59#include <ctype.h>
60#include <errno.h>
61#include <string.h>
62#include <syslog.h>
63#include <stdlib.h>
64#ifdef YP
65#include <rpc/rpc.h>
66#include <rpcsvc/yp.h>
67#include <rpcsvc/ypclnt.h>
68#include "ypinternal.h"
69#endif
70#include "thread_private.h"
71
72#define MULTI_PTRS_ARE_ALIASES 1 /* XXX - experimental */
73
74#define MAXALIASES 35
75#define MAXADDRS 35
76
77static char *h_addr_ptrs[MAXADDRS + 1];
78
79#ifdef YP
80static char *__ypdomain;
81#endif
82
83static struct hostent host;
84static char *host_aliases[MAXALIASES];
85static char hostbuf[BUFSIZ+1];
86static union {
87 struct in_addr _host_in_addr;
88 u_char _host_addr[16]; /* IPv4 or IPv6 */
89} _host_addr_u;
90#define host_addr _host_addr_u._host_addr
91static FILE *hostf = NULL;
92static int stayopen = 0;
93
94static void map_v4v6_address(const char *src, char *dst);
95static void map_v4v6_hostent(struct hostent *hp, char **bp, char *);
96
97#ifdef RESOLVSORT
98static void addrsort(char **, int);
99#endif
100
101int _hokchar(const char *);
102
103static const char AskedForGot[] =
104 "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
105
106#define MAXPACKET (64*1024)
107
108typedef union {
109 HEADER hdr;
110 u_char buf[MAXPACKET];
111} querybuf;
112
113typedef union {
114 int32_t al;
115 char ac;
116} align;
117
118static struct hostent *getanswer(const querybuf *, int, const char *, int);
119
120extern int h_errno;
121
122int
123_hokchar(const char *p)
124{
125 char c;
126
127 /*
128 * Many people do not obey RFC 822 and 1035. The valid
129 * characters are a-z, A-Z, 0-9, '-' and . But the others
130 * tested for below can happen, and we must be more permissive
131 * than the resolver until those idiots clean up their act.
132 * We let '/' through, but not '..'
133 */
134 while ((c = *p++)) {
135 if (('a' <= c && c <= 'z') ||
136 ('A' <= c && c <= 'Z') ||
137 ('0' <= c && c <= '9'))
138 continue;
139 if (strchr("-_/", c))
140 continue;
141 if (c == '.' && *p != '.')
142 continue;
143 return 0;
144 }
145 return 1;
146}
147
148static struct hostent *
149getanswer(const querybuf *answer, int anslen, const char *qname, int qtype)
150{
151 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
152 const HEADER *hp;
153 const u_char *cp, *eom;
154 char tbuf[MAXDNAME];
155 char *bp, **ap, **hap, *ep;
156 int type, class, ancount, qdcount, n;
157 int haveanswer, had_error, toobig = 0;
158 const char *tname;
159 int (*name_ok)(const char *);
160
161 tname = qname;
162 host.h_name = NULL;
163 eom = answer->buf + anslen;
164 switch (qtype) {
165 case T_A:
166 case T_AAAA:
167#ifdef USE_RESOLV_NAME_OK
168 name_ok = res_hnok;
169 break;
170#endif
171 case T_PTR:
172#ifdef USE_RESOLV_NAME_OK
173 name_ok = res_dnok;
174#else
175 name_ok = _hokchar;
176#endif
177 break;
178 default:
179 return (NULL);
180 }
181 /*
182 * find first satisfactory answer
183 */
184 hp = &answer->hdr;
185 ancount = ntohs(hp->ancount);
186 qdcount = ntohs(hp->qdcount);
187 bp = hostbuf;
188 ep = hostbuf + sizeof hostbuf;
189 cp = answer->buf + HFIXEDSZ;
190 if (qdcount != 1) {
191 h_errno = NO_RECOVERY;
192 return (NULL);
193 }
194 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
195 if ((n < 0) || !(*name_ok)(bp)) {
196 h_errno = NO_RECOVERY;
197 return (NULL);
198 }
199 cp += n + QFIXEDSZ;
200 if (qtype == T_A || qtype == T_AAAA) {
201 /* res_send() has already verified that the query name is the
202 * same as the one we sent; this just gets the expanded name
203 * (i.e., with the succeeding search-domain tacked on).
204 */
205 n = strlen(bp) + 1; /* for the \0 */
206 host.h_name = bp;
207 bp += n;
208 /* The qname can be abbreviated, but h_name is now absolute. */
209 qname = host.h_name;
210 }
211 ap = host_aliases;
212 *ap = NULL;
213 host.h_aliases = host_aliases;
214 hap = h_addr_ptrs;
215 *hap = NULL;
216 host.h_addr_list = h_addr_ptrs;
217 haveanswer = 0;
218 had_error = 0;
219 while (ancount-- > 0 && cp < eom && !had_error) {
220 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
221 if ((n < 0) || !(*name_ok)(bp)) {
222 had_error++;
223 continue;
224 }
225 cp += n; /* name */
226 if (cp >= eom)
227 break;
228 type = _getshort(cp);
229 cp += INT16SZ; /* type */
230 if (cp >= eom)
231 break;
232 class = _getshort(cp);
233 cp += INT16SZ + INT32SZ; /* class, TTL */
234 if (cp >= eom)
235 break;
236 n = _getshort(cp);
237 cp += INT16SZ; /* len */
238 if (cp >= eom)
239 break;
240 if (type == T_SIG) {
241 /* XXX - ignore signatures as we don't use them yet */
242 cp += n;
243 continue;
244 }
245 if (class != C_IN) {
246 /* XXX - debug? syslog? */
247 cp += n;
248 continue; /* XXX - had_error++ ? */
249 }
250 if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) {
251 if (ap >= &host_aliases[MAXALIASES-1])
252 continue;
253 n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
254 if ((n < 0) || !(*name_ok)(tbuf)) {
255 had_error++;
256 continue;
257 }
258 cp += n;
259 /* Store alias. */
260 *ap++ = bp;
261 n = strlen(bp) + 1; /* for the \0 */
262 bp += n;
263 /* Get canonical name. */
264 n = strlen(tbuf) + 1; /* for the \0 */
265 if (n > ep - bp) {
266 had_error++;
267 continue;
268 }
269 strlcpy(bp, tbuf, ep - bp);
270 host.h_name = bp;
271 bp += n;
272 continue;
273 }
274 if (qtype == T_PTR && type == T_CNAME) {
275 n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
276#ifdef USE_RESOLV_NAME_OK
277 if ((n < 0) || !res_hnok(tbuf)) {
278#else
279 if ((n < 0) || !_hokchar(tbuf)) {
280#endif
281 had_error++;
282 continue;
283 }
284 cp += n;
285 /* Get canonical name. */
286 n = strlen(tbuf) + 1; /* for the \0 */
287 if (n > ep - bp) {
288 had_error++;
289 continue;
290 }
291 strlcpy(bp, tbuf, ep - bp);
292 tname = bp;
293 bp += n;
294 continue;
295 }
296 if (type != qtype) {
297 syslog(LOG_NOTICE|LOG_AUTH,
298 "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
299 qname, p_class(C_IN), p_type(qtype),
300 p_type(type));
301 cp += n;
302 continue; /* XXX - had_error++ ? */
303 }
304 switch (type) {
305 case T_PTR:
306 if (strcasecmp(tname, bp) != 0) {
307 syslog(LOG_NOTICE|LOG_AUTH,
308 AskedForGot, qname, bp);
309 cp += n;
310 continue; /* XXX - had_error++ ? */
311 }
312 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
313#ifdef USE_RESOLV_NAME_OK
314 if ((n < 0) || !res_hnok(bp)) {
315#else
316 if ((n < 0) || !_hokchar(bp)) {
317#endif
318 had_error++;
319 break;
320 }
321#if MULTI_PTRS_ARE_ALIASES
322 cp += n;
323 if (!haveanswer)
324 host.h_name = bp;
325 else if (ap < &host_aliases[MAXALIASES-1])
326 *ap++ = bp;
327 else
328 n = -1;
329 if (n != -1) {
330 n = strlen(bp) + 1; /* for the \0 */
331 bp += n;
332 }
333 break;
334#else
335 host.h_name = bp;
336 if (_resp->options & RES_USE_INET6) {
337 n = strlen(bp) + 1; /* for the \0 */
338 bp += n;
339 map_v4v6_hostent(&host, &bp, ep);
340 }
341 h_errno = NETDB_SUCCESS;
342 return (&host);
343#endif
344 case T_A:
345 case T_AAAA:
346 if (strcasecmp(host.h_name, bp) != 0) {
347 syslog(LOG_NOTICE|LOG_AUTH,
348 AskedForGot, host.h_name, bp);
349 cp += n;
350 continue; /* XXX - had_error++ ? */
351 }
352 if (n != host.h_length) {
353 cp += n;
354 continue;
355 }
356 if (type == T_AAAA) {
357 struct in6_addr in6;
358 memcpy(&in6, cp, IN6ADDRSZ);
359 if (IN6_IS_ADDR_V4MAPPED(&in6)) {
360 cp += n;
361 continue;
362 }
363 }
364 if (!haveanswer) {
365 int nn;
366
367 host.h_name = bp;
368 nn = strlen(bp) + 1; /* for the \0 */
369 bp += nn;
370 }
371
372 bp += sizeof(align) - ((u_long)bp % sizeof(align));
373
374 if (bp + n >= &hostbuf[sizeof hostbuf]) {
375#ifdef DEBUG
376 if (_resp->options & RES_DEBUG)
377 printf("size (%d) too big\n", n);
378#endif
379 had_error++;
380 continue;
381 }
382 if (hap >= &h_addr_ptrs[MAXADDRS-1]) {
383 if (!toobig++)
384#ifdef DEBUG
385 if (_resp->options & RES_DEBUG)
386 printf("Too many addresses (%d)\n", MAXADDRS);
387#endif
388 cp += n;
389 continue;
390 }
391 bcopy(cp, *hap++ = bp, n);
392 bp += n;
393 cp += n;
394 break;
395 }
396 if (!had_error)
397 haveanswer++;
398 }
399 if (haveanswer) {
400 *ap = NULL;
401 *hap = NULL;
402# if defined(RESOLVSORT)
403 /*
404 * Note: we sort even if host can take only one address
405 * in its return structures - should give it the "best"
406 * address in that case, not some random one
407 */
408 if (_resp->nsort && haveanswer > 1 && qtype == T_A)
409 addrsort(h_addr_ptrs, haveanswer);
410# endif /*RESOLVSORT*/
411 if (!host.h_name) {
412 n = strlen(qname) + 1; /* for the \0 */
413 if (n > ep - bp)
414 goto try_again;
415 strlcpy(bp, qname, ep - bp);
416 host.h_name = bp;
417 bp += n;
418 }
419 if (_resp->options & RES_USE_INET6)
420 map_v4v6_hostent(&host, &bp, ep);
421 h_errno = NETDB_SUCCESS;
422 return (&host);
423 }
424 try_again:
425 h_errno = TRY_AGAIN;
426 return (NULL);
427}
428
429#ifdef notyet
430/*
431 * XXX This is an extremely bogus implementation.
432 *
433 * FreeBSD has this interface:
434 * int gethostbyaddr_r(const char *addr, int len, int type,
435 * struct hostent *result, struct hostent_data *buffer)
436 */
437
438struct hostent *
439gethostbyname_r(const char *name, struct hostent *hp, char *buf, int buflen,
440 int *errorp)
441{
442 struct hostent *res;
443
444 res = gethostbyname(name);
445 *errorp = h_errno;
446 if (res == NULL)
447 return NULL;
448 memcpy(hp, res, sizeof *hp); /* XXX not sufficient */
449 return hp;
450}
451
452/*
453 * XXX This is an extremely bogus implementation.
454 */
455struct hostent *
456gethostbyaddr_r(const char *addr, int len, int af, struct hostent *he,
457 char *buf, int buflen, int *errorp)
458{
459 struct hostent * res;
460
461 res = gethostbyaddr(addr, len, af);
462 *errorp = h_errno;
463 if (res == NULL)
464 return NULL;
465 memcpy(he, res, sizeof *he); /* XXX not sufficient */
466 return he;
467}
468
469/* XXX RFC2133 expects a gethostbyname2_r() -- unimplemented */
470#endif
471
472struct hostent *
473gethostbyname(const char *name)
474{
475 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
476 struct hostent *hp;
477 extern struct hostent *_gethtbyname2(const char *, int);
478
479 if (_res_init(0) == -1)
480 hp = _gethtbyname2(name, AF_INET);
481
482 else if (_resp->options & RES_USE_INET6) {
483 hp = gethostbyname2(name, AF_INET6);
484 if (hp == NULL)
485 hp = gethostbyname2(name, AF_INET);
486 }
487 else
488 hp = gethostbyname2(name, AF_INET);
489 return hp;
490}
491
492struct hostent *
493gethostbyname2(const char *name, int af)
494{
495 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
496 querybuf *buf;
497 const char *cp;
498 char *bp, *ep;
499 int n, size, type, i;
500 struct hostent *hp;
501 char lookups[MAXDNSLUS];
502 extern struct hostent *_gethtbyname2(const char *, int);
503 extern struct hostent *_yp_gethtbyname(const char *);
504
505 if (_res_init(0) == -1)
506 return (_gethtbyname2(name, af));
507
508 switch (af) {
509 case AF_INET:
510 size = INADDRSZ;
511 type = T_A;
512 break;
513 case AF_INET6:
514 size = IN6ADDRSZ;
515 type = T_AAAA;
516 break;
517 default:
518 h_errno = NETDB_INTERNAL;
519 errno = EAFNOSUPPORT;
520 return (NULL);
521 }
522
523 host.h_addrtype = af;
524 host.h_length = size;
525
526 /*
527 * if there aren't any dots, it could be a user-level alias.
528 * this is also done in res_query() since we are not the only
529 * function that looks up host names.
530 */
531 if (!strchr(name, '.') && (cp = __hostalias(name)))
532 name = cp;
533
534 /*
535 * disallow names consisting only of digits/dots, unless
536 * they end in a dot.
537 */
538 if (isdigit(name[0]))
539 for (cp = name;; ++cp) {
540 if (!*cp) {
541 if (*--cp == '.')
542 break;
543 /*
544 * All-numeric, no dot at the end.
545 * Fake up a hostent as if we'd actually
546 * done a lookup.
547 */
548 if (inet_pton(af, name, host_addr) <= 0) {
549 h_errno = HOST_NOT_FOUND;
550 return (NULL);
551 }
552 strlcpy(hostbuf, name, MAXHOSTNAMELEN);
553 bp = hostbuf + MAXHOSTNAMELEN;
554 ep = hostbuf + sizeof(hostbuf);
555 host.h_name = hostbuf;
556 host.h_aliases = host_aliases;
557 host_aliases[0] = NULL;
558 h_addr_ptrs[0] = (char *)host_addr;
559 h_addr_ptrs[1] = NULL;
560 host.h_addr_list = h_addr_ptrs;
561 if (_resp->options & RES_USE_INET6)
562 map_v4v6_hostent(&host, &bp, ep);
563 h_errno = NETDB_SUCCESS;
564 return (&host);
565 }
566 if (!isdigit(*cp) && *cp != '.')
567 break;
568 }
569 if ((isxdigit(name[0]) && strchr(name, ':') != NULL) ||
570 name[0] == ':')
571 for (cp = name;; ++cp) {
572 if (!*cp) {
573 if (*--cp == '.')
574 break;
575 /*
576 * All-IPv6-legal, no dot at the end.
577 * Fake up a hostent as if we'd actually
578 * done a lookup.
579 */
580 if (inet_pton(af, name, host_addr) <= 0) {
581 h_errno = HOST_NOT_FOUND;
582 return (NULL);
583 }
584 strlcpy(hostbuf, name, MAXHOSTNAMELEN);
585 bp = hostbuf + MAXHOSTNAMELEN;
586 ep = hostbuf + sizeof(hostbuf);
587 host.h_name = hostbuf;
588 host.h_aliases = host_aliases;
589 host_aliases[0] = NULL;
590 h_addr_ptrs[0] = (char *)host_addr;
591 h_addr_ptrs[1] = NULL;
592 host.h_addr_list = h_addr_ptrs;
593 h_errno = NETDB_SUCCESS;
594 return (&host);
595 }
596 if (!isxdigit(*cp) && *cp != ':' && *cp != '.')
597 break;
598 }
599
600 bcopy(_resp->lookups, lookups, sizeof lookups);
601 if (lookups[0] == '\0')
602 strlcpy(lookups, "bf", sizeof lookups);
603
604 hp = (struct hostent *)NULL;
605 for (i = 0; i < MAXDNSLUS && hp == NULL && lookups[i]; i++) {
606 switch (lookups[i]) {
607#ifdef YP
608 case 'y':
609 /* YP only supports AF_INET. */
610 if (af == AF_INET)
611 hp = _yp_gethtbyname(name);
612 break;
613#endif
614 case 'b':
615 buf = malloc(sizeof(*buf));
616 if (buf == NULL)
617 break;
618 if ((n = res_search(name, C_IN, type, buf->buf,
619 sizeof(buf->buf))) < 0) {
620 free(buf);
621#ifdef DEBUG
622 if (_resp->options & RES_DEBUG)
623 printf("res_search failed\n");
624#endif
625 break;
626 }
627 hp = getanswer(buf, n, name, type);
628 free(buf);
629 break;
630 case 'f':
631 hp = _gethtbyname2(name, af);
632 break;
633 }
634 }
635 /* XXX h_errno not correct in all cases... */
636 return (hp);
637}
638
639struct hostent *
640gethostbyaddr(const void *addr, socklen_t len, int af)
641{
642 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
643 const u_char *uaddr = (const u_char *)addr;
644 int n, size, i;
645 querybuf *buf;
646 struct hostent *hp;
647 char qbuf[MAXDNAME+1], *qp, *ep;
648 char lookups[MAXDNSLUS];
649 struct hostent *res;
650 extern struct hostent *_gethtbyaddr(const void *, socklen_t, int);
651 extern struct hostent *_yp_gethtbyaddr(const void *);
652
653 if (_res_init(0) == -1) {
654 res = _gethtbyaddr(addr, len, af);
655 return (res);
656 }
657
658 if (af == AF_INET6 && len == IN6ADDRSZ &&
659 (IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)uaddr) ||
660 IN6_IS_ADDR_SITELOCAL((struct in6_addr *)uaddr))) {
661 h_errno = HOST_NOT_FOUND;
662 return (NULL);
663 }
664 if (af == AF_INET6 && len == IN6ADDRSZ &&
665 (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)uaddr) ||
666 IN6_IS_ADDR_V4COMPAT((struct in6_addr *)uaddr))) {
667 /* Unmap. */
668 uaddr += IN6ADDRSZ - INADDRSZ;
669 af = AF_INET;
670 len = INADDRSZ;
671 }
672 switch (af) {
673 case AF_INET:
674 size = INADDRSZ;
675 break;
676 case AF_INET6:
677 size = IN6ADDRSZ;
678 break;
679 default:
680 errno = EAFNOSUPPORT;
681 h_errno = NETDB_INTERNAL;
682 return (NULL);
683 }
684 if (size != len) {
685 errno = EINVAL;
686 h_errno = NETDB_INTERNAL;
687 return (NULL);
688 }
689 ep = qbuf + sizeof(qbuf);
690 switch (af) {
691 case AF_INET:
692 (void) snprintf(qbuf, sizeof qbuf, "%u.%u.%u.%u.in-addr.arpa",
693 (uaddr[3] & 0xff), (uaddr[2] & 0xff),
694 (uaddr[1] & 0xff), (uaddr[0] & 0xff));
695 break;
696 case AF_INET6:
697 qp = qbuf;
698 for (n = IN6ADDRSZ - 1; n >= 0; n--) {
699 i = snprintf(qp, ep - qp, "%x.%x.",
700 uaddr[n] & 0xf, (uaddr[n] >> 4) & 0xf);
701 if (i <= 0 || i >= ep - qp) {
702 errno = EINVAL;
703 h_errno = NETDB_INTERNAL;
704 return (NULL);
705 }
706 qp += i;
707 }
708 strlcpy(qp, "ip6.arpa", ep - qp);
709 break;
710 }
711
712 bcopy(_resp->lookups, lookups, sizeof lookups);
713 if (lookups[0] == '\0')
714 strlcpy(lookups, "bf", sizeof lookups);
715
716 hp = (struct hostent *)NULL;
717 for (i = 0; i < MAXDNSLUS && hp == NULL && lookups[i]; i++) {
718 switch (lookups[i]) {
719#ifdef YP
720 case 'y':
721 /* YP only supports AF_INET. */
722 if (af == AF_INET)
723 hp = _yp_gethtbyaddr(uaddr);
724 break;
725#endif
726 case 'b':
727 buf = malloc(sizeof(*buf));
728 if (!buf)
729 break;
730 n = res_query(qbuf, C_IN, T_PTR, buf->buf,
731 sizeof(buf->buf));
732 if (n < 0) {
733 free(buf);
734#ifdef DEBUG
735 if (_resp->options & RES_DEBUG)
736 printf("res_query failed\n");
737#endif
738 break;
739 }
740 if (!(hp = getanswer(buf, n, qbuf, T_PTR))) {
741 free(buf);
742 break;
743 }
744 free(buf);
745 hp->h_addrtype = af;
746 hp->h_length = len;
747 bcopy(uaddr, host_addr, len);
748 h_addr_ptrs[0] = (char *)host_addr;
749 h_addr_ptrs[1] = NULL;
750 if (af == AF_INET && (_resp->options & RES_USE_INET6)) {
751 map_v4v6_address((char*)host_addr,
752 (char*)host_addr);
753 hp->h_addrtype = AF_INET6;
754 hp->h_length = IN6ADDRSZ;
755 }
756 h_errno = NETDB_SUCCESS;
757 break;
758 case 'f':
759 hp = _gethtbyaddr(uaddr, len, af);
760 break;
761 }
762 }
763 /* XXX h_errno not correct in all cases... */
764 return (hp);
765}
766
767void
768_sethtent(int f)
769{
770 if (hostf == NULL)
771 hostf = fopen(_PATH_HOSTS, "r" );
772 else
773 rewind(hostf);
774 stayopen = f;
775}
776
777void
778_endhtent(void)
779{
780 if (hostf && !stayopen) {
781 (void) fclose(hostf);
782 hostf = NULL;
783 }
784}
785
786static struct hostent *
787_gethtent(void)
788{
789 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
790 char *p, *cp, **q;
791 int af;
792 size_t len;
793
794 if (!hostf && !(hostf = fopen(_PATH_HOSTS, "r" ))) {
795 h_errno = NETDB_INTERNAL;
796 return (NULL);
797 }
798 again:
799 if ((p = fgetln(hostf, &len)) == NULL) {
800 h_errno = HOST_NOT_FOUND;
801 return (NULL);
802 }
803 if (p[len-1] == '\n')
804 len--;
805 if (len >= sizeof(hostbuf) || len == 0)
806 goto again;
807 p = memcpy(hostbuf, p, len);
808 hostbuf[len] = '\0';
809 if (*p == '#')
810 goto again;
811 if ((cp = strchr(p, '#')))
812 *cp = '\0';
813 if (!(cp = strpbrk(p, " \t")))
814 goto again;
815 *cp++ = '\0';
816 if (inet_pton(AF_INET6, p, host_addr) > 0) {
817 af = AF_INET6;
818 len = IN6ADDRSZ;
819 } else if (inet_pton(AF_INET, p, host_addr) > 0) {
820 if (_resp->options & RES_USE_INET6) {
821 map_v4v6_address((char*)host_addr, (char*)host_addr);
822 af = AF_INET6;
823 len = IN6ADDRSZ;
824 } else {
825 af = AF_INET;
826 len = INADDRSZ;
827 }
828 } else {
829 goto again;
830 }
831 /* if this is not something we're looking for, skip it. */
832 if (host.h_addrtype != AF_UNSPEC && host.h_addrtype != af)
833 goto again;
834 if (host.h_length != 0 && host.h_length != len)
835 goto again;
836 h_addr_ptrs[0] = (char *)host_addr;
837 h_addr_ptrs[1] = NULL;
838 host.h_addr_list = h_addr_ptrs;
839 host.h_length = len;
840 host.h_addrtype = af;
841 while (*cp == ' ' || *cp == '\t')
842 cp++;
843 host.h_name = cp;
844 q = host.h_aliases = host_aliases;
845 if ((cp = strpbrk(cp, " \t")))
846 *cp++ = '\0';
847 while (cp && *cp) {
848 if (*cp == ' ' || *cp == '\t') {
849 cp++;
850 continue;
851 }
852 if (q < &host_aliases[MAXALIASES - 1])
853 *q++ = cp;
854 if ((cp = strpbrk(cp, " \t")))
855 *cp++ = '\0';
856 }
857 *q = NULL;
858 if (_resp->options & RES_USE_INET6) {
859 char *bp = hostbuf;
860 char *ep = hostbuf + sizeof hostbuf;
861
862 map_v4v6_hostent(&host, &bp, ep);
863 }
864 h_errno = NETDB_SUCCESS;
865 return (&host);
866}
867
868struct hostent *
869_gethtbyname2(const char *name, int af)
870{
871 struct hostent *p;
872 char **cp;
873
874 _sethtent(0);
875 while ((p = _gethtent())) {
876 if (p->h_addrtype != af)
877 continue;
878 if (strcasecmp(p->h_name, name) == 0)
879 break;
880 for (cp = p->h_aliases; *cp != 0; cp++)
881 if (strcasecmp(*cp, name) == 0)
882 goto found;
883 }
884 found:
885 _endhtent();
886 return (p);
887}
888
889struct hostent *
890_gethtbyaddr(const void *addr, socklen_t len, int af)
891{
892 struct hostent *p;
893
894 host.h_length = len;
895 host.h_addrtype = af;
896
897 _sethtent(0);
898 while ((p = _gethtent()))
899 if (p->h_addrtype == af && p->h_length == len &&
900 !bcmp(p->h_addr, addr, len))
901 break;
902 _endhtent();
903 return (p);
904}
905
906#ifdef YP
907struct hostent *
908_yphostent(char *line)
909{
910 static struct in_addr host_addrs[MAXADDRS];
911 char *p = line;
912 char *cp, **q;
913 char **hap;
914 struct in_addr *buf;
915 int more;
916
917 host.h_name = NULL;
918 host.h_addr_list = h_addr_ptrs;
919 host.h_length = INADDRSZ;
920 host.h_addrtype = AF_INET;
921 hap = h_addr_ptrs;
922 buf = host_addrs;
923 q = host.h_aliases = host_aliases;
924
925nextline:
926 /* check for host_addrs overflow */
927 if (buf >= &host_addrs[sizeof(host_addrs) / sizeof(host_addrs[0])])
928 goto done;
929
930 more = 0;
931 cp = strpbrk(p, " \t");
932 if (cp == NULL)
933 goto done;
934 *cp++ = '\0';
935
936 *hap++ = (char *)buf;
937 (void) inet_aton(p, buf++);
938
939 while (*cp == ' ' || *cp == '\t')
940 cp++;
941 p = cp;
942 cp = strpbrk(p, " \t\n");
943 if (cp != NULL) {
944 if (*cp == '\n')
945 more = 1;
946 *cp++ = '\0';
947 }
948 if (!host.h_name)
949 host.h_name = p;
950 else if (strcmp(host.h_name, p)==0)
951 ;
952 else if (q < &host_aliases[MAXALIASES - 1])
953 *q++ = p;
954 p = cp;
955 if (more)
956 goto nextline;
957
958 while (cp && *cp) {
959 if (*cp == ' ' || *cp == '\t') {
960 cp++;
961 continue;
962 }
963 if (*cp == '\n') {
964 cp++;
965 goto nextline;
966 }
967 if (q < &host_aliases[MAXALIASES - 1])
968 *q++ = cp;
969 cp = strpbrk(cp, " \t");
970 if (cp != NULL)
971 *cp++ = '\0';
972 }
973done:
974 if (host.h_name == NULL)
975 return (NULL);
976 *q = NULL;
977 *hap = NULL;
978 return (&host);
979}
980
981struct hostent *
982_yp_gethtbyaddr(const void *addr)
983{
984 struct hostent *hp = NULL;
985 const u_char *uaddr = (const u_char *)addr;
986 static char *__ypcurrent;
987 int __ypcurrentlen, r;
988 char name[sizeof("xxx.xxx.xxx.xxx")];
989
990 if (!__ypdomain) {
991 if (_yp_check(&__ypdomain) == 0)
992 return (hp);
993 }
994 snprintf(name, sizeof name, "%u.%u.%u.%u", (uaddr[0] & 0xff),
995 (uaddr[1] & 0xff), (uaddr[2] & 0xff), (uaddr[3] & 0xff));
996 if (__ypcurrent)
997 free(__ypcurrent);
998 __ypcurrent = NULL;
999 r = yp_match(__ypdomain, "hosts.byaddr", name,
1000 strlen(name), &__ypcurrent, &__ypcurrentlen);
1001 if (r==0)
1002 hp = _yphostent(__ypcurrent);
1003 if (hp==NULL)
1004 h_errno = HOST_NOT_FOUND;
1005 return (hp);
1006}
1007
1008struct hostent *
1009_yp_gethtbyname(const char *name)
1010{
1011 struct hostent *hp = (struct hostent *)NULL;
1012 static char *__ypcurrent;
1013 int __ypcurrentlen, r;
1014
1015 if (strlen(name) >= MAXHOSTNAMELEN)
1016 return (NULL);
1017 if (!__ypdomain) {
1018 if (_yp_check(&__ypdomain) == 0)
1019 return (hp);
1020 }
1021 if (__ypcurrent)
1022 free(__ypcurrent);
1023 __ypcurrent = NULL;
1024 r = yp_match(__ypdomain, "hosts.byname", name,
1025 strlen(name), &__ypcurrent, &__ypcurrentlen);
1026 if (r == 0)
1027 hp = _yphostent(__ypcurrent);
1028 if (hp == NULL)
1029 h_errno = HOST_NOT_FOUND;
1030 return (hp);
1031}
1032#endif
1033
1034static void
1035map_v4v6_address(const char *src, char *dst)
1036{
1037 u_char *p = (u_char *)dst;
1038 char tmp[INADDRSZ];
1039 int i;
1040
1041 /* Stash a temporary copy so our caller can update in place. */
1042 bcopy(src, tmp, INADDRSZ);
1043 /* Mark this ipv6 addr as a mapped ipv4. */
1044 for (i = 0; i < 10; i++)
1045 *p++ = 0x00;
1046 *p++ = 0xff;
1047 *p++ = 0xff;
1048 /* Retrieve the saved copy and we're done. */
1049 bcopy(tmp, (void*)p, INADDRSZ);
1050}
1051
1052static void
1053map_v4v6_hostent(struct hostent *hp, char **bpp, char *ep)
1054{
1055 char **ap;
1056
1057 if (hp->h_addrtype != AF_INET || hp->h_length != INADDRSZ)
1058 return;
1059 hp->h_addrtype = AF_INET6;
1060 hp->h_length = IN6ADDRSZ;
1061 for (ap = hp->h_addr_list; *ap; ap++) {
1062 int i = sizeof(align) - ((u_long)*bpp % sizeof(align));
1063
1064 if (ep - *bpp < (i + IN6ADDRSZ)) {
1065 /* Out of memory. Truncate address list here. XXX */
1066 *ap = NULL;
1067 return;
1068 }
1069 *bpp += i;
1070 map_v4v6_address(*ap, *bpp);
1071 *ap = *bpp;
1072 *bpp += IN6ADDRSZ;
1073 }
1074}
1075
1076struct hostent *
1077gethostent(void)
1078{
1079 host.h_addrtype = AF_UNSPEC;
1080 host.h_length = 0;
1081 return (_gethtent());
1082}
1083
1084#ifdef RESOLVSORT
1085static void
1086addrsort(char **ap, int num)
1087{
1088 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
1089 int i, j;
1090 char **p;
1091 short aval[MAXADDRS];
1092 int needsort = 0;
1093
1094 p = ap;
1095 for (i = 0; i < num; i++, p++) {
1096 for (j = 0 ; (unsigned)j < _resp->nsort; j++)
1097 if (_resp->sort_list[j].addr.s_addr ==
1098 (((struct in_addr *)(*p))->s_addr &
1099 _resp->sort_list[j].mask))
1100 break;
1101 aval[i] = j;
1102 if (needsort == 0 && i > 0 && j < aval[i-1])
1103 needsort = i;
1104 }
1105 if (!needsort)
1106 return;
1107
1108 while (needsort < num) {
1109 for (j = needsort - 1; j >= 0; j--) {
1110 if (aval[j] > aval[j+1]) {
1111 char *hp;
1112
1113 i = aval[j];
1114 aval[j] = aval[j+1];
1115 aval[j+1] = i;
1116
1117 hp = ap[j];
1118 ap[j] = ap[j+1];
1119 ap[j+1] = hp;
1120 } else
1121 break;
1122 }
1123 needsort++;
1124 }
1125}
1126#endif
diff --git a/src/lib/libc/net/getifaddrs.3 b/src/lib/libc/net/getifaddrs.3
new file mode 100644
index 0000000000..e6380be4b7
--- /dev/null
+++ b/src/lib/libc/net/getifaddrs.3
@@ -0,0 +1,158 @@
1.\" $OpenBSD: getifaddrs.3,v 1.12 2005/07/22 04:50:51 jaredy 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.Bl -tag -width ifa_broadaddr
62.It Fa ifa_next
63Contains a pointer to the next structure on the list.
64This field is set to
65.Dv NULL
66in the last structure on the list.
67.It Fa ifa_name
68Contains the interface name.
69.It Fa ifa_flags
70Contains the interface flags, as set by
71.Xr ifconfig 8 .
72.It Fa ifa_addr
73References either the address of the interface or the link level
74address of the interface, if one exists, otherwise it is
75.Dv NULL .
76(The
77.Fa sa_family
78field of the
79.Fa ifa_addr
80field should be consulted to determine the format of the
81.Fa ifa_addr
82address.)
83.It Fa ifa_netmask
84References the netmask associated with
85.Fa ifa_addr ,
86if one is set, otherwise it is
87.Dv NULL .
88.It Fa ifa_broadaddr
89This field, which should only be referenced for non-P2P interfaces,
90references the broadcast address associated with
91.Fa ifa_addr ,
92if one exists, otherwise it is
93.Dv NULL .
94.It Fa ifa_dstaddr
95References the destination address on a P2P interface,
96if one exists, otherwise it is
97.Dv NULL .
98.It Fa ifa_data
99References address family specific data.
100For
101.Dv AF_LINK
102addresses it contains a pointer to the
103.Li struct if_data
104(as defined in include file
105.Aq Pa net/if.h )
106which contains various interface attributes and statistics.
107For all other address families, it contains a pointer to the
108.Li struct ifa_data
109(as defined in include file
110.Aq Pa net/if.h )
111which contains per-address interface statistics.
112.El
113.Pp
114The data returned by
115.Fn getifaddrs
116is dynamically allocated and should be freed using
117.Fn freeifaddrs
118when no longer needed.
119.Sh RETURN VALUES
120Upon successful completion, a value of 0 is returned.
121Otherwise, a value of \-1 is returned and
122.Va errno
123is set to indicate the error.
124.Sh ERRORS
125The
126.Fn getifaddrs
127may fail and set
128.Va errno
129for any of the errors specified for the library routines
130.Xr ioctl 2 ,
131.Xr socket 2 ,
132.Xr malloc 3 ,
133or
134.Xr sysctl 3 .
135.Sh SEE ALSO
136.Xr ioctl 2 ,
137.Xr socket 2 ,
138.Xr sysctl 3 ,
139.Xr networking 4 ,
140.Xr ifconfig 8
141.Sh HISTORY
142The
143.Fn getifaddrs
144function first appeared in BSDI BSD/OS.
145The function has been available on
146.Ox
147since
148.Ox 2.7 .
149.Sh BUGS
150If both
151.Aq Pa net/if.h
152and
153.Aq Pa ifaddrs.h
154are being included,
155.Aq Pa net/if.h
156.Em must
157be included before
158.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..b17f2e4aeb
--- /dev/null
+++ b/src/lib/libc/net/getnameinfo.3
@@ -0,0 +1,270 @@
1.\" $OpenBSD: getnameinfo.3,v 1.38 2005/01/29 00:49:47 jmc Exp $
2.\" $KAME: getnameinfo.3,v 1.37 2005/01/05 03:23:05 itojun Exp $
3.\"
4.\" Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
5.\" Copyright (C) 2000, 2001 Internet Software Consortium.
6.\"
7.\" Permission to use, copy, modify, and distribute this software for any
8.\" purpose with or without fee is hereby granted, provided that the above
9.\" copyright notice and this permission notice appear in all copies.
10.\"
11.\" THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12.\" REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13.\" AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14.\" INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15.\" LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16.\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17.\" PERFORMANCE OF THIS SOFTWARE.
18.\"
19.Dd December 20, 2004
20.Dt GETNAMEINFO 3
21.Os
22.Sh NAME
23.Nm getnameinfo
24.Nd socket address structure to hostname and service name
25.Sh SYNOPSIS
26.Fd #include <sys/types.h>
27.Fd #include <sys/socket.h>
28.Fd #include <netdb.h>
29.Ft int
30.Fn getnameinfo "const struct sockaddr *sa" "socklen_t salen" "char *host" \
31 "size_t hostlen" "char *serv" "size_t servlen" "int flags"
32.Sh DESCRIPTION
33The
34.Fn getnameinfo
35function is used to convert a
36.Li sockaddr
37structure to a pair of host name and service strings.
38It is a replacement for and provides more flexibility than the
39.Xr gethostbyaddr 3
40and
41.Xr getservbyport 3
42functions and is the converse of the
43.Xr getaddrinfo 3
44function.
45.Pp
46The
47.Li sockaddr
48structure
49.Fa sa
50should point to either a
51.Li sockaddr_in
52or
53.Li sockaddr_in6
54structure (for IPv4 or IPv6 respectively) that is
55.Fa salen
56bytes long.
57.Pp
58The host and service names associated with
59.Fa sa
60are stored in
61.Fa host
62and
63.Fa serv
64which have length parameters
65.Fa hostlen
66and
67.Fa servlen .
68The maximum value for
69.Fa hostlen
70is
71.Dv NI_MAXHOST
72and
73the maximum value for
74.Fa servlen
75is
76.Dv NI_MAXSERV ,
77as defined by
78.Aq Pa netdb.h .
79If a length parameter is zero, no string will be stored.
80Otherwise, enough space must be provided to store the
81host name or service string plus a byte for the NUL terminator.
82.Pp
83The
84.Fa flags
85argument is formed by
86.Tn OR Ns 'ing
87the following values:
88.Bl -tag -width "NI_NUMERICHOSTXX"
89.It Dv NI_NOFQDN
90A fully qualified domain name is not required for local hosts.
91The local part of the fully qualified domain name is returned instead.
92.It Dv NI_NUMERICHOST
93Return the address in numeric form, as if calling
94.Xr inet_ntop 3 ,
95instead of a host name.
96.It Dv NI_NAMEREQD
97A name is required.
98If the host name cannot be found in DNS and this flag is set,
99a non-zero error code is returned.
100If the host name is not found and the flag is not set, the
101address is returned in numeric form.
102.It NI_NUMERICSERV
103The service name is returned as a digit string representing the port number.
104.It NI_DGRAM
105Specifies that the service being looked up is a datagram
106service, and causes
107.Xr getservbyport 3
108to be called with a second argument of
109.Dq udp
110instead of its default of
111.Dq tcp .
112This is required for the few ports (512\-514) that have different services
113for
114.Tn UDP
115and
116.Tn TCP .
117.El
118.Pp
119This implementation allows numeric IPv6 address notation with scope identifier,
120as documented in chapter 11 of draft-ietf-ipv6-scoping-arch-02.txt.
121IPv6 link-local address will appear as a string like
122.Dq Li fe80::1%ne0 .
123Refer to
124.Xr getaddrinfo 3
125for more information.
126.Sh RETURN VALUES
127.Fn getnameinfo
128returns zero on success or one of the error codes listed in
129.Xr gai_strerror 3
130if an error occurs.
131.Sh EXAMPLES
132The following code tries to get a numeric host name, and service name,
133for a given socket address.
134Observe that there is no hardcoded reference to a particular address family.
135.Bd -literal -offset indent
136struct sockaddr *sa; /* input */
137char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
138
139if (getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf), sbuf,
140 sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV)) {
141 errx(1, "could not get numeric hostname");
142 /*NOTREACHED*/
143}
144printf("host=%s, serv=%s\en", hbuf, sbuf);
145.Ed
146.Pp
147The following version checks if the socket address has a reverse address mapping:
148.Bd -literal -offset indent
149struct sockaddr *sa; /* input */
150char hbuf[NI_MAXHOST];
151
152if (getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf), NULL, 0,
153 NI_NAMEREQD)) {
154 errx(1, "could not resolve hostname");
155 /*NOTREACHED*/
156}
157printf("host=%s\en", hbuf);
158.Ed
159.Sh SEE ALSO
160.Xr gai_strerror 3 ,
161.Xr getaddrinfo 3 ,
162.Xr gethostbyaddr 3 ,
163.Xr getservbyport 3 ,
164.Xr inet_ntop 3 ,
165.Xr resolver 3 ,
166.Xr hosts 5 ,
167.Xr resolv.conf 5 ,
168.Xr services 5 ,
169.Xr hostname 7 ,
170.Xr named 8
171.Rs
172.%A R. Gilligan
173.%A S. Thomson
174.%A J. Bound
175.%A W. Stevens
176.%T Basic Socket Interface Extensions for IPv6
177.%R RFC 2553
178.%D March 1999
179.Re
180.Rs
181.%A S. Deering
182.%A B. Haberman
183.%A T. Jinmei
184.%A E. Nordmark
185.%A B. Zill
186.%T "IPv6 Scoped Address Architecture"
187.%R internet draft
188.%N draft-ietf-ipv6-scoping-arch-02.txt
189.%O work in progress material
190.Re
191.Rs
192.%A Craig Metz
193.%T Protocol Independence Using the Sockets API
194.%B "Proceedings of the Freenix Track: 2000 USENIX Annual Technical Conference"
195.%D June 2000
196.Re
197.Sh STANDARDS
198The
199.Fn getnameinfo
200function is defined by the
201.St -p1003.1g-2000
202draft specification and documented in
203.Tn "RFC 2553" ,
204.Dq Basic Socket Interface Extensions for IPv6 .
205.Sh CAVEATS
206.Fn getnameinfo
207can return both numeric and FQDN forms of the address specified in
208.Fa sa .
209There is no return value that indicates whether the string returned in
210.Fa host
211is a result of binary to numeric-text translation (like
212.Xr inet_ntop 3 ) ,
213or is the result of a DNS reverse lookup.
214Because of this, malicious parties could set up a PTR record as follows:
215.Bd -literal -offset indent
2161.0.0.127.in-addr.arpa. IN PTR 10.1.1.1
217.Ed
218.Pp
219and trick the caller of
220.Fn getnameinfo
221into believing that
222.Fa sa
223is
224.Li 10.1.1.1
225when it is actually
226.Li 127.0.0.1 .
227.Pp
228To prevent such attacks, the use of
229.Dv NI_NAMEREQD
230is recommended when the result of
231.Fn getnameinfo
232is used
233for access control purposes:
234.Bd -literal -offset indent
235struct sockaddr *sa;
236socklen_t salen;
237char addr[NI_MAXHOST];
238struct addrinfo hints, *res;
239int error;
240
241error = getnameinfo(sa, salen, addr, sizeof(addr),
242 NULL, 0, NI_NAMEREQD);
243if (error == 0) {
244 memset(&hints, 0, sizeof(hints));
245 hints.ai_socktype = SOCK_DGRAM; /*dummy*/
246 hints.ai_flags = AI_NUMERICHOST;
247 if (getaddrinfo(addr, "0", &hints, &res) == 0) {
248 /* malicious PTR record */
249 freeaddrinfo(res);
250 printf("bogus PTR record\en");
251 return -1;
252 }
253 /* addr is FQDN as a result of PTR lookup */
254} else {
255 /* addr is numeric string */
256 error = getnameinfo(sa, salen, addr, sizeof(addr),
257 NULL, 0, NI_NUMERICHOST);
258}
259.Ed
260.Sh BUGS
261The implementation of
262.Fn getnameinfo
263is not thread-safe.
264.Pp
265.Ox
266intentionally uses a different
267.Dv NI_MAXHOST
268value from what
269.Tn "RFC 2553"
270suggests, 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..4c8ee80fec
--- /dev/null
+++ b/src/lib/libc/net/getnameinfo.c
@@ -0,0 +1,353 @@
1/* $OpenBSD: getnameinfo.c,v 1.31 2005/06/19 04:44:34 marcm 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 */
94void *__THREAD_NAME(serv_mutex);
95
96int
97getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host,
98 size_t hostlen, char *serv, size_t servlen, int flags)
99{
100 const struct afd *afd;
101 struct servent *sp;
102 struct hostent *hp;
103 u_short port;
104 int family, i;
105 const char *addr;
106 u_int32_t v4a;
107 char numserv[512];
108 char numaddr[512];
109
110 if (sa == NULL)
111 return EAI_FAIL;
112
113 family = sa->sa_family;
114 for (i = 0; afdl[i].a_af; i++)
115 if (afdl[i].a_af == family) {
116 afd = &afdl[i];
117 goto found;
118 }
119 return EAI_FAMILY;
120
121 found:
122 if (salen != afd->a_socklen)
123 return EAI_FAIL;
124
125 /* network byte order */
126 port = ((const struct sockinet *)sa)->si_port;
127 addr = (const char *)sa + afd->a_off;
128
129 if (serv == NULL || servlen == 0) {
130 /*
131 * do nothing in this case.
132 * in case you are wondering if "&&" is more correct than
133 * "||" here: rfc2553bis-03 says that serv == NULL OR
134 * servlen == 0 means that the caller does not want the result.
135 */
136 } else {
137 if (flags & NI_NUMERICSERV)
138 sp = NULL;
139 else {
140 _THREAD_PRIVATE_MUTEX_LOCK(serv_mutex);
141 sp = getservbyport(port,
142 (flags & NI_DGRAM) ? "udp" : "tcp");
143 _THREAD_PRIVATE_MUTEX_UNLOCK(serv_mutex);
144 }
145 if (sp) {
146 if (strlen(sp->s_name) + 1 > servlen)
147 return EAI_MEMORY;
148 strlcpy(serv, sp->s_name, servlen);
149 } else {
150 snprintf(numserv, sizeof(numserv), "%u", ntohs(port));
151 if (strlen(numserv) + 1 > servlen)
152 return EAI_MEMORY;
153 strlcpy(serv, numserv, servlen);
154 }
155 }
156
157 switch (sa->sa_family) {
158 case AF_INET:
159 v4a = (u_int32_t)
160 ntohl(((const struct sockaddr_in *)sa)->sin_addr.s_addr);
161 if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))
162 flags |= NI_NUMERICHOST;
163 v4a >>= IN_CLASSA_NSHIFT;
164 if (v4a == 0)
165 flags |= NI_NUMERICHOST;
166 break;
167#ifdef INET6
168 case AF_INET6:
169 {
170 const struct sockaddr_in6 *sin6;
171 sin6 = (const struct sockaddr_in6 *)sa;
172 switch (sin6->sin6_addr.s6_addr[0]) {
173 case 0x00:
174 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr))
175 ;
176 else if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr))
177 ;
178 else
179 flags |= NI_NUMERICHOST;
180 break;
181 default:
182 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
183 flags |= NI_NUMERICHOST;
184 }
185 else if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
186 flags |= NI_NUMERICHOST;
187 break;
188 }
189 }
190 break;
191#endif
192 }
193 if (host == NULL || hostlen == 0) {
194 /*
195 * do nothing in this case.
196 * in case you are wondering if "&&" is more correct than
197 * "||" here: rfc2553bis-03 says that host == NULL or
198 * hostlen == 0 means that the caller does not want the result.
199 */
200 } else if (flags & NI_NUMERICHOST) {
201 int numaddrlen;
202
203 /* NUMERICHOST and NAMEREQD conflicts with each other */
204 if (flags & NI_NAMEREQD)
205 return EAI_NONAME;
206
207 switch(afd->a_af) {
208#ifdef INET6
209 case AF_INET6:
210 {
211 int error;
212
213 if ((error = ip6_parsenumeric(sa, addr, host,
214 hostlen, flags)) != 0)
215 return(error);
216 break;
217 }
218#endif
219 default:
220 if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr))
221 == NULL)
222 return EAI_SYSTEM;
223 numaddrlen = strlen(numaddr);
224 if (numaddrlen + 1 > hostlen) /* don't forget terminator */
225 return EAI_MEMORY;
226 strlcpy(host, numaddr, hostlen);
227 break;
228 }
229 } else {
230 _THREAD_PRIVATE_MUTEX_LOCK(serv_mutex);
231 hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af);
232 _THREAD_PRIVATE_MUTEX_UNLOCK(serv_mutex);
233
234 if (hp) {
235#if 0
236 /*
237 * commented out, since "for local host" is not
238 * implemented here - see RFC2553 p30
239 */
240 if (flags & NI_NOFQDN) {
241 char *p;
242 p = strchr(hp->h_name, '.');
243 if (p)
244 *p = '\0';
245 }
246#endif
247 if (strlen(hp->h_name) + 1 > hostlen) {
248 return EAI_MEMORY;
249 }
250 strlcpy(host, hp->h_name, hostlen);
251 } else {
252 if (flags & NI_NAMEREQD)
253 return EAI_NONAME;
254 switch(afd->a_af) {
255#ifdef INET6
256 case AF_INET6:
257 {
258 int error;
259
260 if ((error = ip6_parsenumeric(sa, addr, host,
261 hostlen,
262 flags)) != 0)
263 return(error);
264 break;
265 }
266#endif
267 default:
268 if (inet_ntop(afd->a_af, addr, host,
269 hostlen) == NULL)
270 return EAI_SYSTEM;
271 break;
272 }
273 }
274 }
275 return(0);
276}
277
278#ifdef INET6
279static int
280ip6_parsenumeric(const struct sockaddr *sa, const char *addr, char *host,
281 size_t hostlen, int flags)
282{
283 int numaddrlen;
284 char numaddr[512];
285
286 if (inet_ntop(AF_INET6, addr, numaddr, sizeof(numaddr)) == NULL)
287 return EAI_SYSTEM;
288
289 numaddrlen = strlen(numaddr);
290 if (numaddrlen + 1 > hostlen) /* don't forget terminator */
291 return EAI_MEMORY;
292 strlcpy(host, numaddr, hostlen);
293
294 if (((const struct sockaddr_in6 *)sa)->sin6_scope_id) {
295 char zonebuf[MAXHOSTNAMELEN];
296 int zonelen;
297
298 zonelen = ip6_sa2str(
299 (const struct sockaddr_in6 *)(const void *)sa,
300 zonebuf, sizeof(zonebuf), flags);
301 if (zonelen < 0)
302 return EAI_MEMORY;
303 if (zonelen + 1 + numaddrlen + 1 > hostlen)
304 return EAI_MEMORY;
305
306 /* construct <numeric-addr><delim><zoneid> */
307 memcpy(host + numaddrlen + 1, zonebuf,
308 (size_t)zonelen);
309 host[numaddrlen] = SCOPE_DELIMITER;
310 host[numaddrlen + 1 + zonelen] = '\0';
311 }
312
313 return 0;
314}
315
316/* ARGSUSED */
317static int
318ip6_sa2str(const struct sockaddr_in6 *sa6, char *buf, size_t bufsiz, int flags)
319{
320 unsigned int ifindex;
321 const struct in6_addr *a6;
322 int n;
323
324 ifindex = (unsigned int)sa6->sin6_scope_id;
325 a6 = &sa6->sin6_addr;
326
327#ifdef notdef
328 if ((flags & NI_NUMERICSCOPE) != 0) {
329 n = snprintf(buf, bufsiz, "%u", sa6->sin6_scope_id);
330 if (n < 0 || n >= bufsiz)
331 return -1;
332 else
333 return n;
334 }
335#endif
336
337 /* if_indextoname() does not take buffer size. not a good api... */
338 if ((IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6)) &&
339 bufsiz >= IF_NAMESIZE) {
340 char *p = if_indextoname(ifindex, buf);
341 if (p) {
342 return(strlen(p));
343 }
344 }
345
346 /* last resort */
347 n = snprintf(buf, bufsiz, "%u", sa6->sin6_scope_id);
348 if (n < 0 || n >= bufsiz)
349 return -1;
350 else
351 return n;
352}
353#endif /* INET6 */
diff --git a/src/lib/libc/net/getnetbyaddr.c b/src/lib/libc/net/getnetbyaddr.c
new file mode 100644
index 0000000000..a85106630c
--- /dev/null
+++ b/src/lib/libc/net/getnetbyaddr.c
@@ -0,0 +1,47 @@
1/* $OpenBSD: getnetbyaddr.c,v 1.8 2005/08/06 20:30:03 espie Exp $ */
2/*
3 * Copyright (c) 1983, 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
31#include <netdb.h>
32
33extern int _net_stayopen;
34
35struct netent *
36_getnetbyaddr(in_addr_t net, int type)
37{
38 struct netent *p;
39
40 setnetent(_net_stayopen);
41 while ((p = getnetent()))
42 if (p->n_addrtype == type && p->n_net == net)
43 break;
44 if (!_net_stayopen)
45 endnetent();
46 return (p);
47}
diff --git a/src/lib/libc/net/getnetbyname.c b/src/lib/libc/net/getnetbyname.c
new file mode 100644
index 0000000000..e6540cf12c
--- /dev/null
+++ b/src/lib/libc/net/getnetbyname.c
@@ -0,0 +1,54 @@
1/* $OpenBSD: getnetbyname.c,v 1.8 2005/08/06 20:30:03 espie Exp $ */
2/*
3 * Copyright (c) 1983, 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
31#include <netdb.h>
32#include <string.h>
33
34extern int _net_stayopen;
35
36struct netent *
37_getnetbyname(const char *name)
38{
39 struct netent *p;
40 char **cp;
41
42 setnetent(_net_stayopen);
43 while ((p = getnetent())) {
44 if (strcasecmp(p->n_name, name) == 0)
45 break;
46 for (cp = p->n_aliases; *cp != 0; cp++)
47 if (strcasecmp(*cp, name) == 0)
48 goto found;
49 }
50found:
51 if (!_net_stayopen)
52 endnetent();
53 return (p);
54}
diff --git a/src/lib/libc/net/getnetent.3 b/src/lib/libc/net/getnetent.3
new file mode 100644
index 0000000000..b337c8c02d
--- /dev/null
+++ b/src/lib/libc/net/getnetent.3
@@ -0,0 +1,140 @@
1.\" $OpenBSD: getnetent.3,v 1.14 2005/07/22 04:50:51 jaredy 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 "const 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 null-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..1bec6fb98c
--- /dev/null
+++ b/src/lib/libc/net/getnetent.c
@@ -0,0 +1,121 @@
1/* $OpenBSD: getnetent.c,v 1.12 2006/01/17 15:37:58 millert Exp $ */
2/*
3 * Copyright (c) 1983, 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
31#include <sys/param.h>
32#include <sys/socket.h>
33#include <netinet/in.h>
34#include <arpa/inet.h>
35#include <netdb.h>
36#include <stdio.h>
37#include <string.h>
38
39#define MAXALIASES 35
40
41static FILE *netf;
42static char line[BUFSIZ+1];
43static struct netent net;
44static char *net_aliases[MAXALIASES];
45int _net_stayopen;
46
47void
48setnetent(int f)
49{
50 if (netf == NULL)
51 netf = fopen(_PATH_NETWORKS, "r" );
52 else
53 rewind(netf);
54 _net_stayopen |= f;
55}
56
57void
58endnetent(void)
59{
60 if (netf) {
61 fclose(netf);
62 netf = NULL;
63 }
64 _net_stayopen = 0;
65}
66
67struct netent *
68getnetent(void)
69{
70 char *p, *cp, **q;
71 size_t len;
72
73 if (netf == NULL && (netf = fopen(_PATH_NETWORKS, "r" )) == NULL)
74 return (NULL);
75again:
76 if ((p = fgetln(netf, &len)) == NULL)
77 return (NULL);
78 if (p[len-1] == '\n')
79 len--;
80 if (len >= sizeof(line) || len == 0)
81 goto again;
82 p = memcpy(line, p, len);
83 line[len] = '\0';
84 if (*p == '#')
85 goto again;
86 if ((cp = strchr(p, '#')) != NULL)
87 *cp = '\0';
88 net.n_name = p;
89 if (strlen(net.n_name) >= MAXHOSTNAMELEN-1)
90 net.n_name[MAXHOSTNAMELEN-1] = '\0';
91 cp = strpbrk(p, " \t");
92 if (cp == NULL)
93 goto again;
94 *cp++ = '\0';
95 while (*cp == ' ' || *cp == '\t')
96 cp++;
97 p = strpbrk(cp, " \t");
98 if (p != NULL)
99 *p++ = '\0';
100 net.n_net = inet_network(cp);
101 net.n_addrtype = AF_INET;
102 q = net.n_aliases = net_aliases;
103 if (p != NULL)
104 cp = p;
105 while (cp && *cp) {
106 if (*cp == ' ' || *cp == '\t') {
107 cp++;
108 continue;
109 }
110 if (q < &net_aliases[MAXALIASES - 1]) {
111 *q++ = cp;
112 if (strlen(cp) >= MAXHOSTNAMELEN-1)
113 cp[MAXHOSTNAMELEN-1] = '\0';
114 }
115 cp = strpbrk(cp, " \t");
116 if (cp != NULL)
117 *cp++ = '\0';
118 }
119 *q = NULL;
120 return (&net);
121}
diff --git a/src/lib/libc/net/getnetnamadr.c b/src/lib/libc/net/getnetnamadr.c
new file mode 100644
index 0000000000..7b770f1ce7
--- /dev/null
+++ b/src/lib/libc/net/getnetnamadr.c
@@ -0,0 +1,384 @@
1/* $OpenBSD: getnetnamadr.c,v 1.26 2005/08/06 20:30:03 espie 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#include <sys/types.h>
64#include <sys/param.h>
65#include <sys/socket.h>
66#include <netinet/in.h>
67#include <arpa/inet.h>
68#include <arpa/nameser.h>
69
70#include <stdio.h>
71#include <netdb.h>
72#include <resolv.h>
73#include <ctype.h>
74#include <errno.h>
75#include <string.h>
76#include <stdlib.h>
77
78#include "thread_private.h"
79
80extern int h_errno;
81
82struct netent *_getnetbyaddr(in_addr_t net, int type);
83struct netent *_getnetbyname(const char *name);
84
85int _hokchar(const char *);
86
87#define BYADDR 0
88#define BYNAME 1
89#define MAXALIASES 35
90
91#define MAXPACKET (64*1024)
92
93typedef union {
94 HEADER hdr;
95 u_char buf[MAXPACKET];
96} querybuf;
97
98typedef union {
99 long al;
100 char ac;
101} align;
102
103static struct netent *
104getnetanswer(querybuf *answer, int anslen, int net_i)
105{
106
107 HEADER *hp;
108 u_char *cp;
109 int n;
110 u_char *eom;
111 int type, class, ancount, qdcount, haveanswer, i, nchar;
112 char aux1[MAXHOSTNAMELEN], aux2[MAXHOSTNAMELEN], ans[MAXHOSTNAMELEN];
113 char *in, *st, *pauxt, *bp, **ap, *ep;
114 char *paux1 = &aux1[0], *paux2 = &aux2[0];
115 static struct netent net_entry;
116 static char *net_aliases[MAXALIASES], netbuf[BUFSIZ+1];
117
118 /*
119 * find first satisfactory answer
120 *
121 * answer --> +------------+ ( MESSAGE )
122 * | Header |
123 * +------------+
124 * | Question | the question for the name server
125 * +------------+
126 * | Answer | RRs answering the question
127 * +------------+
128 * | Authority | RRs pointing toward an authority
129 * | Additional | RRs holding additional information
130 * +------------+
131 */
132 eom = answer->buf + anslen;
133 hp = &answer->hdr;
134 ancount = ntohs(hp->ancount); /* #/records in the answer section */
135 qdcount = ntohs(hp->qdcount); /* #/entries in the question section */
136 bp = netbuf;
137 ep = netbuf + sizeof(netbuf);
138 cp = answer->buf + HFIXEDSZ;
139 if (!qdcount) {
140 if (hp->aa)
141 h_errno = HOST_NOT_FOUND;
142 else
143 h_errno = TRY_AGAIN;
144 return (NULL);
145 }
146 while (qdcount-- > 0) {
147 n = __dn_skipname(cp, eom);
148 if (n < 0 || (cp + n + QFIXEDSZ) > eom) {
149 h_errno = NO_RECOVERY;
150 return(NULL);
151 }
152 cp += n + QFIXEDSZ;
153 }
154 ap = net_aliases;
155 *ap = NULL;
156 net_entry.n_aliases = net_aliases;
157 haveanswer = 0;
158 while (--ancount >= 0 && cp < eom) {
159 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
160#ifdef USE_RESOLV_NAME_OK
161 if ((n < 0) || !res_dnok(bp))
162#else
163 if ((n < 0) || !_hokchar(bp))
164#endif
165 break;
166 cp += n;
167 ans[0] = '\0';
168 strlcpy(&ans[0], bp, sizeof ans);
169 GETSHORT(type, cp);
170 GETSHORT(class, cp);
171 cp += INT32SZ; /* TTL */
172 GETSHORT(n, cp);
173 if (class == C_IN && type == T_PTR) {
174 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
175#ifdef USE_RESOLV_NAME_OK
176 if ((n < 0) || !res_hnok(bp))
177#else
178 if ((n < 0) || !_hokchar(bp))
179#endif
180 {
181 cp += n;
182 return (NULL);
183 }
184 cp += n;
185 if ((ap + 2) < &net_aliases[MAXALIASES]) {
186 *ap++ = bp;
187 bp += strlen(bp) + 1;
188 net_entry.n_addrtype =
189 (class == C_IN) ? AF_INET : AF_UNSPEC;
190 haveanswer++;
191 }
192 }
193 }
194 if (haveanswer) {
195 *ap = NULL;
196 switch (net_i) {
197 case BYADDR:
198 net_entry.n_name = *net_entry.n_aliases;
199 net_entry.n_net = 0L;
200 break;
201 case BYNAME:
202 ap = net_entry.n_aliases;
203 next_alias:
204 in = *ap++;
205 if (in == NULL) {
206 h_errno = HOST_NOT_FOUND;
207 return (NULL);
208 }
209 net_entry.n_name = ans;
210 aux2[0] = '\0';
211 for (i = 0; i < 4; i++) {
212 for (st = in, nchar = 0;
213 isdigit((unsigned char)*st);
214 st++, nchar++)
215 ;
216 if (*st != '.' || nchar == 0 || nchar > 3)
217 goto next_alias;
218 if (i != 0)
219 nchar++;
220 strlcpy(paux1, in, nchar+1);
221 strlcat(paux1, paux2, MAXHOSTNAMELEN);
222 pauxt = paux2;
223 paux2 = paux1;
224 paux1 = pauxt;
225 in = ++st;
226 }
227 if (strcasecmp(in, "IN-ADDR.ARPA") != 0)
228 goto next_alias;
229 net_entry.n_net = inet_network(paux2);
230 break;
231 }
232 net_entry.n_aliases++;
233 return (&net_entry);
234 }
235 h_errno = TRY_AGAIN;
236 return (NULL);
237}
238
239struct netent *
240getnetbyaddr(in_addr_t net, int net_type)
241{
242 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
243 unsigned int netbr[4];
244 int nn, anslen;
245 querybuf *buf;
246 char qbuf[MAXDNAME];
247 in_addr_t net2;
248 struct netent *net_entry = NULL;
249 char lookups[MAXDNSLUS];
250 int i;
251
252 if (_res_init(0) == -1)
253 return(_getnetbyaddr(net, net_type));
254
255 bcopy(_resp->lookups, lookups, sizeof lookups);
256 if (lookups[0] == '\0')
257 strlcpy(lookups, "bf", sizeof lookups);
258
259 for (i = 0; i < MAXDNSLUS && lookups[i]; i++) {
260 switch (lookups[i]) {
261#ifdef YP
262 case 'y':
263 /* There is no YP support. */
264 break;
265#endif /* YP */
266 case 'b':
267 if (net_type != AF_INET)
268 break; /* DNS only supports AF_INET? */
269
270 for (nn = 4, net2 = net; net2; net2 >>= 8)
271 netbr[--nn] = net2 & 0xff;
272 switch (nn) {
273 case 3: /* Class A */
274 snprintf(qbuf, sizeof(qbuf),
275 "0.0.0.%u.in-addr.arpa", netbr[3]);
276 break;
277 case 2: /* Class B */
278 snprintf(qbuf, sizeof(qbuf),
279 "0.0.%u.%u.in-addr.arpa",
280 netbr[3], netbr[2]);
281 break;
282 case 1: /* Class C */
283 snprintf(qbuf, sizeof(qbuf),
284 "0.%u.%u.%u.in-addr.arpa",
285 netbr[3], netbr[2], netbr[1]);
286 break;
287 case 0: /* Class D - E */
288 snprintf(qbuf, sizeof(qbuf),
289 "%u.%u.%u.%u.in-addr.arpa",
290 netbr[3], netbr[2], netbr[1], netbr[0]);
291 break;
292 }
293 buf = malloc(sizeof(*buf));
294 if (buf == NULL)
295 break;
296 anslen = res_query(qbuf, C_IN, T_PTR, buf->buf,
297 sizeof(buf->buf));
298 if (anslen < 0) {
299 free(buf);
300#ifdef DEBUG
301 if (_resp->options & RES_DEBUG)
302 printf("res_query failed\n");
303#endif
304 break;
305 }
306 net_entry = getnetanswer(buf, anslen, BYADDR);
307 free(buf);
308 if (net_entry != NULL) {
309 unsigned u_net = net; /* maybe net should be unsigned ? */
310
311 /* Strip trailing zeros */
312 while ((u_net & 0xff) == 0 && u_net != 0)
313 u_net >>= 8;
314 net_entry->n_net = u_net;
315 return (net_entry);
316 }
317 break;
318 case 'f':
319 net_entry = _getnetbyaddr(net, net_type);
320 if (net_entry != NULL)
321 return (net_entry);
322 }
323 }
324
325 /* Nothing matched. */
326 return (NULL);
327}
328
329struct netent *
330getnetbyname(const char *net)
331{
332 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
333 int anslen;
334 querybuf *buf;
335 char qbuf[MAXDNAME];
336 struct netent *net_entry = NULL;
337 char lookups[MAXDNSLUS];
338 int i;
339
340 if (_res_init(0) == -1)
341 return (_getnetbyname(net));
342
343 bcopy(_resp->lookups, lookups, sizeof lookups);
344 if (lookups[0] == '\0')
345 strlcpy(lookups, "bf", sizeof lookups);
346
347 for (i = 0; i < MAXDNSLUS && lookups[i]; i++) {
348 switch (lookups[i]) {
349#ifdef YP
350 case 'y':
351 /* There is no YP support. */
352 break;
353#endif /* YP */
354 case 'b':
355 strlcpy(qbuf, net, sizeof qbuf);
356 buf = malloc(sizeof(*buf));
357 if (buf == NULL)
358 break;
359 anslen = res_search(qbuf, C_IN, T_PTR, buf->buf,
360 sizeof(buf->buf));
361 if (anslen < 0) {
362 free(buf);
363#ifdef DEBUG
364 if (_resp->options & RES_DEBUG)
365 printf("res_query failed\n");
366#endif
367 break;
368 }
369 net_entry = getnetanswer(buf, anslen, BYNAME);
370 free(buf);
371 if (net_entry != NULL)
372 return (net_entry);
373 break;
374 case 'f':
375 net_entry = _getnetbyname(net);
376 if (net_entry != NULL)
377 return (net_entry);
378 break;
379 }
380 }
381
382 /* Nothing matched. */
383 return (NULL);
384}
diff --git a/src/lib/libc/net/getproto.c b/src/lib/libc/net/getproto.c
new file mode 100644
index 0000000000..07fa33288d
--- /dev/null
+++ b/src/lib/libc/net/getproto.c
@@ -0,0 +1,59 @@
1/* $OpenBSD: getproto.c,v 1.7 2005/08/06 20:30:03 espie Exp $ */
2/*
3 * Copyright (c) 1983, 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
31#include <netdb.h>
32#include <stdio.h>
33
34int
35getprotobynumber_r(int num, struct protoent *pe, struct protoent_data *pd)
36{
37 int error;
38
39 setprotoent_r(pd->stayopen, pd);
40 while ((error = getprotoent_r(pe, pd)) == 0)
41 if (pe->p_proto == num)
42 break;
43 if (!pd->stayopen && pd->fp != NULL) {
44 (void)fclose(pd->fp);
45 pd->fp = NULL;
46 }
47 return (error);
48}
49
50struct protoent *
51getprotobynumber(int num)
52{
53 extern struct protoent_data _protoent_data;
54 static struct protoent proto;
55
56 if (getprotobynumber_r(num, &proto, &_protoent_data) != 0)
57 return (NULL);
58 return (&proto);
59}
diff --git a/src/lib/libc/net/getprotoent.3 b/src/lib/libc/net/getprotoent.3
new file mode 100644
index 0000000000..ea3644f6c9
--- /dev/null
+++ b/src/lib/libc/net/getprotoent.3
@@ -0,0 +1,213 @@
1.\" $OpenBSD: getprotoent.3,v 1.16 2005/07/22 04:50:51 jaredy 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 October 13, 2004
31.Dt GETPROTOENT 3
32.Os
33.Sh NAME
34.Nm getprotoent ,
35.Nm getprotoent_r ,
36.Nm getprotobynumber ,
37.Nm getprotobynumber_r ,
38.Nm getprotobyname ,
39.Nm getprotobyname_r ,
40.Nm setprotoent ,
41.Nm setprotoent_r ,
42.Nm endprotoent ,
43.Nm endprotoent_r
44.Nd get protocol entry
45.Sh SYNOPSIS
46.Fd #include <netdb.h>
47.Ft struct protoent *
48.Fn getprotoent "void"
49.Ft int
50.Fn getprotoent_r "struct protoent *protoent" "struct protoent_data *protoent_data"
51.Ft struct protoent *
52.Fn getprotobyname "const char *name"
53.Ft int
54.Fn getprotobyname_r "const char *name" "struct protoent *protoent" "struct protoent_data *protoent_data"
55.Ft struct protoent *
56.Fn getprotobynumber "int proto"
57.Ft int
58.Fn getprotobynumber_r "int proto" "struct protoent *protoent" "struct protoent_data *protoent_data"
59.Ft void
60.Fn setprotoent "int stayopen"
61.Ft void
62.Fn setprotoent_r "int stayopen" "struct protoent_data *protoent_data"
63.Ft void
64.Fn endprotoent "void"
65.Ft void
66.Fn endprotoent_r "struct protoent_data *protoent_data"
67.Sh DESCRIPTION
68The
69.Fn getprotoent ,
70.Fn getprotobyname ,
71and
72.Fn getprotobynumber
73functions each return a pointer to an object with the following structure
74containing the broken-out fields of a line in the network protocol database,
75.Pa /etc/protocols .
76.Bd -literal -offset indent
77.Pp
78struct protoent {
79 char *p_name; /* official name of protocol */
80 char **p_aliases; /* alias list */
81 int p_proto; /* protocol number */
82};
83.Ed
84.Pp
85The members of this structure are:
86.Bl -tag -width p_aliases
87.It Fa p_name
88The official name of the protocol.
89.It Fa p_aliases
90A null-terminated list of alternate names for the protocol.
91.It Fa p_proto
92The protocol number.
93.El
94.Pp
95The
96.Fn getprotoent
97function reads the next line of the file, opening the file if necessary.
98.Pp
99The
100.Fn setprotoent
101function opens and rewinds the file.
102If the
103.Fa stayopen
104flag is non-zero,
105the protocol database will not be closed after each call to
106.Fn getprotobyname
107or
108.Fn getprotobynumber .
109.Pp
110The
111.Fn endprotoent
112function closes the file.
113.Pp
114The
115.Fn getprotobyname
116and
117.Fn getprotobynumber
118functions sequentially search from the beginning of the file until a
119matching protocol name or protocol number is found, or until
120.Dv EOF
121is encountered.
122.Pp
123The
124.Fn getprotoent_r ,
125.Fn getprotobyport_r ,
126.Fn getprotobyname_r ,
127.Fn setprotoent_r ,
128and
129.Fn endprotoent_r
130functions are reentrant versions of the above functions that take a
131pointer to a
132.Vt protoent_data
133structure which is used to store state information.
134The structure must be zero-filled before it is used
135and should be considered opaque for the sake of portability.
136.Pp
137The
138.Fn getprotoent_r ,
139.Fn getprotobyport_r ,
140and
141.Fn getprotobyname_r
142functions
143also take a pointer to a
144.Vt protoent
145structure which is used to store the results of the database lookup.
146.Sh RETURN VALUES
147The
148.Fn getprotoent ,
149.Fn getprotobyport ,
150and
151.Fn getprotobyname
152functions return a pointer to a
153.Vt protoent
154structure on success or a null pointer if end-of-file
155is reached or an error occurs.
156.Pp
157The
158.Fn getprotoent_r ,
159.Fn getprotobyport_r ,
160and
161.Fn getprotobyname_r
162functions return 0 on success or \-1 if end-of-file
163is reached or an error occurs.
164.Sh FILES
165.Bl -tag -width /etc/protocols -compact
166.It Pa /etc/protocols
167.El
168.Sh SEE ALSO
169.Xr protocols 5
170.Sh STANDARDS
171The
172.Fn getprotoent ,
173.Fn getprotobynumber ,
174.Fn getprotobyname ,
175.Fn setprotoent ,
176and
177.Fn endprotoent
178functions conform to
179.St -p1003.1-2004 .
180.Pp
181The
182.Fn getprotoent_r ,
183.Fn getprotobyport_r ,
184.Fn getprotobyname_r ,
185.Fn setprotoent_r ,
186and
187.Fn endprotoent_r
188functions are not currently standardized.
189This implementation follows the API used by HP, IBM, and Digital.
190.Sh HISTORY
191The
192.Fn getprotoent ,
193.Fn getprotobynumber ,
194.Fn getprotobyname ,
195.Fn setprotoent ,
196and
197.Fn endprotoent
198functions appeared in
199.Bx 4.2 .
200.Pp
201The
202.Fn getprotoent_r ,
203.Fn getprotobyport_r ,
204.Fn getprotobyname_r ,
205.Fn setprotoent_r ,
206and
207.Fn endprotoent_r
208functions appeared in
209.Ox 3.7 .
210.Sh BUGS
211The non-reentrant functions use a static data space; if the data is needed
212for future use, it should be copied before any subsequent calls overwrite it.
213Only 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..7c6ab68166
--- /dev/null
+++ b/src/lib/libc/net/getprotoent.c
@@ -0,0 +1,166 @@
1/* $OpenBSD: getprotoent.c,v 1.9 2006/01/17 15:41:52 millert Exp $ */
2/*
3 * Copyright (c) 1983, 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
31#include <sys/types.h>
32#include <sys/socket.h>
33
34#include <errno.h>
35#include <limits.h>
36#include <netdb.h>
37#include <stdio.h>
38#include <stdlib.h>
39#include <string.h>
40
41void
42setprotoent_r(int f, struct protoent_data *pd)
43{
44 if (pd->fp == NULL)
45 pd->fp = fopen(_PATH_PROTOCOLS, "r" );
46 else
47 rewind(pd->fp);
48 pd->stayopen |= f;
49}
50
51void
52endprotoent_r(struct protoent_data *pd)
53{
54 if (pd->fp) {
55 fclose(pd->fp);
56 pd->fp = NULL;
57 }
58 free(pd->aliases);
59 pd->aliases = NULL;
60 pd->maxaliases = 0;
61 free(pd->line);
62 pd->line = NULL;
63 pd->stayopen = 0;
64}
65
66int
67getprotoent_r(struct protoent *pe, struct protoent_data *pd)
68{
69 char *p, *cp, **q, *endp;
70 size_t len;
71 long l;
72 int serrno;
73
74 if (pd->fp == NULL && (pd->fp = fopen(_PATH_PROTOCOLS, "r" )) == NULL)
75 return (-1);
76again:
77 if ((p = fgetln(pd->fp, &len)) == NULL)
78 return (-1);
79 if (len == 0 || *p == '#' || *p == '\n')
80 goto again;
81 if (p[len-1] == '\n')
82 len--;
83 if ((cp = memchr(p, '#', len)) != NULL)
84 len = cp - p;
85 cp = realloc(pd->line, len + 1);
86 if (cp == NULL)
87 return (-1);
88 pd->line = pe->p_name = memcpy(cp, p, len);
89 cp[len] = '\0';
90 cp = strpbrk(cp, " \t");
91 if (cp == NULL)
92 goto again;
93 *cp++ = '\0';
94 while (*cp == ' ' || *cp == '\t')
95 cp++;
96 p = strpbrk(cp, " \t");
97 if (p != NULL)
98 *p++ = '\0';
99 l = strtol(cp, &endp, 10);
100 if (endp == cp || *endp != '\0' || l < 0 || l >= INT_MAX)
101 goto again;
102 pe->p_proto = l;
103 if (pd->aliases == NULL) {
104 pd->maxaliases = 5;
105 pd->aliases = malloc(pd->maxaliases * sizeof(char *));
106 if (pd->aliases == NULL) {
107 serrno = errno;
108 endprotoent_r(pd);
109 errno = serrno;
110 return (-1);
111 }
112 }
113 q = pe->p_aliases = pd->aliases;
114 if (p != NULL) {
115 cp = p;
116 while (cp && *cp) {
117 if (*cp == ' ' || *cp == '\t') {
118 cp++;
119 continue;
120 }
121 if (q == &pe->p_aliases[pd->maxaliases - 1]) {
122 p = realloc(pe->p_aliases,
123 2 * pd->maxaliases * sizeof(char *));
124 if (p == NULL) {
125 serrno = errno;
126 endprotoent_r(pd);
127 errno = serrno;
128 return (-1);
129 }
130 pd->maxaliases *= 2;
131 q = (char **)p + (q - pe->p_aliases);
132 pe->p_aliases = pd->aliases = (char **)p;
133 }
134 *q++ = cp;
135 cp = strpbrk(cp, " \t");
136 if (cp != NULL)
137 *cp++ = '\0';
138 }
139 }
140 *q = NULL;
141 return (0);
142}
143
144struct protoent_data _protoent_data; /* shared with getproto{,name}.c */
145
146void
147setprotoent(int f)
148{
149 setprotoent_r(f, &_protoent_data);
150}
151
152void
153endprotoent(void)
154{
155 endprotoent_r(&_protoent_data);
156}
157
158struct protoent *
159getprotoent(void)
160{
161 static struct protoent proto;
162
163 if (getprotoent_r(&proto, &_protoent_data) != 0)
164 return (NULL);
165 return (&proto);
166}
diff --git a/src/lib/libc/net/getprotoname.c b/src/lib/libc/net/getprotoname.c
new file mode 100644
index 0000000000..749b6b3f13
--- /dev/null
+++ b/src/lib/libc/net/getprotoname.c
@@ -0,0 +1,67 @@
1/* $OpenBSD: getprotoname.c,v 1.7 2005/08/06 20:30:03 espie Exp $ */
2/*
3 * Copyright (c) 1983, 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
31#include <netdb.h>
32#include <stdio.h>
33#include <string.h>
34
35int
36getprotobyname_r(const char *name, struct protoent *pe,
37 struct protoent_data *pd)
38{
39 char **cp;
40 int error;
41
42 setprotoent_r(pd->stayopen, pd);
43 while ((error = getprotoent_r(pe, pd)) == 0) {
44 if (strcmp(pe->p_name, name) == 0)
45 break;
46 for (cp = pe->p_aliases; *cp != 0; cp++)
47 if (strcmp(*cp, name) == 0)
48 goto found;
49 }
50found:
51 if (!pd->stayopen && pd->fp != NULL) {
52 fclose(pd->fp);
53 pd->fp = NULL;
54 }
55 return (error);
56}
57
58struct protoent *
59getprotobyname(const char *name)
60{
61 extern struct protoent_data _protoent_data;
62 static struct protoent proto;
63
64 if (getprotobyname_r(name, &proto, &_protoent_data) != 0)
65 return (NULL);
66 return (&proto);
67}
diff --git a/src/lib/libc/net/getrrsetbyname.3 b/src/lib/libc/net/getrrsetbyname.3
new file mode 100644
index 0000000000..c951f905ab
--- /dev/null
+++ b/src/lib/libc/net/getrrsetbyname.3
@@ -0,0 +1,166 @@
1.\" $OpenBSD: getrrsetbyname.3,v 1.14 2005/07/22 04:50:51 jaredy 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 freerrset ,
23.Nm getrrsetbyname
24.Nd retrieve DNS records
25.Sh SYNOPSIS
26.Fd #include <netdb.h>
27.Ft int
28.Fn getrrsetbyname "const char *hostname" "unsigned int rdclass" \
29"unsigned int rdtype" "unsigned int flags" "struct rrsetinfo **res"
30.Ft void
31.Fn freerrset "struct rrsetinfo *rrset"
32.Sh DESCRIPTION
33.Fn getrrsetbyname
34gets a set of resource records associated with a
35.Fa hostname ,
36.Fa rdclass ,
37and
38.Fa rdtype .
39.Fa hostname
40is a pointer to a NUL-terminated string.
41The
42.Fa flags
43field is currently unused and must be zero.
44.Pp
45After a successful call to
46.Fn getrrsetbyname ,
47.Fa *res
48is a pointer to an
49.Li rrsetinfo
50structure, containing a list of one or more
51.Li rdatainfo
52structures containing resource records and potentially another list of
53.Li rdatainfo
54structures containing SIG resource records associated with those records.
55The members
56.Li rri_rdclass
57and
58.Li rri_rdtype
59are copied from the parameters.
60.Li rri_ttl
61and
62.Li rri_name
63are properties of the obtained rrset.
64The resource records contained in
65.Li rri_rdatas
66and
67.Li rri_sigs
68are in uncompressed DNS wire format.
69Properties of the rdataset are represented in the
70.Li rri_flags
71bitfield.
72If the
73.Dv RRSET_VALIDATED
74bit is set, the data has been DNSSEC
75validated and the signatures verified.
76.Pp
77The following structures are used:
78.Bd -literal -offset indent
79struct rdatainfo {
80 unsigned int rdi_length; /* length of data */
81 unsigned char *rdi_data; /* record data */
82};
83
84struct rrsetinfo {
85 unsigned int rri_flags; /* RRSET_VALIDATED ... */
86 unsigned int rri_rdclass; /* class number */
87 unsigned int rri_rdtype; /* RR type number */
88 unsigned int rri_ttl; /* time to live */
89 unsigned int rri_nrdatas; /* size of rdatas array */
90 unsigned int rri_nsigs; /* size of sigs array */
91 char *rri_name; /* canonical name */
92 struct rdatainfo *rri_rdatas; /* individual records */
93 struct rdatainfo *rri_sigs; /* individual signatures */
94};
95.Ed
96.Pp
97All of the information returned by
98.Fn getrrsetbyname
99is dynamically allocated: the
100.Li rrsetinfo
101and
102.Li rdatainfo
103structures,
104and the canonical host name strings pointed to by the
105.Li rrsetinfo
106structure.
107Memory allocated for the dynamically allocated structures created by
108a successful call to
109.Fn getrrsetbyname
110is released by
111.Fn freerrset .
112.Li rrset
113is a pointer to a
114.Li struct rrsetinfo
115created by a call to
116.Fn getrrsetbyname .
117.Pp
118If the EDNS0 option is activated in
119.Xr resolv.conf 5 ,
120.Fn getrrsetbyname
121will request DNSSEC authentication using the EDNS0 DNSSEC OK (DO) bit.
122.Sh RETURN VALUES
123.Fn getrrsetbyname
124returns zero on success, and one of the following error
125codes if an error occurred:
126.Pp
127.Bl -tag -width ERRSET_NOMEMORY
128.It Bq Er ERRSET_NONAME
129The name does not exist.
130.It Bq Er ERRSET_NODATA
131The name exists, but does not have data of the desired type.
132.It Bq Er ERRSET_NOMEMORY
133Memory could not be allocated.
134.It Bq Er ERRSET_INVAL
135A parameter is invalid.
136.It Bq Er ERRSET_FAIL
137Other failure.
138.El
139.Sh SEE ALSO
140.Xr resolver 3 ,
141.Xr resolv.conf 5 ,
142.Xr named 8
143.Sh HISTORY
144.Fn getrrsetbyname
145first appeared in
146.Ox 3.0 .
147The API first appeared in ISC BIND version 9.
148.Sh AUTHORS
149.An Jakob Schlyter Aq jakob@openbsd.org
150.Sh CAVEATS
151The
152.Dv RRSET_VALIDATED
153flag in
154.Li rri_flags
155is set if the AD (authenticated data) bit in the DNS answer is
156set.
157This flag
158.Em should not
159be trusted unless the transport between the nameserver and the resolver
160is secure (e.g. IPsec, trusted network, loopback communication).
161.Sh BUGS
162The data in
163.Li *rdi_data
164should be returned in uncompressed wire format.
165Currently, the data is in compressed format and the caller can't
166uncompress 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..e679eb5d96
--- /dev/null
+++ b/src/lib/libc/net/getrrsetbyname.c
@@ -0,0 +1,514 @@
1/* $OpenBSD: getrrsetbyname.c,v 1.10 2005/03/30 02:58:28 tedu 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 = NULL;
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 (_res_init(0) == -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 rrset->rri_name = strdup(response->answer->name);
190 if (rrset->rri_name == NULL) {
191 result = ERRSET_NOMEMORY;
192 goto fail;
193 }
194
195 /* count answers */
196 rrset->rri_nrdatas = count_dns_rr(response->answer, rrset->rri_rdclass,
197 rrset->rri_rdtype);
198 rrset->rri_nsigs = count_dns_rr(response->answer, rrset->rri_rdclass,
199 T_SIG);
200
201 /* allocate memory for answers */
202 rrset->rri_rdatas = calloc(rrset->rri_nrdatas,
203 sizeof(struct rdatainfo));
204 if (rrset->rri_rdatas == NULL) {
205 result = ERRSET_NOMEMORY;
206 goto fail;
207 }
208
209 /* allocate memory for signatures */
210 rrset->rri_sigs = calloc(rrset->rri_nsigs, sizeof(struct rdatainfo));
211 if (rrset->rri_sigs == NULL) {
212 result = ERRSET_NOMEMORY;
213 goto fail;
214 }
215
216 /* copy answers & signatures */
217 for (rr = response->answer, index_ans = 0, index_sig = 0;
218 rr; rr = rr->next) {
219
220 rdata = NULL;
221
222 if (rr->class == rrset->rri_rdclass &&
223 rr->type == rrset->rri_rdtype)
224 rdata = &rrset->rri_rdatas[index_ans++];
225
226 if (rr->class == rrset->rri_rdclass &&
227 rr->type == T_SIG)
228 rdata = &rrset->rri_sigs[index_sig++];
229
230 if (rdata) {
231 rdata->rdi_length = rr->size;
232 rdata->rdi_data = malloc(rr->size);
233
234 if (rdata->rdi_data == NULL) {
235 result = ERRSET_NOMEMORY;
236 goto fail;
237 }
238 memcpy(rdata->rdi_data, rr->rdata, rr->size);
239 }
240 }
241 free_dns_response(response);
242
243 *res = rrset;
244 return (ERRSET_SUCCESS);
245
246fail:
247 if (rrset != NULL)
248 freerrset(rrset);
249 if (response != NULL)
250 free_dns_response(response);
251 return (result);
252}
253
254void
255freerrset(struct rrsetinfo *rrset)
256{
257 u_int16_t i;
258
259 if (rrset == NULL)
260 return;
261
262 if (rrset->rri_rdatas) {
263 for (i = 0; i < rrset->rri_nrdatas; i++) {
264 if (rrset->rri_rdatas[i].rdi_data == NULL)
265 break;
266 free(rrset->rri_rdatas[i].rdi_data);
267 }
268 free(rrset->rri_rdatas);
269 }
270
271 if (rrset->rri_sigs) {
272 for (i = 0; i < rrset->rri_nsigs; i++) {
273 if (rrset->rri_sigs[i].rdi_data == NULL)
274 break;
275 free(rrset->rri_sigs[i].rdi_data);
276 }
277 free(rrset->rri_sigs);
278 }
279
280 if (rrset->rri_name)
281 free(rrset->rri_name);
282 free(rrset);
283}
284
285/*
286 * DNS response parsing routines
287 */
288static struct dns_response *
289parse_dns_response(const u_char *answer, int size)
290{
291 struct dns_response *resp;
292 const u_char *cp;
293
294 /* allocate memory for the response */
295 resp = calloc(1, sizeof(*resp));
296 if (resp == NULL)
297 return (NULL);
298
299 /* initialize current pointer */
300 cp = answer;
301
302 /* copy header */
303 memcpy(&resp->header, cp, HFIXEDSZ);
304 cp += HFIXEDSZ;
305
306 /* fix header byte order */
307 resp->header.qdcount = ntohs(resp->header.qdcount);
308 resp->header.ancount = ntohs(resp->header.ancount);
309 resp->header.nscount = ntohs(resp->header.nscount);
310 resp->header.arcount = ntohs(resp->header.arcount);
311
312 /* there must be at least one query */
313 if (resp->header.qdcount < 1) {
314 free_dns_response(resp);
315 return (NULL);
316 }
317
318 /* parse query section */
319 resp->query = parse_dns_qsection(answer, size, &cp,
320 resp->header.qdcount);
321 if (resp->header.qdcount && resp->query == NULL) {
322 free_dns_response(resp);
323 return (NULL);
324 }
325
326 /* parse answer section */
327 resp->answer = parse_dns_rrsection(answer, size, &cp,
328 resp->header.ancount);
329 if (resp->header.ancount && resp->answer == NULL) {
330 free_dns_response(resp);
331 return (NULL);
332 }
333
334 /* parse authority section */
335 resp->authority = parse_dns_rrsection(answer, size, &cp,
336 resp->header.nscount);
337 if (resp->header.nscount && resp->authority == NULL) {
338 free_dns_response(resp);
339 return (NULL);
340 }
341
342 /* parse additional section */
343 resp->additional = parse_dns_rrsection(answer, size, &cp,
344 resp->header.arcount);
345 if (resp->header.arcount && resp->additional == NULL) {
346 free_dns_response(resp);
347 return (NULL);
348 }
349
350 return (resp);
351}
352
353static struct dns_query *
354parse_dns_qsection(const u_char *answer, int size, const u_char **cp, int count)
355{
356 struct dns_query *head, *curr, *prev;
357 int i, length;
358 char name[MAXDNAME];
359
360 for (i = 1, head = NULL, prev = NULL; i <= count; i++, prev = curr) {
361
362 /* allocate and initialize struct */
363 curr = calloc(1, sizeof(struct dns_query));
364 if (curr == NULL) {
365 free_dns_query(head);
366 return (NULL);
367 }
368 if (head == NULL)
369 head = curr;
370 if (prev != NULL)
371 prev->next = curr;
372
373 /* name */
374 length = dn_expand(answer, answer + size, *cp, name,
375 sizeof(name));
376 if (length < 0) {
377 free_dns_query(head);
378 return (NULL);
379 }
380 curr->name = strdup(name);
381 if (curr->name == NULL) {
382 free_dns_query(head);
383 return (NULL);
384 }
385 *cp += length;
386
387 /* type */
388 curr->type = _getshort(*cp);
389 *cp += INT16SZ;
390
391 /* class */
392 curr->class = _getshort(*cp);
393 *cp += INT16SZ;
394 }
395
396 return (head);
397}
398
399static struct dns_rr *
400parse_dns_rrsection(const u_char *answer, int size, const u_char **cp,
401 int count)
402{
403 struct dns_rr *head, *curr, *prev;
404 int i, length;
405 char name[MAXDNAME];
406
407 for (i = 1, head = NULL, prev = NULL; i <= count; i++, prev = curr) {
408
409 /* allocate and initialize struct */
410 curr = calloc(1, sizeof(struct dns_rr));
411 if (curr == NULL) {
412 free_dns_rr(head);
413 return (NULL);
414 }
415 if (head == NULL)
416 head = curr;
417 if (prev != NULL)
418 prev->next = curr;
419
420 /* name */
421 length = dn_expand(answer, answer + size, *cp, name,
422 sizeof(name));
423 if (length < 0) {
424 free_dns_rr(head);
425 return (NULL);
426 }
427 curr->name = strdup(name);
428 if (curr->name == NULL) {
429 free_dns_rr(head);
430 return (NULL);
431 }
432 *cp += length;
433
434 /* type */
435 curr->type = _getshort(*cp);
436 *cp += INT16SZ;
437
438 /* class */
439 curr->class = _getshort(*cp);
440 *cp += INT16SZ;
441
442 /* ttl */
443 curr->ttl = _getlong(*cp);
444 *cp += INT32SZ;
445
446 /* rdata size */
447 curr->size = _getshort(*cp);
448 *cp += INT16SZ;
449
450 /* rdata itself */
451 curr->rdata = malloc(curr->size);
452 if (curr->rdata == NULL) {
453 free_dns_rr(head);
454 return (NULL);
455 }
456 memcpy(curr->rdata, *cp, curr->size);
457 *cp += curr->size;
458 }
459
460 return (head);
461}
462
463static void
464free_dns_query(struct dns_query *p)
465{
466 if (p == NULL)
467 return;
468
469 if (p->name)
470 free(p->name);
471 free_dns_query(p->next);
472 free(p);
473}
474
475static void
476free_dns_rr(struct dns_rr *p)
477{
478 if (p == NULL)
479 return;
480
481 if (p->name)
482 free(p->name);
483 if (p->rdata)
484 free(p->rdata);
485 free_dns_rr(p->next);
486 free(p);
487}
488
489static void
490free_dns_response(struct dns_response *p)
491{
492 if (p == NULL)
493 return;
494
495 free_dns_query(p->query);
496 free_dns_rr(p->answer);
497 free_dns_rr(p->authority);
498 free_dns_rr(p->additional);
499 free(p);
500}
501
502static int
503count_dns_rr(struct dns_rr *p, u_int16_t class, u_int16_t type)
504{
505 int n = 0;
506
507 while(p) {
508 if (p->class == class && p->type == type)
509 n++;
510 p = p->next;
511 }
512
513 return (n);
514}
diff --git a/src/lib/libc/net/getservbyname.c b/src/lib/libc/net/getservbyname.c
new file mode 100644
index 0000000000..beb8943af6
--- /dev/null
+++ b/src/lib/libc/net/getservbyname.c
@@ -0,0 +1,70 @@
1/* $OpenBSD: getservbyname.c,v 1.10 2005/08/06 20:30:03 espie Exp $ */
2/*
3 * Copyright (c) 1983, 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
31#include <netdb.h>
32#include <stdio.h>
33#include <string.h>
34
35int
36getservbyname_r(const char *name, const char *proto, struct servent *se,
37 struct servent_data *sd)
38{
39 char **cp;
40 int error;
41
42 setservent_r(sd->stayopen, sd);
43 while ((error = getservent_r(se, sd)) == 0) {
44 if (strcmp(name, se->s_name) == 0)
45 goto gotname;
46 for (cp = se->s_aliases; *cp; cp++)
47 if (strcmp(name, *cp) == 0)
48 goto gotname;
49 continue;
50gotname:
51 if (proto == 0 || strcmp(se->s_proto, proto) == 0)
52 break;
53 }
54 if (!sd->stayopen && sd->fp != NULL) {
55 fclose(sd->fp);
56 sd->fp = NULL;
57 }
58 return (error);
59}
60
61struct servent *
62getservbyname(const char *name, const char *proto)
63{
64 extern struct servent_data _servent_data;
65 static struct servent serv;
66
67 if (getservbyname_r(name, proto, &serv, &_servent_data) != 0)
68 return (NULL);
69 return (&serv);
70}
diff --git a/src/lib/libc/net/getservbyport.c b/src/lib/libc/net/getservbyport.c
new file mode 100644
index 0000000000..46679ba366
--- /dev/null
+++ b/src/lib/libc/net/getservbyport.c
@@ -0,0 +1,64 @@
1/* $OpenBSD: getservbyport.c,v 1.7 2005/08/06 20:30:03 espie Exp $ */
2/*
3 * Copyright (c) 1983, 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
31#include <netdb.h>
32#include <stdio.h>
33#include <string.h>
34
35int
36getservbyport_r(int port, const char *proto, struct servent *se,
37 struct servent_data *sd)
38{
39 int error;
40
41 setservent_r(sd->stayopen, sd);
42 while ((error = getservent_r(se, sd)) == 0) {
43 if (se->s_port != port)
44 continue;
45 if (proto == 0 || strcmp(se->s_proto, proto) == 0)
46 break;
47 }
48 if (!sd->stayopen && sd->fp != NULL) {
49 fclose(sd->fp);
50 sd->fp = NULL;
51 }
52 return (error);
53}
54
55struct servent *
56getservbyport(int port, const char *proto)
57{
58 extern struct servent_data _servent_data;
59 static struct servent serv;
60
61 if (getservbyport_r(port, proto, &serv, &_servent_data) != 0)
62 return (NULL);
63 return (&serv);
64}
diff --git a/src/lib/libc/net/getservent.3 b/src/lib/libc/net/getservent.3
new file mode 100644
index 0000000000..839d89de6c
--- /dev/null
+++ b/src/lib/libc/net/getservent.3
@@ -0,0 +1,220 @@
1.\" $OpenBSD: getservent.3,v 1.19 2005/07/22 04:50:51 jaredy 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 October 13, 2004
31.Dt GETSERVENT 3
32.Os
33.Sh NAME
34.Nm getservent ,
35.Nm getservent_r ,
36.Nm getservbyport ,
37.Nm getservbyport_r ,
38.Nm getservbyname ,
39.Nm getservbyname_r ,
40.Nm setservent ,
41.Nm setservent_r ,
42.Nm endservent ,
43.Nm endservent_r
44.Nd get service entry
45.Sh SYNOPSIS
46.Fd #include <netdb.h>
47.Ft struct servent *
48.Fn getservent "void"
49.Ft int
50.Fn getservent_r "struct servent *servent" "struct servent_data *servent_data"
51.Ft struct servent *
52.Fn getservbyname "const char *name" "const char *proto"
53.Ft int
54.Fn getservbyname_r "const char *name" "const char *proto" "struct servent *servent" "struct servent_data *servent_data"
55.Ft struct servent *
56.Fn getservbyport "int port" "const char *proto"
57.Ft int
58.Fn getservbyport_r "int port" "const char *proto" "struct servent *servent" "struct servent_data *servent_data"
59.Ft void
60.Fn setservent "int stayopen"
61.Ft void
62.Fn setservent_r "int stayopen" "struct servent_data *servent_data"
63.Ft void
64.Fn endservent "void"
65.Ft void
66.Fn endservent_r "struct servent_data *servent_data"
67.Sh DESCRIPTION
68The
69.Fn getservent ,
70.Fn getservbyname ,
71and
72.Fn getservbyport
73functions each return a pointer to an object with the following structure
74containing the broken-out fields of a line in the network services database,
75.Pa /etc/services .
76.Bd -literal -offset indent
77struct servent {
78 char *s_name; /* official name of service */
79 char **s_aliases; /* alias list */
80 int s_port; /* port service resides at */
81 char *s_proto; /* protocol to use */
82};
83.Ed
84.Pp
85The members of this structure are:
86.Bl -tag -width s_aliases
87.It Fa s_name
88The official name of the service.
89.It Fa s_aliases
90A null-terminated list of alternate names for the service.
91.It Fa s_port
92The port number at which the service resides.
93Port numbers are returned in network byte order.
94.It Fa s_proto
95The name of the protocol to use when contacting the service.
96.El
97.Pp
98The
99.Fn getservent
100function reads the next line of the file, opening the file if necessary.
101.Pp
102The
103.Fn setservent
104function opens and rewinds the file.
105If the
106.Fa stayopen
107flag is non-zero,
108the services database will not be closed after each call to
109.Fn getservbyname
110or
111.Fn getservbyport .
112.Pp
113The
114.Fn endservent
115function closes the file.
116.Pp
117The
118.Fn getservbyname
119and
120.Fn getservbyport
121functions sequentially search from the beginning of the file until a
122matching protocol name or port number (specified in network byte order)
123is found, or until
124.Dv EOF
125is encountered.
126If a protocol name is also supplied (non-null),
127searches must also match the protocol.
128.Pp
129The
130.Fn getservent_r ,
131.Fn getservbyport_r ,
132.Fn getservbyname_r ,
133.Fn setservent_r ,
134and
135.Fn endservent_r
136functions are reentrant versions of the above functions that take a
137pointer to a
138.Fa servent_data
139structure which is used to store state information.
140The structure must be zero-filled before it is used
141and should be considered opaque for the sake of portability.
142.Pp
143The
144.Fn getservent_r ,
145.Fn getservbyport_r ,
146and
147.Fn getservbyname_r
148functions
149also take a pointer to a
150.Fa servent
151structure which is used to store the results of the database lookup.
152.Sh RETURN VALUES
153The
154.Fn getservent ,
155.Fn getservbyport ,
156and
157.Fn getservbyname
158functions return a pointer to a
159.Fa servent
160structure on success or a null pointer if end-of-file
161is reached or an error occurs.
162.Pp
163The
164.Fn getservent_r ,
165.Fn getservbyport_r ,
166and
167.Fn getservbyname_r
168functions return 0 on success or \-1 if end-of-file
169is reached or an error occurs.
170.Sh FILES
171.Bl -tag -width /etc/services -compact
172.It Pa /etc/services
173.El
174.Sh SEE ALSO
175.Xr getprotoent 3 ,
176.Xr services 5
177.Sh STANDARDS
178The
179.Fn getservent ,
180.Fn getservbynumber ,
181.Fn getservbyname ,
182.Fn setservent ,
183and
184.Fn endservent
185functions conform to
186.St -p1003.1-2004 .
187.Pp
188The
189.Fn getservent_r ,
190.Fn getservbyport_r ,
191.Fn getservbyname_r ,
192.Fn setservent_r ,
193and
194.Fn endservent_r
195functions are not currently standardized.
196This implementation follows the API used by HP, IBM, and Digital.
197.Sh HISTORY
198The
199.Fn getservent ,
200.Fn getservbyport ,
201.Fn getservbyname ,
202.Fn setservent ,
203and
204.Fn endservent
205functions appeared in
206.Bx 4.2 .
207.Pp
208The
209.Fn getservent_r ,
210.Fn getservbyport_r ,
211.Fn getservbyname_r ,
212.Fn setservent_r ,
213and
214.Fn endservent_r
215functions appeared in
216.Ox 3.7 .
217.Sh BUGS
218The non-reentrant functions use static data storage; if the data is needed
219for future use, it should be copied before any subsequent calls overwrite it.
220Expecting 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..ab916b8e80
--- /dev/null
+++ b/src/lib/libc/net/getservent.c
@@ -0,0 +1,168 @@
1/* $OpenBSD: getservent.c,v 1.11 2006/01/17 15:41:52 millert Exp $ */
2/*
3 * Copyright (c) 1983, 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
31#include <sys/types.h>
32#include <sys/socket.h>
33
34#include <errno.h>
35#include <limits.h>
36#include <netdb.h>
37#include <stdio.h>
38#include <string.h>
39#include <stdlib.h>
40
41void
42setservent_r(int f, struct servent_data *sd)
43{
44 if (sd->fp == NULL)
45 sd->fp = fopen(_PATH_SERVICES, "r" );
46 else
47 rewind(sd->fp);
48 sd->stayopen |= f;
49}
50
51void
52endservent_r(struct servent_data *sd)
53{
54 if (sd->fp) {
55 fclose(sd->fp);
56 sd->fp = NULL;
57 }
58 free(sd->aliases);
59 sd->aliases = NULL;
60 sd->maxaliases = 0;
61 free(sd->line);
62 sd->line = NULL;
63 sd->stayopen = 0;
64}
65
66int
67getservent_r(struct servent *se, struct servent_data *sd)
68{
69 char *p, *cp, **q, *endp;
70 size_t len;
71 long l;
72 int serrno;
73
74 if (sd->fp == NULL && (sd->fp = fopen(_PATH_SERVICES, "r" )) == NULL)
75 return (-1);
76again:
77 if ((p = fgetln(sd->fp, &len)) == NULL)
78 return (-1);
79 if (len == 0 || *p == '#' || *p == '\n')
80 goto again;
81 if (p[len-1] == '\n')
82 len--;
83 if ((cp = memchr(p, '#', len)) != NULL)
84 len = cp - p;
85 cp = realloc(sd->line, len + 1);
86 if (cp == NULL)
87 return (-1);
88 sd->line = se->s_name = memcpy(cp, p, len);
89 cp[len] = '\0';
90 p = strpbrk(cp, " \t");
91 if (p == NULL)
92 goto again;
93 *p++ = '\0';
94 while (*p == ' ' || *p == '\t')
95 p++;
96 cp = strpbrk(p, ",/");
97 if (cp == NULL)
98 goto again;
99 *cp++ = '\0';
100 l = strtol(p, &endp, 10);
101 if (endp == p || *endp != '\0' || l < 0 || l > USHRT_MAX)
102 goto again;
103 se->s_port = htons((in_port_t)l);
104 se->s_proto = cp;
105 if (sd->aliases == NULL) {
106 sd->maxaliases = 10;
107 sd->aliases = malloc(sd->maxaliases * sizeof(char *));
108 if (sd->aliases == NULL) {
109 serrno = errno;
110 endservent_r(sd);
111 errno = serrno;
112 return (-1);
113 }
114 }
115 q = se->s_aliases = sd->aliases;
116 cp = strpbrk(cp, " \t");
117 if (cp != NULL)
118 *cp++ = '\0';
119 while (cp && *cp) {
120 if (*cp == ' ' || *cp == '\t') {
121 cp++;
122 continue;
123 }
124 if (q == &se->s_aliases[sd->maxaliases - 1]) {
125 p = realloc(se->s_aliases,
126 2 * sd->maxaliases * sizeof(char *));
127 if (p == NULL) {
128 serrno = errno;
129 endservent_r(sd);
130 errno = serrno;
131 return (-1);
132 }
133 sd->maxaliases *= 2;
134 q = (char **)p + (q - se->s_aliases);
135 se->s_aliases = sd->aliases = (char **)p;
136 }
137 *q++ = cp;
138 cp = strpbrk(cp, " \t");
139 if (cp != NULL)
140 *cp++ = '\0';
141 }
142 *q = NULL;
143 return (0);
144}
145
146struct servent_data _servent_data; /* shared with getservby{name,port}.c */
147
148void
149setservent(int f)
150{
151 setservent_r(f, &_servent_data);
152}
153
154void
155endservent(void)
156{
157 endservent_r(&_servent_data);
158}
159
160struct servent *
161getservent(void)
162{
163 static struct servent serv;
164
165 if (getservent_r(&serv, &_servent_data) != 0)
166 return (NULL);
167 return (&serv);
168}
diff --git a/src/lib/libc/net/herror.c b/src/lib/libc/net/herror.c
new file mode 100644
index 0000000000..7787115a9d
--- /dev/null
+++ b/src/lib/libc/net/herror.c
@@ -0,0 +1,106 @@
1/* $OpenBSD: herror.c,v 1.8 2005/08/06 20:30:03 espie 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#include <sys/types.h>
55#include <sys/param.h>
56#include <sys/uio.h>
57#include <netdb.h>
58#include <unistd.h>
59#include <string.h>
60
61const char * const h_errlist[] = {
62 "Resolver Error 0 (no error)",
63 "Unknown host", /* 1 HOST_NOT_FOUND */
64 "Host name lookup failure", /* 2 TRY_AGAIN */
65 "Unknown server error", /* 3 NO_RECOVERY */
66 "No address associated with name", /* 4 NO_ADDRESS */
67};
68const int h_nerr = { sizeof h_errlist / sizeof h_errlist[0] };
69
70extern int h_errno;
71
72/*
73 * herror --
74 * print the error indicated by the h_errno value.
75 */
76void
77herror(const char *s)
78{
79 struct iovec iov[4];
80 struct iovec *v = iov;
81
82 if (s && *s) {
83 v->iov_base = (char *)s;
84 v->iov_len = strlen(s);
85 v++;
86 v->iov_base = ": ";
87 v->iov_len = 2;
88 v++;
89 }
90 v->iov_base = (char *)hstrerror(h_errno);
91 v->iov_len = strlen(v->iov_base);
92 v++;
93 v->iov_base = "\n";
94 v->iov_len = 1;
95 writev(STDERR_FILENO, iov, (v - iov) + 1);
96}
97
98const char *
99hstrerror(int err)
100{
101 if (err < 0)
102 return ("Resolver internal error");
103 else if (err < h_nerr)
104 return (h_errlist[err]);
105 return ("Unknown resolver error");
106}
diff --git a/src/lib/libc/net/htonl.c b/src/lib/libc/net/htonl.c
new file mode 100644
index 0000000000..5ab4189597
--- /dev/null
+++ b/src/lib/libc/net/htonl.c
@@ -0,0 +1,21 @@
1/* $OpenBSD: htonl.c,v 1.6 2005/08/06 20:30:03 espie Exp $ */
2/*
3 * Written by J.T. Conklin <jtc@netbsd.org>.
4 * Public domain.
5 */
6
7#include <sys/types.h>
8#include <machine/endian.h>
9
10#undef htonl
11
12u_int32_t
13htonl(u_int32_t x)
14{
15#if BYTE_ORDER == LITTLE_ENDIAN
16 u_char *s = (u_char *)&x;
17 return (u_int32_t)(s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3]);
18#else
19 return x;
20#endif
21}
diff --git a/src/lib/libc/net/htons.c b/src/lib/libc/net/htons.c
new file mode 100644
index 0000000000..c8b73fdbb7
--- /dev/null
+++ b/src/lib/libc/net/htons.c
@@ -0,0 +1,21 @@
1/* $OpenBSD: htons.c,v 1.8 2005/08/06 20:30:03 espie Exp $ */
2/*
3 * Written by J.T. Conklin <jtc@netbsd.org>.
4 * Public domain.
5 */
6
7#include <sys/types.h>
8#include <machine/endian.h>
9
10#undef htons
11
12u_int16_t
13htons(u_int16_t x)
14{
15#if BYTE_ORDER == LITTLE_ENDIAN
16 u_char *s = (u_char *) &x;
17 return (u_int16_t)(s[0] << 8 | s[1]);
18#else
19 return x;
20#endif
21}
diff --git a/src/lib/libc/net/if_indextoname.3 b/src/lib/libc/net/if_indextoname.3
new file mode 100644
index 0000000000..da2330b861
--- /dev/null
+++ b/src/lib/libc/net/if_indextoname.3
@@ -0,0 +1,144 @@
1.\" $OpenBSD: if_indextoname.3,v 1.10 2005/12/30 20:45:59 claudio 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 <sys/types.h>
42.Fd #include <sys/socket.h>
43.Fd #include <net/if.h>
44.Ft "unsigned int"
45.Fn if_nametoindex "const char *ifname"
46.Ft "char *"
47.Fn if_indextoname "unsigned int ifindex" "char *ifname"
48.Ft "struct if_nameindex *"
49.Fn if_nameindex "void"
50.Ft "void"
51.Fn if_freenameindex "struct if_nameindex *ptr"
52.Sh DESCRIPTION
53These functions map interface indexes to interface names (such as
54.Dq lo0 ) ,
55and vice versa.
56.Pp
57The
58.Fn if_nametoindex
59function converts an interface name specified by the
60.Fa ifname
61argument to an interface index (positive integer value).
62If the specified interface does not exist, 0 will be returned.
63.Pp
64.Fn if_indextoname
65converts an interface index specified by the
66.Fa ifindex
67argument to an interface name.
68The
69.Fa ifname
70argument must point to a buffer of at least
71.Dv IF_NAMESIZE
72bytes into which the interface name corresponding to the specified index is
73returned.
74.Pf ( Dv IF_NAMESIZE
75is also defined in
76.Aq Pa net/if.h
77and its value includes a terminating NUL byte at the end of the
78interface name.)
79This pointer is also the return value of the function.
80If there is no interface corresponding to the specified index,
81.Dv NULL
82is returned.
83.Pp
84.Fn if_nameindex
85returns an array of
86.Vt if_nameindex
87structures.
88.Vt if_nameindex
89is also defined in
90.Aq Pa net/if.h ,
91and is as follows:
92.Bd -literal -offset indent
93struct if_nameindex {
94 unsigned int if_index; /* 1, 2, ... */
95 char *if_name; /* NUL-terminated name */
96};
97.Ed
98.Pp
99The end of the array of structures is indicated by a structure with
100an
101.Fa if_index
102of 0 and an
103.Fa if_name
104of
105.Dv NULL .
106The function returns a null pointer on error.
107The memory used for this array of structures along with the interface
108names pointed to by the
109.Fa if_name
110members is obtained dynamically.
111This memory is freed by the
112.Fn if_freenameindex
113function.
114.Pp
115.Fn if_freenameindex
116takes a pointer that was returned by
117.Fn if_nameindex
118as argument
119.Pq Fa ptr ,
120and it reclaims the region allocated.
121.Sh DIAGNOSTICS
122.Fn if_nametoindex
123returns 0 on error, positive integer on success.
124.Fn if_indextoname
125and
126.Fn if_nameindex
127return
128.Dv NULL
129on errors.
130.Sh SEE ALSO
131.Xr getifaddrs 3 ,
132.Xr networking 4
133.Rs
134.%A R. Gilligan
135.%A S. Thomson
136.%A J. Bound
137.%A W. Stevens
138.%T Basic Socket Interface Extensions for IPv6
139.%R RFC 2553
140.%D March 1999
141.Re
142.Sh STANDARDS
143These functions are defined in ``Basic Socket Interface Extensions for IPv6''
144.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..f22e4b7d6f
--- /dev/null
+++ b/src/lib/libc/net/inet.3
@@ -0,0 +1,355 @@
1.\" $OpenBSD: inet.3,v 1.19 2005/07/22 04:50:51 jaredy 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;
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; 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..5beec487ac
--- /dev/null
+++ b/src/lib/libc/net/inet6_option_space.3
@@ -0,0 +1,438 @@
1.\" $OpenBSD: inet6_option_space.3,v 1.18 2005/01/11 17:45:41 jaredy Exp $
2.\" $KAME: inet6_option_space.3,v 1.11 2005/01/05 03:00:44 itojun Exp $
3.\"
4.\" Copyright (C) 2004 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.Dd December 23, 2004
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 Option Manipulation
43.\"
44.Sh SYNOPSIS
45.In sys/types.h
46.In netinet/in.h
47.Ft "int"
48.Fn inet6_option_space "int nbytes"
49.Ft "int"
50.Fn inet6_option_init "void *bp" "struct cmsghdr **cmsgp" "int type"
51.Ft "int"
52.Fn inet6_option_append "struct cmsghdr *cmsg" "const u_int8_t *typep" "int multx" "int plusy"
53.Ft "u_int8_t *"
54.Fn inet6_option_alloc "struct cmsghdr *cmsg" "int datalen" "int multx" "int plusy"
55.Ft "int"
56.Fn inet6_option_next "const struct cmsghdr *cmsg" "u_int8_t **tptrp"
57.Ft "int"
58.Fn inet6_option_find "const struct cmsghdr *cmsg" "u_int8_t **tptrp" "int type"
59.\"
60.Sh DESCRIPTION
61.\"
62Manipulating and parsing IPv6's Hop-by-Hop and Destination options is
63complicated by the need to properly align and pad data as well as the
64need to manipulate ancillary information that is not part of the data
65stream.
66RFC 2292 defines a set of functions, which are implemented as
67part of the Kame libraries, to help developers create, change,
68and parse Hop-by-Hop and Destination options.
69All of the prototypes
70for the option functions are defined in the
71.Aq Pa netinet/in.h
72header file.
73.\"
74.Ss inet6_option_space
75In order to determine the amount of space necessary to hold any option
76the
77.Fn inet6_option_space
78function is called.
79It returns the number of bytes required to hold
80an option when it is stored as ancillary data, including the
81.Li cmsghdr
82structure at the beginning, and any necessary padding at the end.
83The
84.Fa nbytes
85argument indicates the size of the structure defining the option,
86and must include any pad bytes at the beginning (the value
87.Li y
88in the alignment term
89.Dq Li "xn + y" ) ,
90the type byte, the length byte, and the option data.
91.Pp
92Note: If multiple options are stored in a single ancillary data
93object, which is the recommended technique, the
94.Fn inet6_option_space
95function overestimates the amount of space required by the size of
96.Li N-1
97.Li cmsghdr
98structures, where
99.Li N
100is the number of options to be stored in the object.
101Usually this has
102no impact because it is assumed that most Hop-by-Hop and Destination
103option headers carry only one option as indicated in appendix B of RFC 2460.
104.\"
105.Ss inet6_option_init
106The
107.Fn inet6_option_init
108function is called to initialize any ancillary data object that will contain
109a Hop-by-Hop or Destination option.
110It returns
111.Li 0
112on success and
113.Li \-1
114when an error occurs.
115.Pp
116The
117.Fa bp
118argument points to a previously allocated area of memory which must be
119large enough to contain all the arguments that the application intends
120to add later via the
121.Fn inet6_option_append
122and
123.Fn inet6_option_alloc
124routines.
125.Pp
126The
127.Fa cmsgp
128argument is a pointer to a pointer to a
129.Li cmsghdr
130structure.
131The
132.Fa *cmsgp
133argument
134points to a
135.Li cmsghdr
136structure which is constructed by this function and stored in the
137area of memory pointed to by
138.Fa bp .
139.Pp
140The
141.Fa type
142is either
143.Dv IPV6_HOPOPTS
144or
145.Dv IPV6_DSTOPTS
146and is stored in the
147.Li cmsg_type
148member of the
149.Li cmsghdr
150structure mentioned above.
151.\"
152.Ss inet6_option_append
153This function appends a Hop-by-Hop option or a Destination option into
154an ancillary data object previously initialized by a call to
155.Fn inet6_option_init .
156The
157.Fn inet6_option_append
158function returns
159.Li 0
160if it succeeds or
161.Li \-1
162when an error occurs.
163.Pp
164The
165.Fa cmsg
166argument is a pointer to the
167.Li cmsghdr
168structure that was initialized by a call to
169.Fn inet6_option_init .
170.Pp
171The
172.Fa typep
173argument is a pointer to the 8-bit option type.
174All options are
175encoded as type-length-value tuples and it is assumed that
176the
177.Fa typep
178field is immediately followed by the 8-bit option data length field,
179which is then followed by the option data.
180.Pp
181The option types of
182.Li 0
183and
184.Li 1
185are reserved for the
186.Li Pad1
187and
188.Li PadN
189options respectively.
190All other values from
191.Li 2
192through
193.Li 255
194are available for applications to use.
195.Pp
196The option data length, since it is stored in 8 bites, must have a
197value between
198.Li 0
199and
200.Li 255 ,
201inclusive.
202.Pp
203The
204.Fa multx
205argument
206is the value
207.Li x
208in the alignment term
209.Dq Li xn + y
210and indicates the byte alignment necessary for the data.
211Alignments may be specified as
212.Li 1 ,
213.Li 2 ,
214.Li 4 ,
215or
216.Li 8
217bytes, which is no alignment, 16-bit, 32-bit and 64-bit alignments
218respectively.
219.Pp
220The
221.Fa plusy
222argument
223is the value
224.Li y
225in the alignment term
226.Dq Li xn + y
227and must have a value between
228.Li 0
229and
230.Li 7 ,
231inclusive, indicating the amount of padding that is necessary for an
232option.
233.\"
234.Ss inet6_option_alloc
235The
236.Fn inet6_option_alloc
237function appends a Hop-by-Hop option or a Destination option into an
238ancillary data object that has previously been initialized by a call to
239.Fn inet6_option_init .
240A successful call to the
241.Fn inet6_option_alloc
242function returns a pointer to the 8-bit option type field,
243which is at the beginning of the allocated region.
244.Fn inet6_option_alloc
245returns
246.Dv NULL
247when an error has occurred.
248.Pp
249The difference between the
250.Fn inet6_option_alloc
251and
252.Fn inet6_option_append
253functions is that the latter copies the contents of a previously built
254option into the ancillary data object while the former returns a
255pointer to the place in the data object where the option's TLV must
256then be built by the application.
257.Pp
258The
259.Fa cmsg
260argument is a pointer to a
261.Li cmsghdr
262structure that was initialized by
263.Fn inet6_option_init .
264.Pp
265The
266.Fa datalen
267argument is the value of the option data length byte for this option.
268This value is required as an argument to allow the function to
269determine if padding must be appended at the end of the option.
270(The
271.Fn inet6_option_append
272function does not need a data length argument
273since the option data length must already be stored by the caller.)
274.Pp
275The
276.Fa multx
277and
278.Fa plusy
279arguments
280are identical to the arguments of the same name described in the
281.Fn inet6_option_init
282function above.
283.\"
284.Ss inet6_option_next
285The
286.Fn inet6_option_next
287function is used to process Hop-by-Hop and Destination options that
288are present in an ancillary data object.
289When an option remains to
290be processed, the return value of the
291.Fn inet6_option_next
292function is
293.Li 0
294and the
295.Fa *tptrp
296argument points to the 8-bit option type field, which is followed by
297the 8-bit option data length, and then the option data.
298When no more
299options remain to be processed, the return value is
300.Li \-1
301and
302.Fa *tptrp
303is
304.Dv NULL .
305When an error occurs, the return value is
306.Li \-1 ,
307but the
308.Fa *tptrp
309argument is not
310.Dv NULL .
311This set of return values allows a program to easily loop through all
312the options in an ancillary data object, checking for the error and
313end of stream conditions along the way.
314.Pp
315When a valid option is returned, the
316.Fa cmsg
317argument points to a
318.Li cmsghdr
319where the
320.Li cmsg_level
321element equals
322.Dv IPPROTO_IPV6
323and the
324.Li cmsg_type
325element is either
326.Dv IPV6_HOPOPTS
327or
328.Dv IPV6_DSTOPTS .
329.Pp
330The
331.Fa tptrp
332argument is a pointer to a pointer to an 8-bit byte and
333.Fa *tptrp
334is used by the function to remember its place in the ancillary data
335object each time the function is called.
336When the
337.Fn inet6_option_next
338function is called for the first time on a given ancillary data object,
339.Fa *tptrp
340must be set to
341.Dv NULL .
342.Pp
343Each time the function returns success,
344the
345.Fa *tptrp
346argument points to the 8-bit option type field for the next option to
347be processed.
348.\"
349.Ss inet6_option_find
350The
351.Fn inet6_option_find
352function allows an application to search for a particular option type
353in an ancillary data object.
354The
355.Fa cmsg
356argument is a pointer to a
357.Li cmsghdr
358structure in which the
359.Li cmsg_level
360element equals
361.Dv IPPROTO_IPV6
362and the
363.Li cmsg_type
364element is either
365.Dv IPV6_HOPOPTS
366or
367.Dv IPV6_DSTOPTS .
368.Pp
369The
370.Fa tptrp
371argument is handled exactly as in the
372.Fn inet6_option_next
373function described above.
374.Pp
375The
376.Fn inet6_option_find
377function starts searching for an option of the specified type
378beginning after the value of
379.Fa *tptrp .
380.\"
381.Sh EXAMPLES
382RFC 2292 gives comprehensive examples in chapter 6.
383.\"
384.Sh DIAGNOSTICS
385The
386.Fn inet6_option_init
387and
388.Fn inet6_option_append
389functions return
390.Li 0
391on success or
392.Li \-1
393on an error.
394.Pp
395The
396.Fn inet6_option_alloc
397function returns
398.Dv NULL
399on an error.
400.Pp
401When
402.Fn inet6_option_next
403or
404.Fn inet6_option_find
405detect an error they return
406.Li \-1 ,
407setting
408.Fa *tptrp
409to a non
410.Dv NULL
411value.
412.\"
413.Sh SEE ALSO
414.Xr inet6 4 ,
415.Xr ip6 4
416.Rs
417.%A W. Stevens
418.%A M. Thomas
419.%T "Advanced Sockets API for IPv6"
420.%N RFC 2292
421.%D February 1998
422.Re
423.Rs
424.%A S. Deering
425.%A R. Hinden
426.%T "Internet Protocol, Version 6 (IPv6) Specification"
427.%N RFC 2460
428.%D December 1998
429.Re
430.\"
431.Sh STANDARDS
432The functions are documented in
433.Dq Advanced Sockets API for IPv6
434(RFC 2292).
435.\"
436.Sh HISTORY
437This implementation first appeared in the KAME advanced networking kit.
438.\"
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..7c00c42e42
--- /dev/null
+++ b/src/lib/libc/net/inet6_rthdr_space.3
@@ -0,0 +1,308 @@
1.\" $OpenBSD: inet6_rthdr_space.3,v 1.17 2005/01/11 17:45:41 jaredy Exp $
2.\" $KAME: inet6_rthdr_space.3,v 1.11 2005/01/05 03:00:44 itojun Exp $
3.\"
4.\" Copyright (C) 2004 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.Dd December 27, 2004
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.In sys/types.h
48.In netinet/in.h
49.Ft size_t
50.Fn inet6_rthdr_space "int type" "int segments"
51.Ft "struct cmsghdr *"
52.Fn inet6_rthdr_init "void *bp" "int type"
53.Ft int
54.Fn inet6_rthdr_add "struct cmsghdr *cmsg" "const struct in6_addr *addr" "unsigned int flags"
55.Ft int
56.Fn inet6_rthdr_lasthop "struct cmsghdr *cmsg" "unsigned int flags"
57.Ft int
58.Fn inet6_rthdr_reverse "const struct cmsghdr *in" "struct cmsghdr *out"
59.Ft int
60.Fn inet6_rthdr_segments "const struct cmsghdr *cmsg"
61.Ft "struct in6_addr *"
62.Fn inet6_rthdr_getaddr "struct cmsghdr *cmsg" "int index"
63.Ft int
64.Fn inet6_rthdr_getflags "const struct cmsghdr *cmsg" "int index"
65.\"
66.Sh DESCRIPTION
67.\"The RFC 2292 IPv6 Advanced API has been deprecated in favor of the
68.\"newer, RFC 3542 APIs.
69.\"On platforms that support it, currently only
70.\"FreeBSD, please use the newer API to manipulate routing header
71.\"options.
72.\".Pp
73The RFC 2292 IPv6 Advanced API defined eight functions for
74applications to use for building and parsing routing headers.
75The
76eight functions are split into two groups, the first of which builds
77the header and the second of which can parse it.
78The function prototypes for these functions are all in the
79.Aq Pa netinet/in.h
80header.
81Although direct manipulation of a routing header is possible,
82this set of APIs make it unnecessary and such direct manipulation
83should be avoided so that changes to the underlying structures do not
84break applications.
85.Pp
86Please note that RFC 2292 uses the term
87.Dq segments
88instead of the term
89.Dq addresses
90but they are considered equivalent for this manual page.
91.\"
92.Ss inet6_rthdr_space
93The
94.Fn inet6_rthdr_space
95function returns the number of bytes required to hold a routing header
96of the specified
97.Fa type
98and containing the specified number of
99.Fa segments .
100Only one
101.Fa type
102is supported,
103.Dv IPV6_RTHDR_TYPE_0 ,
104and it can hold from 1 to 23 segments.
105The return value includes the
106size of the
107.Vt cmsghdr
108structure that precedes the routing header and
109any required padding.
110.Pp
111A return value of 0 indicates an error.
112Either the type was specified
113incorrectly, or the number of segments was less than one or greater
114than 23.
115.Pp
116Note: The
117.Fn inet6_rthdr_space
118function only returns the size required by the routing header and does
119not allocate memory for the caller.
120.\"
121.Ss inet6_rthdr_init
122The
123.Fn inet6_rthdr_init
124function initializes a buffer, pointed to by
125.Fa bp
126with an appropriate
127.Li cmsghdr
128structure followed by a routing header of the specified
129.Fa type .
130.Pp
131The caller must use the
132.Fn inet6_rthdr_space
133function to determine the size of the buffer, and then allocate that
134buffer before calling
135.Fn inet6_rthdr_init .
136.Pp
137The return value is a pointer to a
138.Li cmsghdr
139structure, which is used as the first argument to the
140.Fn inet6_rthdr_add
141and
142.Fn inet6_rthdr_lasthop
143functions in order to construct the routing header.
144When an error occurs the return value is
145.Dv NULL .
146.\"
147.Ss inet6_rthdr_add
148The
149.Fn inet6_rthdr_add
150function adds the IPv6 address pointed to by
151.Fa addr
152to the end of the
153routing header being constructed and sets the type of this address to the
154value of
155.Fa flags .
156The
157.Fa flags
158must be either
159.Dv IPV6_RTHDR_LOOSE
160or
161.Dv IPV6_RTHDR_STRICT
162indicating whether loose or strict source routing is required.
163.Pp
164When the function succeeds it returns 0, otherwise \-1 is returned.
165.\"
166.Ss inet6_rthdr_lasthop
167The
168.Fn inet6_rthdr_lasthop
169function specifies the strict or loose flag for the final hop of a
170routing header.
171The
172.Fa flags
173argument must be either
174.Dv IPV6_RTHDR_LOOSE
175or
176.Dv IPV6_RTHDR_STRICT .
177.Pp
178The return value of the function is 0 upon success, and \-1 when an
179error has occurred.
180.Pp
181Please note that a routing header specifying
182.Li N
183intermediate nodes requires
184.Li N+1
185strict or loose flags meaning that
186.Fn inet6_rthdr_add
187must be called
188.Li N
189times and then
190.Fn inet6_rthdr_lasthop
191must be called once.
192.\"
193.Ss inet6_rthdr_reverse
194This function was never implemented.
195.Pp
196The following three functions provide an API for parsing a received
197routing header:
198.\"
199.Ss inet6_rthdr_segments
200The
201.Fn inet6_rthdr_segments
202function returns the number of segments contained in the routing
203header pointed to by the
204.Fa cmsg
205argument.
206On success the return value is from 1 to 23.
207When an error occurs, \-1 is returned.
208.\"
209.Ss inet6_rthdr_getaddr
210The
211.Fn inet6_rthdr_getaddr
212function returns a pointer to the IPv6 address specified by the
213.Fa index
214argument from the routing header pointed to by
215.Fa cmsg .
216The index must be between 1 and the number returned by
217.Fn inet6_rthdr_segments ,
218described above.
219An application must call
220.Fn inet6_rthdr_segments
221to obtain the number of segments in the routing header.
222.Pp
223If an error occurs,
224.Dv NULL
225is returned.
226.\"
227.Ss inet6_rthdr_getflags
228The
229.Fn inet6_rthdr_getflags
230function returns the flags value of the segment specified by
231.Fa index
232of the routing header pointed to by
233.Fa cmsg .
234The
235.Fa index
236argument must be between 0 and the value returned by
237.Fn inet6_rthdr_segments .
238The return value will be either
239.Dv IPV6_RTHDR_LOOSE
240or
241.Dv IPV6_RTHDR_STRICT
242indicating whether loose or strict source routing was requested for
243that segment.
244.Pp
245When an error occurs, \-1 is returned.
246.Pp
247Note: Flags begin at index 0 while segments begin at index 1, to
248maintain consistency with the terminology and figures in RFC 2460.
249.\"
250.Sh EXAMPLES
251RFC 2292 gives comprehensive examples in chapter 8.
252.\"
253.Sh DIAGNOSTICS
254The
255.Fn inet6_rthdr_space
256function returns 0 when an error occurs.
257.Pp
258The
259.Fn inet6_rthdr_add
260and
261.Fn inet6_rthdr_lasthop
262functions return 0 on success, and \-1 on error.
263.Pp
264The
265.Fn inet6_rthdr_init
266and
267.Fn inet6_rthdr_getaddr
268functions
269return
270.Dv NULL
271on error.
272.Pp
273The
274.Fn inet6_rthdr_segments
275and
276.Fn inet6_rthdr_getflags
277functions return \-1 on error.
278.\"
279.Sh SEE ALSO
280.Xr inet6 4 ,
281.Xr ip6 4
282.Rs
283.%A W. Stevens
284.%A M. Thomas
285.%T "Advanced Sockets API for IPv6"
286.%N RFC 2292
287.%D February 1998
288.Re
289.Rs
290.%A S. Deering
291.%A R. Hinden
292.%T "Internet Protocol, Version 6 (IPv6) Specification"
293.%N RFC 2460
294.%D December 1998
295.Re
296.\"
297.Sh HISTORY
298This implementation first appeared in the KAME advanced networking kit.
299.\"
300.Sh BUGS
301The
302.Fn inet6_rthdr_reverse
303function was never implemented.
304.\".Pp
305.\"This API is deprecated in favor of
306.\".Xr inet6_rth_space 3
307.\".Sh SEE ALSO
308.\".Xr inet6_rth_space 3
diff --git a/src/lib/libc/net/inet_addr.c b/src/lib/libc/net/inet_addr.c
new file mode 100644
index 0000000000..c962a03382
--- /dev/null
+++ b/src/lib/libc/net/inet_addr.c
@@ -0,0 +1,171 @@
1/* $OpenBSD: inet_addr.c,v 1.9 2005/08/06 20:30:03 espie 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#include <sys/types.h>
55#include <sys/param.h>
56#include <netinet/in.h>
57#include <arpa/inet.h>
58#include <ctype.h>
59
60/*
61 * Ascii internet address interpretation routine.
62 * The value returned is in network order.
63 */
64in_addr_t
65inet_addr(const char *cp)
66{
67 struct in_addr val;
68
69 if (inet_aton(cp, &val))
70 return (val.s_addr);
71 return (INADDR_NONE);
72}
73
74/*
75 * Check whether "cp" is a valid ascii representation
76 * of an Internet address and convert to a binary address.
77 * Returns 1 if the address is valid, 0 if not.
78 * This replaces inet_addr, the return value from which
79 * cannot distinguish between failure and a local broadcast address.
80 */
81int
82inet_aton(const char *cp, struct in_addr *addr)
83{
84 in_addr_t val;
85 int base, n;
86 char c;
87 u_int parts[4];
88 u_int *pp = parts;
89
90 c = *cp;
91 for (;;) {
92 /*
93 * Collect number up to ``.''.
94 * Values are specified as for C:
95 * 0x=hex, 0=octal, isdigit=decimal.
96 */
97 if (!isdigit(c))
98 return (0);
99 val = 0; base = 10;
100 if (c == '0') {
101 c = *++cp;
102 if (c == 'x' || c == 'X')
103 base = 16, c = *++cp;
104 else
105 base = 8;
106 }
107 for (;;) {
108 if (isascii(c) && isdigit(c)) {
109 val = (val * base) + (c - '0');
110 c = *++cp;
111 } else if (base == 16 && isascii(c) && isxdigit(c)) {
112 val = (val << 4) |
113 (c + 10 - (islower(c) ? 'a' : 'A'));
114 c = *++cp;
115 } else
116 break;
117 }
118 if (c == '.') {
119 /*
120 * Internet format:
121 * a.b.c.d
122 * a.b.c (with c treated as 16 bits)
123 * a.b (with b treated as 24 bits)
124 */
125 if (pp >= parts + 3)
126 return (0);
127 *pp++ = val;
128 c = *++cp;
129 } else
130 break;
131 }
132 /*
133 * Check for trailing characters.
134 */
135 if (c != '\0' && (!isascii(c) || !isspace(c)))
136 return (0);
137 /*
138 * Concoct the address according to
139 * the number of parts specified.
140 */
141 n = pp - parts + 1;
142 switch (n) {
143
144 case 0:
145 return (0); /* initial nondigit */
146
147 case 1: /* a -- 32 bits */
148 break;
149
150 case 2: /* a.b -- 8.24 bits */
151 if ((val > 0xffffff) || (parts[0] > 0xff))
152 return (0);
153 val |= parts[0] << 24;
154 break;
155
156 case 3: /* a.b.c -- 8.8.16 bits */
157 if ((val > 0xffff) || (parts[0] > 0xff) || (parts[1] > 0xff))
158 return (0);
159 val |= (parts[0] << 24) | (parts[1] << 16);
160 break;
161
162 case 4: /* a.b.c.d -- 8.8.8.8 bits */
163 if ((val > 0xff) || (parts[0] > 0xff) || (parts[1] > 0xff) || (parts[2] > 0xff))
164 return (0);
165 val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
166 break;
167 }
168 if (addr)
169 addr->s_addr = htonl(val);
170 return (1);
171}
diff --git a/src/lib/libc/net/inet_lnaof.c b/src/lib/libc/net/inet_lnaof.c
new file mode 100644
index 0000000000..b1a58cd2c1
--- /dev/null
+++ b/src/lib/libc/net/inet_lnaof.c
@@ -0,0 +1,51 @@
1/* $OpenBSD: inet_lnaof.c,v 1.6 2005/08/06 20:30:03 espie Exp $ */
2/*
3 * Copyright (c) 1983, 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
31#include <sys/param.h>
32#include <netinet/in.h>
33#include <arpa/inet.h>
34
35/*
36 * Return the local network address portion of an
37 * internet address; handles class a/b/c network
38 * number formats.
39 */
40in_addr_t
41inet_lnaof(struct in_addr in)
42{
43 in_addr_t i = ntohl(in.s_addr);
44
45 if (IN_CLASSA(i))
46 return ((i)&IN_CLASSA_HOST);
47 else if (IN_CLASSB(i))
48 return ((i)&IN_CLASSB_HOST);
49 else
50 return ((i)&IN_CLASSC_HOST);
51}
diff --git a/src/lib/libc/net/inet_makeaddr.c b/src/lib/libc/net/inet_makeaddr.c
new file mode 100644
index 0000000000..87d9325231
--- /dev/null
+++ b/src/lib/libc/net/inet_makeaddr.c
@@ -0,0 +1,54 @@
1/* $OpenBSD: inet_makeaddr.c,v 1.6 2005/08/06 20:30:03 espie Exp $ */
2/*
3 * Copyright (c) 1983, 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
31#include <sys/param.h>
32#include <netinet/in.h>
33#include <arpa/inet.h>
34
35/*
36 * Formulate an Internet address from network + host. Used in
37 * building addresses stored in the ifnet structure.
38 */
39struct in_addr
40inet_makeaddr(in_addr_t net, in_addr_t host)
41{
42 in_addr_t addr;
43
44 if (net < 128)
45 addr = (net << IN_CLASSA_NSHIFT) | (host & IN_CLASSA_HOST);
46 else if (net < 65536)
47 addr = (net << IN_CLASSB_NSHIFT) | (host & IN_CLASSB_HOST);
48 else if (net < 16777216L)
49 addr = (net << IN_CLASSC_NSHIFT) | (host & IN_CLASSC_HOST);
50 else
51 addr = net | host;
52 addr = htonl(addr);
53 return (*(struct in_addr *)&addr);
54}
diff --git a/src/lib/libc/net/inet_net.3 b/src/lib/libc/net/inet_net.3
new file mode 100644
index 0000000000..a763bb12a5
--- /dev/null
+++ b/src/lib/libc/net/inet_net.3
@@ -0,0 +1,183 @@
1.\" $OpenBSD: inet_net.3,v 1.12 2005/12/30 20:45:59 claudio 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/types.h>
47.Fd #include <sys/socket.h>
48.Fd #include <netinet/in.h>
49.Fd #include <arpa/inet.h>
50.Ft char *
51.Fn inet_net_ntop "int af" "const void *src" "int bits" "char *dst" "size_t size"
52.Ft int
53.Fn inet_net_pton "int af" "const char *src" "void *dst" "size_t size"
54.Sh DESCRIPTION
55The
56.Fn inet_net_ntop
57function converts an Internet network number from network format (usually a
58.Li struct in_addr
59or some other binary form, in network byte order) to CIDR presentation format
60(suitable for external display purposes).
61.Fa bits
62is the number of bits in
63.Fa src
64that are the network number.
65It returns
66.Dv NULL
67if a system error occurs (in which case,
68.Va errno
69will have been set), or it returns a pointer to the destination string.
70.Pp
71The
72.Fn inet_net_pton
73function converts a presentation format Internet network number (that is,
74printable form as held in a character string) to network format (usually a
75.Li struct in_addr
76or some other internal binary representation, in network byte order).
77It returns the number of bits (either computed based on the class, or
78specified with /CIDR), or \-1 if a failure occurred
79(in which case
80.Va errno
81will have been set.
82It will be set to
83.Er ENOENT
84if the Internet network number was not valid).
85.Pp
86Caution:
87The
88.Fa dst
89field should be zeroed before calling
90.Fn inet_net_pton
91as the function will only fill the number of bytes necessary to
92encode the network number in network byte order.
93.Pp
94The only value for
95.Fa af
96currently supported is
97.Dv AF_INET .
98.Fa size
99is the size of the result buffer
100.Fa dst .
101.Sh NETWORK NUMBERS (IP VERSION 4)
102The external representation of Internet network numbers may be specified in
103one of the following forms:
104.Bd -literal -offset indent
105a
106a.b
107a.b.c
108a.b.c.d
109.Ed
110.Pp
111Any of the above four forms may have
112.Dq Li /bits
113appended where
114.Dq Li bits
115is in the range
116.Li 0-32
117and is used to explicitly specify the number of bits in the network address.
118When
119.Dq Li /bits
120is not specified the number of bits in the network address is calculated
121as the larger of the number of bits in the class to which the address
122belongs and the number of bits provided rounded up modulo 8.
123Examples:
124.Pp
125.Bl -tag -width 10.1.2.3/24 -offset indent -compact
126.It Li 10
127an 8-bit network number (class A), value
128.Li 10.0.0.0 .
129.It Li 192
130a 24-bit network number (class C), value
131.Li 192.0.0.0 .
132.It Li 10.10
133a 16-bit network number, value
134.Li 10.10.0.0 .
135.It Li 10.1.2
136a 24-bit network number, value
137.Li 10.1.2.0 .
138.It Li 10.1.2.3
139a 32-bit network number, value
140.Li 10.1.2.3 .
141.It Li 10.1.2.3/24
142a 24-bit network number (explicit), value
143.Li 10.1.2.3 .
144.El
145.Pp
146Note that when the number of bits is specified using
147.Dq Li /bits
148notation, the value of the address still includes all bits supplied
149in the external representation, even those bits which are the host
150part of an Internet address.
151Also, unlike
152.Xr inet_pton 3
153where the external representation is assumed to be a host address, the
154external representation for
155.Fn inet_net_pton
156is assumed to be a network address.
157Thus
158.Dq Li 10.1
159is assumed to be
160.Dq Li 10.1.0.0
161not
162.Dq Li 10.0.0.1
163.Pp
164All numbers supplied as
165.Dq parts
166in a
167.Ql \&.
168notation
169may be decimal, octal, or hexadecimal, as specified
170in the C language (i.e., a leading 0x or 0X implies
171hexadecimal; otherwise, a leading 0 implies octal;
172otherwise, the number is interpreted as decimal).
173.Sh SEE ALSO
174.Xr byteorder 3 ,
175.Xr inet 3 ,
176.Xr inet_pton 3 ,
177.Xr networks 5
178.Sh HISTORY
179The
180.Nm inet_net_ntop
181and
182.Nm inet_net_pton
183functions 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..fc9071798a
--- /dev/null
+++ b/src/lib/libc/net/inet_net_ntop.c
@@ -0,0 +1,135 @@
1/* $OpenBSD: inet_net_ntop.c,v 1.6 2005/08/06 20:30:03 espie 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#include <sys/types.h>
21#include <sys/socket.h>
22#include <netinet/in.h>
23#include <arpa/inet.h>
24
25#include <errno.h>
26#include <stdio.h>
27#include <string.h>
28#include <stdlib.h>
29
30static char *inet_net_ntop_ipv4(const u_char *, int, char *, size_t);
31
32/*
33 * char *
34 * inet_net_ntop(af, src, bits, dst, size)
35 * convert network number from network to presentation format.
36 * generates CIDR style result always.
37 * return:
38 * pointer to dst, or NULL if an error occurred (check errno).
39 * author:
40 * Paul Vixie (ISC), July 1996
41 */
42char *
43inet_net_ntop(int af, const void *src, int bits, char *dst, size_t size)
44{
45 switch (af) {
46 case AF_INET:
47 return (inet_net_ntop_ipv4(src, bits, dst, size));
48 default:
49 errno = EAFNOSUPPORT;
50 return (NULL);
51 }
52}
53
54/*
55 * static char *
56 * inet_net_ntop_ipv4(src, bits, dst, size)
57 * convert IPv4 network number from network to presentation format.
58 * generates CIDR style result always.
59 * return:
60 * pointer to dst, or NULL if an error occurred (check errno).
61 * note:
62 * network byte order assumed. this means 192.5.5.240/28 has
63 * 0x11110000 in its fourth octet.
64 * author:
65 * Paul Vixie (ISC), July 1996
66 */
67static char *
68inet_net_ntop_ipv4(const u_char *src, int bits, char *dst, size_t size)
69{
70 char *odst = dst;
71 u_int m;
72 int b;
73 char *ep;
74 int advance;
75
76 ep = dst + size;
77 if (ep <= dst)
78 goto emsgsize;
79
80 if (bits < 0 || bits > 32) {
81 errno = EINVAL;
82 return (NULL);
83 }
84 if (bits == 0) {
85 if (ep - dst < sizeof "0")
86 goto emsgsize;
87 *dst++ = '0';
88 *dst = '\0';
89 }
90
91 /* Format whole octets. */
92 for (b = bits / 8; b > 0; b--) {
93 if (ep - dst < sizeof "255.")
94 goto emsgsize;
95 advance = snprintf(dst, ep - dst, "%u", *src++);
96 if (advance <= 0 || advance >= ep - dst)
97 goto emsgsize;
98 dst += advance;
99 if (b > 1) {
100 if (dst + 1 >= ep)
101 goto emsgsize;
102 *dst++ = '.';
103 *dst = '\0';
104 }
105 }
106
107 /* Format partial octet. */
108 b = bits % 8;
109 if (b > 0) {
110 if (ep - dst < sizeof ".255")
111 goto emsgsize;
112 if (dst != odst)
113 if (dst + 1 >= ep)
114 goto emsgsize;
115 *dst++ = '.';
116 m = ((1 << b) - 1) << (8 - b);
117 advance = snprintf(dst, ep - dst, "%u", *src & m);
118 if (advance <= 0 || advance >= ep - dst)
119 goto emsgsize;
120 dst += advance;
121 }
122
123 /* Format CIDR /width. */
124 if (ep - dst < sizeof "/32")
125 goto emsgsize;
126 advance = snprintf(dst, ep - dst, "/%u", bits);
127 if (advance <= 0 || advance >= ep - dst)
128 goto emsgsize;
129 dst += advance;
130 return (odst);
131
132 emsgsize:
133 errno = EMSGSIZE;
134 return (NULL);
135}
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..9bb35478ca
--- /dev/null
+++ b/src/lib/libc/net/inet_net_pton.c
@@ -0,0 +1,191 @@
1/* $OpenBSD: inet_net_pton.c,v 1.5 2005/08/06 20:30:03 espie 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#include <sys/types.h>
21#include <sys/socket.h>
22#include <netinet/in.h>
23#include <arpa/inet.h>
24
25#include <assert.h>
26#include <ctype.h>
27#include <errno.h>
28#include <stdio.h>
29#include <string.h>
30#include <stdlib.h>
31
32static int inet_net_pton_ipv4(const char *, u_char *, size_t);
33
34/*
35 * static int
36 * inet_net_pton(af, src, dst, size)
37 * convert network number from presentation to network format.
38 * accepts hex octets, hex strings, decimal octets, and /CIDR.
39 * "size" is in bytes and describes "dst".
40 * return:
41 * number of bits, either imputed classfully or specified with /CIDR,
42 * or -1 if some failure occurred (check errno). ENOENT means it was
43 * not a valid network specification.
44 * author:
45 * Paul Vixie (ISC), June 1996
46 */
47int
48inet_net_pton(int af, const char *src, void *dst, size_t size)
49{
50 switch (af) {
51 case AF_INET:
52 return (inet_net_pton_ipv4(src, dst, size));
53 default:
54 errno = EAFNOSUPPORT;
55 return (-1);
56 }
57}
58
59/*
60 * static int
61 * inet_net_pton_ipv4(src, dst, size)
62 * convert IPv4 network number from presentation to network format.
63 * accepts hex octets, hex strings, decimal octets, and /CIDR.
64 * "size" is in bytes and describes "dst".
65 * return:
66 * number of bits, either imputed classfully or specified with /CIDR,
67 * or -1 if some failure occurred (check errno). ENOENT means it was
68 * not an IPv4 network specification.
69 * note:
70 * network byte order assumed. this means 192.5.5.240/28 has
71 * 0x11110000 in its fourth octet.
72 * author:
73 * Paul Vixie (ISC), June 1996
74 */
75static int
76inet_net_pton_ipv4(const char *src, u_char *dst, size_t size)
77{
78 static const char
79 xdigits[] = "0123456789abcdef",
80 digits[] = "0123456789";
81 int n, ch, tmp, dirty, bits;
82 const u_char *odst = dst;
83
84 ch = *src++;
85 if (ch == '0' && (src[0] == 'x' || src[0] == 'X')
86 && isascii(src[1]) && isxdigit(src[1])) {
87 /* Hexadecimal: Eat nybble string. */
88 if (size <= 0)
89 goto emsgsize;
90 *dst = 0, dirty = 0;
91 src++; /* skip x or X. */
92 while ((ch = *src++) != '\0' &&
93 isascii(ch) && isxdigit(ch)) {
94 if (isupper(ch))
95 ch = tolower(ch);
96 n = strchr(xdigits, ch) - xdigits;
97 assert(n >= 0 && n <= 15);
98 *dst |= n;
99 if (!dirty++)
100 *dst <<= 4;
101 else if (size-- > 0)
102 *++dst = 0, dirty = 0;
103 else
104 goto emsgsize;
105 }
106 if (dirty)
107 size--;
108 } else if (isascii(ch) && isdigit(ch)) {
109 /* Decimal: eat dotted digit string. */
110 for (;;) {
111 tmp = 0;
112 do {
113 n = strchr(digits, ch) - digits;
114 assert(n >= 0 && n <= 9);
115 tmp *= 10;
116 tmp += n;
117 if (tmp > 255)
118 goto enoent;
119 } while ((ch = *src++) != '\0' &&
120 isascii(ch) && isdigit(ch));
121 if (size-- <= 0)
122 goto emsgsize;
123 *dst++ = (u_char) tmp;
124 if (ch == '\0' || ch == '/')
125 break;
126 if (ch != '.')
127 goto enoent;
128 ch = *src++;
129 if (!isascii(ch) || !isdigit(ch))
130 goto enoent;
131 }
132 } else
133 goto enoent;
134
135 bits = -1;
136 if (ch == '/' && isascii(src[0]) && isdigit(src[0]) && dst > odst) {
137 /* CIDR width specifier. Nothing can follow it. */
138 ch = *src++; /* Skip over the /. */
139 bits = 0;
140 do {
141 n = strchr(digits, ch) - digits;
142 assert(n >= 0 && n <= 9);
143 bits *= 10;
144 bits += n;
145 } while ((ch = *src++) != '\0' &&
146 isascii(ch) && isdigit(ch));
147 if (ch != '\0')
148 goto enoent;
149 if (bits > 32)
150 goto emsgsize;
151 }
152
153 /* Firey death and destruction unless we prefetched EOS. */
154 if (ch != '\0')
155 goto enoent;
156
157 /* If nothing was written to the destination, we found no address. */
158 if (dst == odst)
159 goto enoent;
160 /* If no CIDR spec was given, infer width from net class. */
161 if (bits == -1) {
162 if (*odst >= 240) /* Class E */
163 bits = 32;
164 else if (*odst >= 224) /* Class D */
165 bits = 4;
166 else if (*odst >= 192) /* Class C */
167 bits = 24;
168 else if (*odst >= 128) /* Class B */
169 bits = 16;
170 else /* Class A */
171 bits = 8;
172 /* If imputed mask is narrower than specified octets, widen. */
173 if (bits < ((dst - odst) * 8))
174 bits = (dst - odst) * 8;
175 }
176 /* Extend network to cover the actual mask. */
177 while (bits > ((dst - odst) * 8)) {
178 if (size-- <= 0)
179 goto emsgsize;
180 *dst++ = '\0';
181 }
182 return (bits);
183
184 enoent:
185 errno = ENOENT;
186 return (-1);
187
188 emsgsize:
189 errno = EMSGSIZE;
190 return (-1);
191}
diff --git a/src/lib/libc/net/inet_neta.c b/src/lib/libc/net/inet_neta.c
new file mode 100644
index 0000000000..e3e7d0eb71
--- /dev/null
+++ b/src/lib/libc/net/inet_neta.c
@@ -0,0 +1,80 @@
1/* $OpenBSD: inet_neta.c,v 1.7 2005/08/06 20:30:03 espie 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#include <sys/types.h>
21#include <sys/socket.h>
22#include <netinet/in.h>
23#include <arpa/inet.h>
24
25#include <errno.h>
26#include <stdio.h>
27#include <string.h>
28
29/*
30 * char *
31 * inet_neta(src, dst, size)
32 * format an in_addr_t network number into presentation format.
33 * return:
34 * pointer to dst, or NULL if an error occurred (check errno).
35 * note:
36 * format of ``src'' is as for inet_network().
37 * author:
38 * Paul Vixie (ISC), July 1996
39 */
40char *
41inet_neta(in_addr_t src, char *dst, size_t size)
42{
43 char *odst = dst;
44 char *ep;
45 int advance;
46
47 if (src == 0x00000000) {
48 if (size < sizeof "0.0.0.0")
49 goto emsgsize;
50 strlcpy(dst, "0.0.0.0", size);
51 return dst;
52 }
53 ep = dst + size;
54 if (ep <= dst)
55 goto emsgsize;
56 while (src & 0xffffffff) {
57 u_char b = (src & 0xff000000) >> 24;
58
59 src <<= 8;
60 if (b || src) {
61 if (ep - dst < sizeof "255.")
62 goto emsgsize;
63 advance = snprintf(dst, ep - dst, "%u", b);
64 if (advance <= 0 || advance >= ep - dst)
65 goto emsgsize;
66 dst += advance;
67 if (src != 0L) {
68 if (dst + 1 >= ep)
69 goto emsgsize;
70 *dst++ = '.';
71 *dst = '\0';
72 }
73 }
74 }
75 return (odst);
76
77 emsgsize:
78 errno = EMSGSIZE;
79 return (NULL);
80}
diff --git a/src/lib/libc/net/inet_netof.c b/src/lib/libc/net/inet_netof.c
new file mode 100644
index 0000000000..2f468c3aca
--- /dev/null
+++ b/src/lib/libc/net/inet_netof.c
@@ -0,0 +1,50 @@
1/* $OpenBSD: inet_netof.c,v 1.6 2005/08/06 20:30:03 espie Exp $ */
2/*
3 * Copyright (c) 1983, 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
31#include <sys/param.h>
32#include <netinet/in.h>
33#include <arpa/inet.h>
34
35/*
36 * Return the network number from an internet
37 * address; handles class a/b/c network #'s.
38 */
39in_addr_t
40inet_netof(struct in_addr in)
41{
42 in_addr_t i = ntohl(in.s_addr);
43
44 if (IN_CLASSA(i))
45 return (((i)&IN_CLASSA_NET) >> IN_CLASSA_NSHIFT);
46 else if (IN_CLASSB(i))
47 return (((i)&IN_CLASSB_NET) >> IN_CLASSB_NSHIFT);
48 else
49 return (((i)&IN_CLASSC_NET) >> IN_CLASSC_NSHIFT);
50}
diff --git a/src/lib/libc/net/inet_network.c b/src/lib/libc/net/inet_network.c
new file mode 100644
index 0000000000..8b26ba8ff9
--- /dev/null
+++ b/src/lib/libc/net/inet_network.c
@@ -0,0 +1,84 @@
1/* $OpenBSD: inet_network.c,v 1.10 2005/08/06 20:30:03 espie Exp $ */
2/*
3 * Copyright (c) 1983, 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
31#include <sys/types.h>
32#include <netinet/in.h>
33#include <arpa/inet.h>
34#include <ctype.h>
35
36/*
37 * Internet network address interpretation routine.
38 * The library routines call this routine to interpret
39 * network numbers.
40 */
41in_addr_t
42inet_network(const char *cp)
43{
44 in_addr_t val, base, n;
45 char c;
46 in_addr_t parts[4], *pp = parts;
47 int i;
48
49again:
50 val = 0; base = 10;
51 if (*cp == '0')
52 base = 8, cp++;
53 if (*cp == 'x' || *cp == 'X')
54 base = 16, cp++;
55 while ((c = *cp)) {
56 if (isdigit(c)) {
57 val = (val * base) + (c - '0');
58 cp++;
59 continue;
60 }
61 if (base == 16 && isxdigit(c)) {
62 val = (val << 4) + (c + 10 - (islower(c) ? 'a' : 'A'));
63 cp++;
64 continue;
65 }
66 break;
67 }
68 if (*cp == '.') {
69 if (pp >= parts + 3)
70 return (INADDR_NONE);
71 *pp++ = val, cp++;
72 goto again;
73 }
74 if (*cp && !isspace(*cp))
75 return (INADDR_NONE);
76 *pp++ = val;
77 n = pp - parts;
78 for (val = 0, i = 0; i < 4; i++) {
79 val <<= 8;
80 if (i < n)
81 val |= parts[i] & 0xff;
82 }
83 return (val);
84}
diff --git a/src/lib/libc/net/inet_ntoa.c b/src/lib/libc/net/inet_ntoa.c
new file mode 100644
index 0000000000..ff5d93ded2
--- /dev/null
+++ b/src/lib/libc/net/inet_ntoa.c
@@ -0,0 +1,51 @@
1/* $OpenBSD: inet_ntoa.c,v 1.6 2005/08/06 20:30:03 espie Exp $ */
2/*
3 * Copyright (c) 1983, 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
31/*
32 * Convert network-format internet address
33 * to base 256 d.d.d.d representation.
34 */
35#include <sys/types.h>
36#include <netinet/in.h>
37#include <arpa/inet.h>
38#include <stdio.h>
39
40char *
41inet_ntoa(struct in_addr in)
42{
43 static char b[18];
44 char *p;
45
46 p = (char *)&in;
47#define UC(b) (((int)b)&0xff)
48 (void)snprintf(b, sizeof(b),
49 "%u.%u.%u.%u", UC(p[0]), UC(p[1]), UC(p[2]), UC(p[3]));
50 return (b);
51}
diff --git a/src/lib/libc/net/inet_ntop.c b/src/lib/libc/net/inet_ntop.c
new file mode 100644
index 0000000000..d36a0d7889
--- /dev/null
+++ b/src/lib/libc/net/inet_ntop.c
@@ -0,0 +1,195 @@
1/* $OpenBSD: inet_ntop.c,v 1.7 2005/08/06 20:30:03 espie 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#include <sys/param.h>
20#include <sys/types.h>
21#include <sys/socket.h>
22#include <netinet/in.h>
23#include <arpa/inet.h>
24#include <arpa/nameser.h>
25#include <string.h>
26#include <errno.h>
27#include <stdio.h>
28
29/*
30 * WARNING: Don't even consider trying to compile this on a system where
31 * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
32 */
33
34static const char *inet_ntop4(const u_char *src, char *dst, size_t size);
35static const char *inet_ntop6(const u_char *src, char *dst, size_t size);
36
37/* char *
38 * inet_ntop(af, src, dst, size)
39 * convert a network format address to presentation format.
40 * return:
41 * pointer to presentation format address (`dst'), or NULL (see errno).
42 * author:
43 * Paul Vixie, 1996.
44 */
45const char *
46inet_ntop(int af, const void *src, char *dst, size_t size)
47{
48 switch (af) {
49 case AF_INET:
50 return (inet_ntop4(src, dst, size));
51 case AF_INET6:
52 return (inet_ntop6(src, dst, size));
53 default:
54 errno = EAFNOSUPPORT;
55 return (NULL);
56 }
57 /* NOTREACHED */
58}
59
60/* const char *
61 * inet_ntop4(src, dst, size)
62 * format an IPv4 address, more or less like inet_ntoa()
63 * return:
64 * `dst' (as a const)
65 * notes:
66 * (1) uses no statics
67 * (2) takes a u_char* not an in_addr as input
68 * author:
69 * Paul Vixie, 1996.
70 */
71static const char *
72inet_ntop4(const u_char *src, char *dst, size_t size)
73{
74 static const char fmt[] = "%u.%u.%u.%u";
75 char tmp[sizeof "255.255.255.255"];
76 int l;
77
78 l = snprintf(tmp, size, fmt, src[0], src[1], src[2], src[3]);
79 if (l <= 0 || l >= size) {
80 errno = ENOSPC;
81 return (NULL);
82 }
83 strlcpy(dst, tmp, size);
84 return (dst);
85}
86
87/* const char *
88 * inet_ntop6(src, dst, size)
89 * convert IPv6 binary address into presentation (printable) format
90 * author:
91 * Paul Vixie, 1996.
92 */
93static const char *
94inet_ntop6(const u_char *src, char *dst, size_t size)
95{
96 /*
97 * Note that int32_t and int16_t need only be "at least" large enough
98 * to contain a value of the specified size. On some systems, like
99 * Crays, there is no such thing as an integer variable with 16 bits.
100 * Keep this in mind if you think this function should have been coded
101 * to use pointer overlays. All the world's not a VAX.
102 */
103 char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"];
104 char *tp, *ep;
105 struct { int base, len; } best, cur;
106 u_int words[IN6ADDRSZ / INT16SZ];
107 int i;
108 int advance;
109
110 /*
111 * Preprocess:
112 * Copy the input (bytewise) array into a wordwise array.
113 * Find the longest run of 0x00's in src[] for :: shorthanding.
114 */
115 memset(words, '\0', sizeof words);
116 for (i = 0; i < IN6ADDRSZ; i++)
117 words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
118 best.base = -1;
119 cur.base = -1;
120 for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) {
121 if (words[i] == 0) {
122 if (cur.base == -1)
123 cur.base = i, cur.len = 1;
124 else
125 cur.len++;
126 } else {
127 if (cur.base != -1) {
128 if (best.base == -1 || cur.len > best.len)
129 best = cur;
130 cur.base = -1;
131 }
132 }
133 }
134 if (cur.base != -1) {
135 if (best.base == -1 || cur.len > best.len)
136 best = cur;
137 }
138 if (best.base != -1 && best.len < 2)
139 best.base = -1;
140
141 /*
142 * Format the result.
143 */
144 tp = tmp;
145 ep = tmp + sizeof(tmp);
146 for (i = 0; i < (IN6ADDRSZ / INT16SZ) && tp < ep; i++) {
147 /* Are we inside the best run of 0x00's? */
148 if (best.base != -1 && i >= best.base &&
149 i < (best.base + best.len)) {
150 if (i == best.base) {
151 if (tp + 1 >= ep)
152 return (NULL);
153 *tp++ = ':';
154 }
155 continue;
156 }
157 /* Are we following an initial run of 0x00s or any real hex? */
158 if (i != 0) {
159 if (tp + 1 >= ep)
160 return (NULL);
161 *tp++ = ':';
162 }
163 /* Is this address an encapsulated IPv4? */
164 if (i == 6 && best.base == 0 &&
165 (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
166 if (!inet_ntop4(src+12, tp, (size_t)(ep - tp)))
167 return (NULL);
168 tp += strlen(tp);
169 break;
170 }
171 advance = snprintf(tp, ep - tp, "%x", words[i]);
172 if (advance <= 0 || advance >= ep - tp)
173 return (NULL);
174 tp += advance;
175 }
176 /* Was it a trailing run of 0x00's? */
177 if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ)) {
178 if (tp + 1 >= ep)
179 return (NULL);
180 *tp++ = ':';
181 }
182 if (tp + 1 >= ep)
183 return (NULL);
184 *tp++ = '\0';
185
186 /*
187 * Check for overflow, copy, and we're done.
188 */
189 if ((size_t)(tp - tmp) > size) {
190 errno = ENOSPC;
191 return (NULL);
192 }
193 strlcpy(dst, tmp, size);
194 return (dst);
195}
diff --git a/src/lib/libc/net/inet_pton.c b/src/lib/libc/net/inet_pton.c
new file mode 100644
index 0000000000..87206ee8b8
--- /dev/null
+++ b/src/lib/libc/net/inet_pton.c
@@ -0,0 +1,207 @@
1/* $OpenBSD: inet_pton.c,v 1.6 2005/08/06 20:30:03 espie 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#include <sys/param.h>
20#include <sys/types.h>
21#include <sys/socket.h>
22#include <netinet/in.h>
23#include <arpa/inet.h>
24#include <arpa/nameser.h>
25#include <string.h>
26#include <errno.h>
27
28/*
29 * WARNING: Don't even consider trying to compile this on a system where
30 * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
31 */
32
33static int inet_pton4(const char *src, u_char *dst);
34static int inet_pton6(const char *src, u_char *dst);
35
36/* int
37 * inet_pton(af, src, dst)
38 * convert from presentation format (which usually means ASCII printable)
39 * to network format (which is usually some kind of binary format).
40 * return:
41 * 1 if the address was valid for the specified address family
42 * 0 if the address wasn't valid (`dst' is untouched in this case)
43 * -1 if some other error occurred (`dst' is untouched in this case, too)
44 * author:
45 * Paul Vixie, 1996.
46 */
47int
48inet_pton(int af, const char *src, void *dst)
49{
50 switch (af) {
51 case AF_INET:
52 return (inet_pton4(src, dst));
53 case AF_INET6:
54 return (inet_pton6(src, dst));
55 default:
56 errno = EAFNOSUPPORT;
57 return (-1);
58 }
59 /* NOTREACHED */
60}
61
62/* int
63 * inet_pton4(src, dst)
64 * like inet_aton() but without all the hexadecimal and shorthand.
65 * return:
66 * 1 if `src' is a valid dotted quad, else 0.
67 * notice:
68 * does not touch `dst' unless it's returning 1.
69 * author:
70 * Paul Vixie, 1996.
71 */
72static int
73inet_pton4(const char *src, u_char *dst)
74{
75 static const char digits[] = "0123456789";
76 int saw_digit, octets, ch;
77 u_char tmp[INADDRSZ], *tp;
78
79 saw_digit = 0;
80 octets = 0;
81 *(tp = tmp) = 0;
82 while ((ch = *src++) != '\0') {
83 const char *pch;
84
85 if ((pch = strchr(digits, ch)) != NULL) {
86 u_int new = *tp * 10 + (pch - digits);
87
88 if (new > 255)
89 return (0);
90 if (! saw_digit) {
91 if (++octets > 4)
92 return (0);
93 saw_digit = 1;
94 }
95 *tp = new;
96 } else if (ch == '.' && saw_digit) {
97 if (octets == 4)
98 return (0);
99 *++tp = 0;
100 saw_digit = 0;
101 } else
102 return (0);
103 }
104 if (octets < 4)
105 return (0);
106
107 memcpy(dst, tmp, INADDRSZ);
108 return (1);
109}
110
111/* int
112 * inet_pton6(src, dst)
113 * convert presentation level address to network order binary form.
114 * return:
115 * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
116 * notice:
117 * (1) does not touch `dst' unless it's returning 1.
118 * (2) :: in a full address is silently ignored.
119 * credit:
120 * inspired by Mark Andrews.
121 * author:
122 * Paul Vixie, 1996.
123 */
124static int
125inet_pton6(const char *src, u_char *dst)
126{
127 static const char xdigits_l[] = "0123456789abcdef",
128 xdigits_u[] = "0123456789ABCDEF";
129 u_char tmp[IN6ADDRSZ], *tp, *endp, *colonp;
130 const char *xdigits, *curtok;
131 int ch, saw_xdigit;
132 u_int val;
133
134 memset((tp = tmp), '\0', IN6ADDRSZ);
135 endp = tp + IN6ADDRSZ;
136 colonp = NULL;
137 /* Leading :: requires some special handling. */
138 if (*src == ':')
139 if (*++src != ':')
140 return (0);
141 curtok = src;
142 saw_xdigit = 0;
143 val = 0;
144 while ((ch = *src++) != '\0') {
145 const char *pch;
146
147 if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
148 pch = strchr((xdigits = xdigits_u), ch);
149 if (pch != NULL) {
150 val <<= 4;
151 val |= (pch - xdigits);
152 if (val > 0xffff)
153 return (0);
154 saw_xdigit = 1;
155 continue;
156 }
157 if (ch == ':') {
158 curtok = src;
159 if (!saw_xdigit) {
160 if (colonp)
161 return (0);
162 colonp = tp;
163 continue;
164 } else if (*src == '\0') {
165 return (0);
166 }
167 if (tp + INT16SZ > endp)
168 return (0);
169 *tp++ = (u_char) (val >> 8) & 0xff;
170 *tp++ = (u_char) val & 0xff;
171 saw_xdigit = 0;
172 val = 0;
173 continue;
174 }
175 if (ch == '.' && ((tp + INADDRSZ) <= endp) &&
176 inet_pton4(curtok, tp) > 0) {
177 tp += INADDRSZ;
178 saw_xdigit = 0;
179 break; /* '\0' was seen by inet_pton4(). */
180 }
181 return (0);
182 }
183 if (saw_xdigit) {
184 if (tp + INT16SZ > endp)
185 return (0);
186 *tp++ = (u_char) (val >> 8) & 0xff;
187 *tp++ = (u_char) val & 0xff;
188 }
189 if (colonp != NULL) {
190 /*
191 * Since some memmove()'s erroneously fail to handle
192 * overlapping regions, we'll do the shift by hand.
193 */
194 const int n = tp - colonp;
195 int i;
196
197 for (i = 1; i <= n; i++) {
198 endp[- i] = colonp[n - i];
199 colonp[n - i] = 0;
200 }
201 tp = endp;
202 }
203 if (tp != endp)
204 return (0);
205 memcpy(dst, tmp, IN6ADDRSZ);
206 return (1);
207}
diff --git a/src/lib/libc/net/ip6opt.c b/src/lib/libc/net/ip6opt.c
new file mode 100644
index 0000000000..565c0ed369
--- /dev/null
+++ b/src/lib/libc/net/ip6opt.c
@@ -0,0 +1,371 @@
1/* $OpenBSD: ip6opt.c,v 1.2 2005/03/25 13:24:12 otto 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(int nbytes)
56{
57 nbytes += 2; /* we need space for nxt-hdr and length fields */
58 return(CMSG_SPACE((nbytes + 7) & ~7));
59}
60
61/*
62 * This function is called once per ancillary data object that will
63 * contain either Hop-by-Hop or Destination options. It returns 0 on
64 * success or -1 on an error.
65 */
66int
67inet6_option_init(void *bp, struct cmsghdr **cmsgp, int type)
68{
69 struct cmsghdr *ch = (struct cmsghdr *)bp;
70
71 /* argument validation */
72 if (type != IPV6_HOPOPTS && type != IPV6_DSTOPTS)
73 return(-1);
74
75 ch->cmsg_level = IPPROTO_IPV6;
76 ch->cmsg_type = type;
77 ch->cmsg_len = CMSG_LEN(0);
78
79 *cmsgp = ch;
80 return(0);
81}
82
83/*
84 * This function appends a Hop-by-Hop option or a Destination option
85 * into an ancillary data object that has been initialized by
86 * inet6_option_init(). This function returns 0 if it succeeds or -1 on
87 * an error.
88 * multx is the value x in the alignment term "xn + y" described
89 * earlier. It must have a value of 1, 2, 4, or 8.
90 * plusy is the value y in the alignment term "xn + y" described
91 * earlier. It must have a value between 0 and 7, inclusive.
92 */
93int
94inet6_option_append(struct cmsghdr *cmsg, const u_int8_t *typep, int multx,
95 int plusy)
96{
97 int padlen, optlen, off;
98 u_char *bp = (u_char *)cmsg + cmsg->cmsg_len;
99 struct ip6_ext *eh = (struct ip6_ext *)CMSG_DATA(cmsg);
100
101 /* argument validation */
102 if (multx != 1 && multx != 2 && multx != 4 && multx != 8)
103 return(-1);
104 if (plusy < 0 || plusy > 7)
105 return(-1);
106 if (typep[0] > 255)
107 return(-1);
108
109 /*
110 * If this is the first option, allocate space for the
111 * first 2 bytes(for next header and length fields) of
112 * the option header.
113 */
114 if (bp == (u_char *)eh) {
115 bp += 2;
116 cmsg->cmsg_len += 2;
117 }
118
119 /* calculate pad length before the option. */
120 off = bp - (u_char *)eh;
121 padlen = (((off % multx) + (multx - 1)) & ~(multx - 1)) -
122 (off % multx);
123 padlen += plusy;
124 padlen %= multx; /* keep the pad as short as possible */
125 /* insert padding */
126 inet6_insert_padopt(bp, padlen);
127 cmsg->cmsg_len += padlen;
128 bp += padlen;
129
130 /* copy the option */
131 if (typep[0] == IP6OPT_PAD1)
132 optlen = 1;
133 else
134 optlen = typep[1] + 2;
135 memcpy(bp, typep, optlen);
136 bp += optlen;
137 cmsg->cmsg_len += optlen;
138
139 /* calculate pad length after the option and insert the padding */
140 off = bp - (u_char *)eh;
141 padlen = ((off + 7) & ~7) - off;
142 inet6_insert_padopt(bp, padlen);
143 bp += padlen;
144 cmsg->cmsg_len += padlen;
145
146 /* update the length field of the ip6 option header */
147 eh->ip6e_len = ((bp - (u_char *)eh) >> 3) - 1;
148
149 return(0);
150}
151
152/*
153 * This function appends a Hop-by-Hop option or a Destination option
154 * into an ancillary data object that has been initialized by
155 * inet6_option_init(). This function returns a pointer to the 8-bit
156 * option type field that starts the option on success, or NULL on an
157 * error.
158 * The difference between this function and inet6_option_append() is
159 * that the latter copies the contents of a previously built option into
160 * the ancillary data object while the current function returns a
161 * pointer to the space in the data object where the option's TLV must
162 * then be built by the caller.
163 *
164 */
165u_int8_t *
166inet6_option_alloc(struct cmsghdr *cmsg, int datalen, int multx, int plusy)
167{
168 int padlen, off;
169 u_int8_t *bp = (u_char *)cmsg + cmsg->cmsg_len;
170 u_int8_t *retval;
171 struct ip6_ext *eh = (struct ip6_ext *)CMSG_DATA(cmsg);
172
173 /* argument validation */
174 if (multx != 1 && multx != 2 && multx != 4 && multx != 8)
175 return(NULL);
176 if (plusy < 0 || plusy > 7)
177 return(NULL);
178
179 /*
180 * If this is the first option, allocate space for the
181 * first 2 bytes(for next header and length fields) of
182 * the option header.
183 */
184 if (bp == (u_char *)eh) {
185 bp += 2;
186 cmsg->cmsg_len += 2;
187 }
188
189 /* calculate pad length before the option. */
190 off = bp - (u_char *)eh;
191 padlen = (((off % multx) + (multx - 1)) & ~(multx - 1)) -
192 (off % multx);
193 padlen += plusy;
194 padlen %= multx; /* keep the pad as short as possible */
195 /* insert padding */
196 inet6_insert_padopt(bp, padlen);
197 cmsg->cmsg_len += padlen;
198 bp += padlen;
199
200 /* keep space to store specified length of data */
201 retval = bp;
202 bp += datalen;
203 cmsg->cmsg_len += datalen;
204
205 /* calculate pad length after the option and insert the padding */
206 off = bp - (u_char *)eh;
207 padlen = ((off + 7) & ~7) - off;
208 inet6_insert_padopt(bp, padlen);
209 bp += padlen;
210 cmsg->cmsg_len += padlen;
211
212 /* update the length field of the ip6 option header */
213 eh->ip6e_len = ((bp - (u_char *)eh) >> 3) - 1;
214
215 return(retval);
216}
217
218/*
219 * This function processes the next Hop-by-Hop option or Destination
220 * option in an ancillary data object. If another option remains to be
221 * processed, the return value of the function is 0 and *tptrp points to
222 * the 8-bit option type field (which is followed by the 8-bit option
223 * data length, followed by the option data). If no more options remain
224 * to be processed, the return value is -1 and *tptrp is NULL. If an
225 * error occurs, the return value is -1 and *tptrp is not NULL.
226 * (RFC 2292, 6.3.5)
227 */
228int
229inet6_option_next(const struct cmsghdr *cmsg, u_int8_t **tptrp)
230{
231 struct ip6_ext *ip6e;
232 int hdrlen, optlen;
233 u_int8_t *lim;
234
235 if (cmsg->cmsg_level != IPPROTO_IPV6 ||
236 (cmsg->cmsg_type != IPV6_HOPOPTS &&
237 cmsg->cmsg_type != IPV6_DSTOPTS))
238 return(-1);
239
240 /* message length validation */
241 if (cmsg->cmsg_len < CMSG_SPACE(sizeof(struct ip6_ext)))
242 return(-1);
243 ip6e = (struct ip6_ext *)CMSG_DATA(cmsg);
244 hdrlen = (ip6e->ip6e_len + 1) << 3;
245 if (cmsg->cmsg_len < CMSG_SPACE(hdrlen))
246 return(-1);
247
248 /*
249 * If the caller does not specify the starting point,
250 * simply return the 1st option.
251 * Otherwise, search the option list for the next option.
252 */
253 lim = (u_int8_t *)ip6e + hdrlen;
254 if (*tptrp == NULL)
255 *tptrp = (u_int8_t *)(ip6e + 1);
256 else {
257 if ((optlen = ip6optlen(*tptrp, lim)) == 0)
258 return(-1);
259
260 *tptrp = *tptrp + optlen;
261 }
262 if (*tptrp >= lim) { /* there is no option */
263 *tptrp = NULL;
264 return(-1);
265 }
266 /*
267 * Finally, checks if the next option is safely stored in the
268 * cmsg data.
269 */
270 if (ip6optlen(*tptrp, lim) == 0)
271 return(-1);
272 else
273 return(0);
274}
275
276/*
277 * This function is similar to the inet6_option_next() function,
278 * except this function lets the caller specify the option type to be
279 * searched for, instead of always returning the next option in the
280 * ancillary data object.
281 * Note: RFC 2292 says the type of tptrp is u_int8_t *, but we think
282 * it's a typo. The variable should be type of u_int8_t **.
283 */
284int
285inet6_option_find(const struct cmsghdr *cmsg, u_int8_t **tptrp, int type)
286{
287 struct ip6_ext *ip6e;
288 int hdrlen, optlen;
289 u_int8_t *optp, *lim;
290
291 if (cmsg->cmsg_level != IPPROTO_IPV6 ||
292 (cmsg->cmsg_type != IPV6_HOPOPTS &&
293 cmsg->cmsg_type != IPV6_DSTOPTS))
294 return(-1);
295
296 /* message length validation */
297 if (cmsg->cmsg_len < CMSG_SPACE(sizeof(struct ip6_ext)))
298 return(-1);
299 ip6e = (struct ip6_ext *)CMSG_DATA(cmsg);
300 hdrlen = (ip6e->ip6e_len + 1) << 3;
301 if (cmsg->cmsg_len < CMSG_SPACE(hdrlen))
302 return(-1);
303
304 /*
305 * If the caller does not specify the starting point,
306 * search from the beginning of the option list.
307 * Otherwise, search from *the next option* of the specified point.
308 */
309 lim = (u_int8_t *)ip6e + hdrlen;
310 if (*tptrp == NULL)
311 *tptrp = (u_int8_t *)(ip6e + 1);
312 else {
313 if ((optlen = ip6optlen(*tptrp, lim)) == 0)
314 return(-1);
315
316 *tptrp = *tptrp + optlen;
317 }
318 for (optp = *tptrp; optp < lim; optp += optlen) {
319 if (*optp == type) {
320 *tptrp = optp;
321 return(0);
322 }
323 if ((optlen = ip6optlen(optp, lim)) == 0)
324 return(-1);
325 }
326
327 /* search failed */
328 *tptrp = NULL;
329 return(-1);
330}
331
332/*
333 * Calculate the length of a given IPv6 option. Also checks
334 * if the option is safely stored in user's buffer according to the
335 * calculated length and the limitation of the buffer.
336 */
337static int
338ip6optlen(u_int8_t *opt, u_int8_t *lim)
339{
340 int optlen;
341
342 if (*opt == IP6OPT_PAD1)
343 optlen = 1;
344 else {
345 /* is there enough space to store type and len? */
346 if (opt + 2 > lim)
347 return(0);
348 optlen = *(opt + 1) + 2;
349 }
350 if (opt + optlen <= lim)
351 return(optlen);
352
353 return(0);
354}
355
356static void
357inet6_insert_padopt(u_char *p, int len)
358{
359 switch(len) {
360 case 0:
361 return;
362 case 1:
363 p[0] = IP6OPT_PAD1;
364 return;
365 default:
366 p[0] = IP6OPT_PADN;
367 p[1] = len - 2;
368 memset(&p[2], 0, len - 2);
369 return;
370 }
371}
diff --git a/src/lib/libc/net/ipx.3 b/src/lib/libc/net/ipx.3
new file mode 100644
index 0000000000..503483bfab
--- /dev/null
+++ b/src/lib/libc/net/ipx.3
@@ -0,0 +1,122 @@
1.\" $OpenBSD: ipx.3,v 1.11 2005/06/09 08:40:49 jmc 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 hosts 5 ,
107.Xr networks 5
108.Sh HISTORY
109The precursor
110.Fn ns_addr
111and
112.Fn ns_ntoa
113functions appeared in
114.Bx 4.3 .
115.Sh BUGS
116The string returned by
117.Fn ipx_ntoa
118resides in a static memory area.
119The function
120.Fn ipx_addr
121should diagnose improperly formed input, and there should be an unambiguous
122way 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..b65d5f6cfd
--- /dev/null
+++ b/src/lib/libc/net/ipx_addr.c
@@ -0,0 +1,213 @@
1/* $OpenBSD: ipx_addr.c,v 1.8 2005/08/06 20:30:03 espie Exp $ */
2/*
3 * Copyright (c) 1986, 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 * J.Q. Johnson.
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 * from @(#)ipx_addr.c
34 */
35
36#include <sys/param.h>
37#include <netipx/ipx.h>
38#include <stdio.h>
39#include <string.h>
40
41static struct ipx_addr addr, zero_addr;
42
43static void Field(char *, u_char *, int);
44static void cvtbase(long, int, int *, int, unsigned char *, int);
45
46struct ipx_addr
47ipx_addr(const char *name)
48{
49 char separator;
50 char *hostname, *socketname, *cp;
51 char buf[50];
52
53 strlcpy(buf, name, sizeof(buf));
54
55 /*
56 * First, figure out what he intends as a field separtor.
57 * Despite the way this routine is written, the prefered
58 * form 2-272.AA001234H.01777, i.e. XDE standard.
59 * Great efforts are made to insure backward compatibility.
60 */
61 if ((hostname = strchr(buf, '#')))
62 separator = '#';
63 else {
64 hostname = strchr(buf, '.');
65 if ((cp = strchr(buf, ':')) &&
66 ((hostname && cp < hostname) || (hostname == 0))) {
67 hostname = cp;
68 separator = ':';
69 } else
70 separator = '.';
71 }
72 if (hostname)
73 *hostname++ = 0;
74
75 addr = zero_addr;
76 Field(buf, addr.ipx_net.c_net, 4);
77 if (hostname == 0)
78 return (addr); /* No separator means net only */
79
80 socketname = strchr(hostname, separator);
81 if (socketname) {
82 *socketname++ = 0;
83 Field(socketname, (u_char *)&addr.ipx_port, 2);
84 }
85
86 Field(hostname, addr.ipx_host.c_host, 6);
87
88 return (addr);
89}
90
91static void
92Field(char *buf, u_char *out, int len)
93{
94 char *bp = buf;
95 int i, ibase, base16 = 0, base10 = 0, clen = 0;
96 int hb[6], *hp;
97 char *fmt;
98
99 /*
100 * first try 2-273#2-852-151-014#socket
101 */
102 if ((*buf != '-') &&
103 (1 < (i = sscanf(buf, "%d-%d-%d-%d-%d",
104 &hb[0], &hb[1], &hb[2], &hb[3], &hb[4])))) {
105 cvtbase(1000L, 256, hb, i, out, len);
106 return;
107 }
108 /*
109 * try form 8E1#0.0.AA.0.5E.E6#socket
110 */
111 if (1 < (i = sscanf(buf,"%x.%x.%x.%x.%x.%x",
112 &hb[0], &hb[1], &hb[2], &hb[3], &hb[4], &hb[5]))) {
113 cvtbase(256L, 256, hb, i, out, len);
114 return;
115 }
116 /*
117 * try form 8E1#0:0:AA:0:5E:E6#socket
118 */
119 if (1 < (i = sscanf(buf,"%x:%x:%x:%x:%x:%x",
120 &hb[0], &hb[1], &hb[2], &hb[3], &hb[4], &hb[5]))) {
121 cvtbase(256L, 256, hb, i, out, len);
122 return;
123 }
124 /*
125 * This is REALLY stretching it but there was a
126 * comma notation separting shorts -- definitely non standard
127 */
128 if (1 < (i = sscanf(buf,"%x,%x,%x",
129 &hb[0], &hb[1], &hb[2]))) {
130 hb[0] = htons(hb[0]); hb[1] = htons(hb[1]);
131 hb[2] = htons(hb[2]);
132 cvtbase(65536L, 256, hb, i, out, len);
133 return;
134 }
135
136 /* Need to decide if base 10, 16 or 8 */
137 while (*bp) switch (*bp++) {
138
139 case '0': case '1': case '2': case '3': case '4': case '5':
140 case '6': case '7': case '-':
141 break;
142
143 case '8': case '9':
144 base10 = 1;
145 break;
146
147 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
148 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
149 base16 = 1;
150 break;
151
152 case 'x': case 'X':
153 *--bp = '0';
154 base16 = 1;
155 break;
156
157 case 'h': case 'H':
158 base16 = 1;
159 /* fall into */
160
161 default:
162 *--bp = 0; /* Ends Loop */
163 }
164 if (base16) {
165 fmt = "%3x";
166 ibase = 4096;
167 } else if (base10 == 0 && *buf == '0') {
168 fmt = "%3o";
169 ibase = 512;
170 } else {
171 fmt = "%3d";
172 ibase = 1000;
173 }
174
175 for (bp = buf; *bp++; ) clen++;
176 if (clen == 0) clen++;
177 if (clen > 18) clen = 18;
178 i = ((clen - 1) / 3) + 1;
179 bp = clen + buf - 3;
180 hp = hb + i - 1;
181
182 while (hp > hb) {
183 (void)sscanf(bp, fmt, hp);
184 bp[0] = 0;
185 hp--;
186 bp -= 3;
187 }
188 (void)sscanf(buf, fmt, hp);
189 cvtbase((long)ibase, 256, hb, i, out, len);
190}
191
192static void
193cvtbase(long oldbase, int newbase, int *input, int inlen,
194 unsigned char *result, int reslen)
195{
196 int d, e;
197 long sum;
198
199 e = 1;
200 while (e > 0 && reslen > 0) {
201 d = 0; e = 0; sum = 0;
202 /* long division: input=input/newbase */
203 while (d < inlen) {
204 sum = sum*oldbase + (long) input[d];
205 e += (sum > 0);
206 input[d++] = sum / newbase;
207 sum %= newbase;
208 }
209 result[--reslen] = sum; /* accumulate remainder */
210 }
211 for (d=0; d < reslen; d++)
212 result[d] = 0;
213}
diff --git a/src/lib/libc/net/ipx_ntoa.c b/src/lib/libc/net/ipx_ntoa.c
new file mode 100644
index 0000000000..9b1b6a1c49
--- /dev/null
+++ b/src/lib/libc/net/ipx_ntoa.c
@@ -0,0 +1,46 @@
1/* $OpenBSD: ipx_ntoa.c,v 1.6 2005/08/06 20:30:03 espie Exp $ */
2/*
3 * Copyright (c) 1986, 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
31#include <sys/param.h>
32#include <netipx/ipx.h>
33#include <stdio.h>
34
35char *
36ipx_ntoa(struct ipx_addr addr)
37{
38 static char obuf[] = "xxxxxxxxH.xx:xx:xx:xx:xx:xx.uuuuu";
39
40 snprintf(obuf, sizeof obuf, "%8xH.%02x:%02x:%02x:%02x:%02x:%02x.%u",
41 ntohl(addr.ipx_net.l_net), addr.ipx_host.c_host[0],
42 addr.ipx_host.c_host[1], addr.ipx_host.c_host[2],
43 addr.ipx_host.c_host[3], addr.ipx_host.c_host[4],
44 addr.ipx_host.c_host[5], ntohs(addr.ipx_port));
45 return (obuf);
46}
diff --git a/src/lib/libc/net/link_addr.3 b/src/lib/libc/net/link_addr.3
new file mode 100644
index 0000000000..fc1fd85257
--- /dev/null
+++ b/src/lib/libc/net/link_addr.3
@@ -0,0 +1,127 @@
1.\" $OpenBSD: link_addr.3,v 1.11 2005/07/22 04:50:51 jaredy 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 NUL-terminated string.
94.Fn link_addr
95has no return value.
96(See
97.Sx BUGS . )
98.Sh SEE ALSO
99.Xr ifconfig 8
100.Sh HISTORY
101The
102.Fn link_addr
103and
104.Fn link_ntoa
105functions appeared in
106.Bx 4.3 Reno .
107.Sh BUGS
108The returned values for
109.Fn 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..ac96f3acdf
--- /dev/null
+++ b/src/lib/libc/net/linkaddr.c
@@ -0,0 +1,148 @@
1/* $OpenBSD: linkaddr.c,v 1.5 2005/08/06 20:30:03 espie Exp $ */
2/*-
3 * Copyright (c) 1990, 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
31#include <sys/types.h>
32#include <sys/socket.h>
33#include <net/if_dl.h>
34#include <string.h>
35
36/* States*/
37#define NAMING 0
38#define GOTONE 1
39#define GOTTWO 2
40#define RESET 3
41/* Inputs */
42#define DIGIT (4*0)
43#define END (4*1)
44#define DELIM (4*2)
45#define LETTER (4*3)
46
47void
48link_addr(const char *addr, struct sockaddr_dl *sdl)
49{
50 char *cp = sdl->sdl_data;
51 char *cplim = sdl->sdl_len + (char *)sdl;
52 int byte = 0, state = NAMING, new;
53
54 bzero((char *)&sdl->sdl_family, sdl->sdl_len - 1);
55 sdl->sdl_family = AF_LINK;
56 do {
57 state &= ~LETTER;
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 if (state == NAMING &&
67 (((*addr >= 'A') && (*addr <= 'Z')) ||
68 ((*addr >= 'a') && (*addr <= 'z'))))
69 state |= LETTER;
70 else
71 state |= DELIM;
72 addr++;
73 switch (state /* | INPUT */) {
74 case NAMING | DIGIT:
75 case NAMING | LETTER:
76 *cp++ = addr[-1];
77 continue;
78 case NAMING | DELIM:
79 state = RESET;
80 sdl->sdl_nlen = cp - sdl->sdl_data;
81 continue;
82 case GOTTWO | DIGIT:
83 *cp++ = byte;
84 /* FALLTHROUGH */
85 case RESET | DIGIT:
86 state = GOTONE;
87 byte = new;
88 continue;
89 case GOTONE | DIGIT:
90 state = GOTTWO;
91 byte = new + (byte << 4);
92 continue;
93 default: /* | DELIM */
94 state = RESET;
95 *cp++ = byte;
96 byte = 0;
97 continue;
98 case GOTONE | END:
99 case GOTTWO | END:
100 *cp++ = byte;
101 /* FALLTHROUGH */
102 case RESET | END:
103 break;
104 }
105 break;
106 } while (cp < cplim);
107 sdl->sdl_alen = cp - LLADDR(sdl);
108 new = cp - (char *)sdl;
109 if (new > sizeof(*sdl))
110 sdl->sdl_len = new;
111 return;
112}
113
114static char hexlist[] = "0123456789abcdef";
115
116char *
117link_ntoa(const struct sockaddr_dl *sdl)
118{
119 static char obuf[64];
120 char *out = obuf;
121 int i;
122 u_char *in = (u_char *)LLADDR(sdl);
123 u_char *inlim = in + sdl->sdl_alen;
124 int firsttime = 1;
125
126 if (sdl->sdl_nlen) {
127 bcopy(sdl->sdl_data, obuf, sdl->sdl_nlen);
128 out += sdl->sdl_nlen;
129 if (sdl->sdl_alen)
130 *out++ = ':';
131 }
132 while (in < inlim) {
133 if (firsttime)
134 firsttime = 0;
135 else
136 *out++ = '.';
137 i = *in++;
138 if (i > 0xf) {
139 out[1] = hexlist[i & 0xf];
140 i >>= 4;
141 out[0] = hexlist[i];
142 out += 2;
143 } else
144 *out++ = hexlist[i];
145 }
146 *out = 0;
147 return (obuf);
148}
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..c2630a5265
--- /dev/null
+++ b/src/lib/libc/net/net_addrcmp.c
@@ -0,0 +1,63 @@
1/* $OpenBSD: net_addrcmp.c,v 1.10 2005/06/17 20:36:16 henning Exp $ */
2
3/*
4 * Copyright (c) 1999 Theo de Raadt
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 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#include <sys/types.h>
29#include <sys/socket.h>
30#include <sys/un.h>
31#include <netinet/in.h>
32#include <string.h>
33
34int
35net_addrcmp(struct sockaddr *sa1, struct sockaddr *sa2)
36{
37
38 if (sa1->sa_len != sa2->sa_len)
39 return (sa1->sa_len < sa2->sa_len) ? -1 : 1;
40 if (sa1->sa_family != sa2->sa_family)
41 return (sa1->sa_family < sa2->sa_family) ? -1 : 1;
42
43 switch(sa1->sa_family) {
44 case AF_INET:
45 return (memcmp(&((struct sockaddr_in *)sa1)->sin_addr,
46 &((struct sockaddr_in *)sa2)->sin_addr,
47 sizeof(struct in_addr)));
48 case AF_INET6:
49 if (((struct sockaddr_in6 *)sa1)->sin6_scope_id !=
50 ((struct sockaddr_in6 *)sa2)->sin6_scope_id)
51 return (((struct sockaddr_in6 *)sa1)->sin6_scope_id <
52 ((struct sockaddr_in6 *)sa2)->sin6_scope_id)
53 ? -1 : 1;
54 return memcmp(&((struct sockaddr_in6 *)sa1)->sin6_addr,
55 &((struct sockaddr_in6 *)sa2)->sin6_addr,
56 sizeof(struct in6_addr));
57 case AF_LOCAL:
58 return (strcmp(((struct sockaddr_un *)sa1)->sun_path,
59 ((struct sockaddr_un *)sa1)->sun_path));
60 default:
61 return -1;
62 }
63}
diff --git a/src/lib/libc/net/nsap_addr.c b/src/lib/libc/net/nsap_addr.c
new file mode 100644
index 0000000000..8cfe86f475
--- /dev/null
+++ b/src/lib/libc/net/nsap_addr.c
@@ -0,0 +1,94 @@
1/* $OpenBSD: nsap_addr.c,v 1.7 2006/03/31 05:35:44 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#include <sys/types.h>
21#include <sys/param.h>
22#include <sys/socket.h>
23#include <netinet/in.h>
24#include <arpa/nameser.h>
25#include <ctype.h>
26#include <resolv.h>
27
28static u_char
29xtob(int c)
30{
31 return (c - (((c >= '0') && (c <= '9')) ? '0' : '7'));
32}
33
34u_int
35inet_nsap_addr(const char *ascii, u_char *binary, int maxlen)
36{
37 u_char c, nib;
38 u_int len = 0;
39
40 while ((c = *ascii++) != '\0' && len < maxlen) {
41 if (c == '.' || c == '+' || c == '/')
42 continue;
43 if (!isascii(c))
44 return (0);
45 if (islower(c))
46 c = (u_char)toupper(c);
47 if (isxdigit(c)) {
48 nib = xtob(c);
49 if ((c = *ascii++)) {
50 c = (u_char)toupper(c);
51 if (isxdigit(c)) {
52 *binary++ = (nib << 4) | xtob(c);
53 len++;
54 } else
55 return (0);
56 }
57 else
58 return (0);
59 }
60 else
61 return (0);
62 }
63 return (len);
64}
65
66char *
67inet_nsap_ntoa(int binlen, const u_char *binary, char *ascii)
68{
69 int nib;
70 int i;
71 static char tmpbuf[255*3];
72 char *start;
73
74 if (ascii)
75 start = ascii;
76 else {
77 ascii = tmpbuf;
78 start = tmpbuf;
79 }
80
81 if (binlen > 255)
82 binlen = 255;
83
84 for (i = 0; i < binlen; i++) {
85 nib = *binary >> 4;
86 *ascii++ = nib + (nib < 10 ? '0' : '7');
87 nib = *binary++ & 0x0f;
88 *ascii++ = nib + (nib < 10 ? '0' : '7');
89 if (((i % 2) == 0 && (i + 1) < binlen))
90 *ascii++ = '.';
91 }
92 *ascii = '\0';
93 return (start);
94}
diff --git a/src/lib/libc/net/ntohl.c b/src/lib/libc/net/ntohl.c
new file mode 100644
index 0000000000..36414b7a13
--- /dev/null
+++ b/src/lib/libc/net/ntohl.c
@@ -0,0 +1,21 @@
1/* $OpenBSD: ntohl.c,v 1.6 2005/08/06 20:30:03 espie Exp $ */
2/*
3 * Written by J.T. Conklin <jtc@netbsd.org>.
4 * Public domain.
5 */
6
7#include <sys/types.h>
8#include <machine/endian.h>
9
10#undef ntohl
11
12u_int32_t
13ntohl(u_int32_t x)
14{
15#if BYTE_ORDER == LITTLE_ENDIAN
16 u_char *s = (u_char *)&x;
17 return (u_int32_t)(s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3]);
18#else
19 return x;
20#endif
21}
diff --git a/src/lib/libc/net/ntohs.c b/src/lib/libc/net/ntohs.c
new file mode 100644
index 0000000000..8f345e84ad
--- /dev/null
+++ b/src/lib/libc/net/ntohs.c
@@ -0,0 +1,21 @@
1/* $OpenBSD: ntohs.c,v 1.8 2005/08/06 20:30:03 espie Exp $ */
2/*
3 * Written by J.T. Conklin <jtc@netbsd.org>.
4 * Public domain.
5 */
6
7#include <sys/types.h>
8#include <machine/endian.h>
9
10#undef ntohs
11
12u_int16_t
13ntohs(u_int16_t x)
14{
15#if BYTE_ORDER == LITTLE_ENDIAN
16 u_char *s = (u_char *) &x;
17 return (u_int16_t)(s[0] << 8 | s[1]);
18#else
19 return x;
20#endif
21}
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..e2b9199492
--- /dev/null
+++ b/src/lib/libc/net/rcmd.c
@@ -0,0 +1,687 @@
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#include <sys/param.h>
32#include <sys/socket.h>
33#include <sys/stat.h>
34
35#include <netinet/in.h>
36#include <arpa/inet.h>
37
38#include <signal.h>
39#include <fcntl.h>
40#include <netdb.h>
41#include <unistd.h>
42#include <pwd.h>
43#include <errno.h>
44#include <stdio.h>
45#include <ctype.h>
46#include <string.h>
47#include <syslog.h>
48#include <stdlib.h>
49#include <netgroup.h>
50
51int __ivaliduser(FILE *, in_addr_t, const char *, const char *);
52int __ivaliduser_sa(FILE *, struct sockaddr *, socklen_t,
53 const char *, const char *);
54static int __icheckhost(struct sockaddr *, socklen_t, const char *);
55static char *__gethostloop(struct sockaddr *, socklen_t);
56
57int
58rcmd(char **ahost, int rport, const char *locuser, const char *remuser,
59 const char *cmd, int *fd2p)
60{
61 return rcmd_af(ahost, rport, locuser, remuser, cmd, fd2p, AF_INET);
62}
63
64int
65rcmd_af(char **ahost, int porta, const char *locuser, const char *remuser,
66 const char *cmd, int *fd2p, int af)
67{
68 static char hbuf[MAXHOSTNAMELEN];
69 char pbuf[NI_MAXSERV];
70 struct addrinfo hints, *res, *r;
71 int error;
72 struct sockaddr_storage from;
73 fd_set *readsp = NULL;
74 sigset_t oldmask, mask;
75 pid_t pid;
76 int s, lport, timo;
77 char c, *p;
78 int refused;
79 in_port_t rport = porta;
80
81 /* call rcmdsh() with specified remote shell if appropriate. */
82 if (!issetugid() && (p = getenv("RSH")) && *p) {
83 struct servent *sp = getservbyname("shell", "tcp");
84
85 if (sp && sp->s_port == rport)
86 return (rcmdsh(ahost, rport, locuser, remuser,
87 cmd, p));
88 }
89
90 /* use rsh(1) if non-root and remote port is shell. */
91 if (geteuid()) {
92 struct servent *sp = getservbyname("shell", "tcp");
93
94 if (sp && sp->s_port == rport)
95 return (rcmdsh(ahost, rport, locuser, remuser,
96 cmd, NULL));
97 }
98
99 pid = getpid();
100 snprintf(pbuf, sizeof(pbuf), "%u", ntohs(rport));
101 memset(&hints, 0, sizeof(hints));
102 hints.ai_family = af;
103 hints.ai_socktype = SOCK_STREAM;
104 hints.ai_flags = AI_CANONNAME;
105 error = getaddrinfo(*ahost, pbuf, &hints, &res);
106 if (error) {
107#if 0
108 warnx("%s: %s", *ahost, gai_strerror(error));
109#endif
110 return (-1);
111 }
112 if (res->ai_canonname) {
113 strlcpy(hbuf, res->ai_canonname, sizeof(hbuf));
114 *ahost = hbuf;
115 } else
116 ; /*XXX*/
117
118 r = res;
119 refused = 0;
120 sigemptyset(&mask);
121 sigaddset(&mask, SIGURG);
122 sigprocmask(SIG_BLOCK, &mask, &oldmask);
123 for (timo = 1, lport = IPPORT_RESERVED - 1;;) {
124 s = rresvport_af(&lport, r->ai_family);
125 if (s < 0) {
126 if (errno == EAGAIN)
127 (void)fprintf(stderr,
128 "rcmd: socket: All ports in use\n");
129 else
130 (void)fprintf(stderr, "rcmd: socket: %s\n",
131 strerror(errno));
132 if (r->ai_next) {
133 r = r->ai_next;
134 continue;
135 } else {
136 sigprocmask(SIG_SETMASK, &oldmask, NULL);
137 freeaddrinfo(res);
138 return (-1);
139 }
140 }
141 fcntl(s, F_SETOWN, pid);
142 if (connect(s, r->ai_addr, r->ai_addrlen) >= 0)
143 break;
144 (void)close(s);
145 if (errno == EADDRINUSE) {
146 lport--;
147 continue;
148 }
149 if (errno == ECONNREFUSED)
150 refused++;
151 if (r->ai_next) {
152 int oerrno = errno;
153 char hbuf[NI_MAXHOST];
154 const int niflags = NI_NUMERICHOST;
155
156 hbuf[0] = '\0';
157 if (getnameinfo(r->ai_addr, r->ai_addrlen,
158 hbuf, sizeof(hbuf), NULL, 0, niflags) != 0)
159 strlcpy(hbuf, "(invalid)", sizeof hbuf);
160 (void)fprintf(stderr, "connect to address %s: ", hbuf);
161 errno = oerrno;
162 perror(0);
163 r = r->ai_next;
164 hbuf[0] = '\0';
165 if (getnameinfo(r->ai_addr, r->ai_addrlen,
166 hbuf, sizeof(hbuf), NULL, 0, niflags) != 0)
167 strlcpy(hbuf, "(invalid)", sizeof hbuf);
168 (void)fprintf(stderr, "Trying %s...\n", hbuf);
169 continue;
170 }
171 if (refused && timo <= 16) {
172 (void)sleep(timo);
173 timo *= 2;
174 r = res;
175 refused = 0;
176 continue;
177 }
178 (void)fprintf(stderr, "%s: %s\n", res->ai_canonname,
179 strerror(errno));
180 sigprocmask(SIG_SETMASK, &oldmask, NULL);
181 freeaddrinfo(res);
182 return (-1);
183 }
184 /* given "af" can be PF_UNSPEC, we need the real af for "s" */
185 af = r->ai_family;
186 freeaddrinfo(res);
187#if 0
188 /*
189 * try to rresvport() to the same port. This will make rresvport()
190 * fail it's first bind, resulting in it choosing a random port.
191 */
192 lport--;
193#endif
194 if (fd2p == 0) {
195 write(s, "", 1);
196 lport = 0;
197 } else {
198 char num[8];
199 int s2 = rresvport_af(&lport, af), s3;
200 socklen_t len = sizeof(from);
201 int fdssize = howmany(MAX(s, s2)+1, NFDBITS) * sizeof(fd_mask);
202
203 if (s2 < 0)
204 goto bad;
205 readsp = (fd_set *)malloc(fdssize);
206 if (readsp == NULL) {
207 close(s2);
208 goto bad;
209 }
210 listen(s2, 1);
211 (void)snprintf(num, sizeof(num), "%d", lport);
212 if (write(s, num, strlen(num)+1) != strlen(num)+1) {
213 (void)fprintf(stderr,
214 "rcmd: write (setting up stderr): %s\n",
215 strerror(errno));
216 (void)close(s2);
217 goto bad;
218 }
219again:
220 bzero(readsp, fdssize);
221 FD_SET(s, readsp);
222 FD_SET(s2, readsp);
223 errno = 0;
224 if (select(MAX(s, s2) + 1, readsp, 0, 0, 0) < 1 ||
225 !FD_ISSET(s2, readsp)) {
226 if (errno != 0)
227 (void)fprintf(stderr,
228 "rcmd: select (setting up stderr): %s\n",
229 strerror(errno));
230 else
231 (void)fprintf(stderr,
232 "select: protocol failure in circuit setup\n");
233 (void)close(s2);
234 goto bad;
235 }
236 s3 = accept(s2, (struct sockaddr *)&from, &len);
237 if (s3 < 0) {
238 (void)fprintf(stderr,
239 "rcmd: accept: %s\n", strerror(errno));
240 lport = 0;
241 close(s2);
242 goto bad;
243 }
244
245 /*
246 * XXX careful for ftp bounce attacks. If discovered, shut them
247 * down and check for the real auxiliary channel to connect.
248 */
249 switch (from.ss_family) {
250 case AF_INET:
251 case AF_INET6:
252 if (getnameinfo((struct sockaddr *)&from, len,
253 NULL, 0, num, sizeof(num), NI_NUMERICSERV) == 0 &&
254 atoi(num) != 20) {
255 break;
256 }
257 close(s3);
258 goto again;
259 default:
260 break;
261 }
262 (void)close(s2);
263
264 *fd2p = s3;
265 switch (from.ss_family) {
266 case AF_INET:
267 case AF_INET6:
268 if (getnameinfo((struct sockaddr *)&from, len,
269 NULL, 0, num, sizeof(num), NI_NUMERICSERV) != 0 ||
270 (atoi(num) >= IPPORT_RESERVED ||
271 atoi(num) < IPPORT_RESERVED / 2)) {
272 (void)fprintf(stderr,
273 "socket: protocol failure in circuit setup.\n");
274 goto bad2;
275 }
276 break;
277 default:
278 break;
279 }
280 }
281 (void)write(s, locuser, strlen(locuser)+1);
282 (void)write(s, remuser, strlen(remuser)+1);
283 (void)write(s, cmd, strlen(cmd)+1);
284 if (read(s, &c, 1) != 1) {
285 (void)fprintf(stderr,
286 "rcmd: %s: %s\n", *ahost, strerror(errno));
287 goto bad2;
288 }
289 if (c != 0) {
290 while (read(s, &c, 1) == 1) {
291 (void)write(STDERR_FILENO, &c, 1);
292 if (c == '\n')
293 break;
294 }
295 goto bad2;
296 }
297 sigprocmask(SIG_SETMASK, &oldmask, NULL);
298 free(readsp);
299 return (s);
300bad2:
301 if (lport)
302 (void)close(*fd2p);
303bad:
304 if (readsp)
305 free(readsp);
306 (void)close(s);
307 sigprocmask(SIG_SETMASK, &oldmask, NULL);
308 return (-1);
309}
310
311int __check_rhosts_file = 1;
312char *__rcmd_errstr;
313
314int
315ruserok(const char *rhost, int superuser, const char *ruser, const char *luser)
316{
317 struct addrinfo hints, *res, *r;
318 int error;
319
320 memset(&hints, 0, sizeof(hints));
321 hints.ai_family = PF_UNSPEC;
322 hints.ai_socktype = SOCK_DGRAM; /*dummy*/
323 error = getaddrinfo(rhost, "0", &hints, &res);
324 if (error)
325 return (-1);
326
327 for (r = res; r; r = r->ai_next) {
328 if (iruserok_sa(r->ai_addr, r->ai_addrlen, superuser, ruser,
329 luser) == 0) {
330 freeaddrinfo(res);
331 return (0);
332 }
333 }
334 freeaddrinfo(res);
335 return (-1);
336}
337
338/*
339 * New .rhosts strategy: We are passed an ip address. We spin through
340 * hosts.equiv and .rhosts looking for a match. When the .rhosts only
341 * has ip addresses, we don't have to trust a nameserver. When it
342 * contains hostnames, we spin through the list of addresses the nameserver
343 * gives us and look for a match.
344 *
345 * Returns 0 if ok, -1 if not ok.
346 */
347int
348iruserok(u_int32_t raddr, int superuser, const char *ruser, const char *luser)
349{
350 struct sockaddr_in sin;
351
352 memset(&sin, 0, sizeof(sin));
353 sin.sin_family = AF_INET;
354 sin.sin_len = sizeof(struct sockaddr_in);
355 memcpy(&sin.sin_addr, &raddr, sizeof(sin.sin_addr));
356 return iruserok_sa(&sin, sizeof(struct sockaddr_in), superuser, ruser,
357 luser);
358}
359
360int
361iruserok_sa(const void *raddr, int rlen, int superuser, const char *ruser,
362 const char *luser)
363{
364 struct sockaddr *sa;
365 char *cp;
366 struct stat sbuf;
367 struct passwd *pwd;
368 FILE *hostf;
369 uid_t uid;
370 int first;
371 char pbuf[MAXPATHLEN];
372
373 sa = (struct sockaddr *)raddr;
374 first = 1;
375 hostf = superuser ? NULL : fopen(_PATH_HEQUIV, "r");
376again:
377 if (hostf) {
378 if (__ivaliduser_sa(hostf, sa, rlen, luser, ruser) == 0) {
379 (void)fclose(hostf);
380 return (0);
381 }
382 (void)fclose(hostf);
383 }
384 if (first == 1 && (__check_rhosts_file || superuser)) {
385 first = 0;
386 if ((pwd = getpwnam(luser)) == NULL)
387 return (-1);
388 snprintf(pbuf, sizeof pbuf, "%s/.rhosts", pwd->pw_dir);
389
390 /*
391 * Change effective uid while opening .rhosts. If root and
392 * reading an NFS mounted file system, can't read files that
393 * are protected read/write owner only.
394 */
395 uid = geteuid();
396 (void)seteuid(pwd->pw_uid);
397 hostf = fopen(pbuf, "r");
398 (void)seteuid(uid);
399
400 if (hostf == NULL)
401 return (-1);
402 /*
403 * If not a regular file, or is owned by someone other than
404 * user or root or if writeable by anyone but the owner, quit.
405 */
406 cp = NULL;
407 if (lstat(pbuf, &sbuf) < 0)
408 cp = ".rhosts lstat failed";
409 else if (!S_ISREG(sbuf.st_mode))
410 cp = ".rhosts not regular file";
411 else if (fstat(fileno(hostf), &sbuf) < 0)
412 cp = ".rhosts fstat failed";
413 else if (sbuf.st_uid && sbuf.st_uid != pwd->pw_uid)
414 cp = "bad .rhosts owner";
415 else if (sbuf.st_mode & (S_IWGRP|S_IWOTH))
416 cp = ".rhosts writable by other than owner";
417 /* If there were any problems, quit. */
418 if (cp) {
419 __rcmd_errstr = cp;
420 (void)fclose(hostf);
421 return (-1);
422 }
423 goto again;
424 }
425 return (-1);
426}
427
428/*
429 * XXX
430 * Don't make static, used by lpd(8).
431 *
432 * Returns 0 if ok, -1 if not ok.
433 */
434int
435__ivaliduser(FILE *hostf, in_addr_t raddrl, const char *luser,
436 const char *ruser)
437{
438 struct sockaddr_in sin;
439
440 memset(&sin, 0, sizeof(sin));
441 sin.sin_family = AF_INET;
442 sin.sin_len = sizeof(struct sockaddr_in);
443 memcpy(&sin.sin_addr, &raddrl, sizeof(sin.sin_addr));
444 return __ivaliduser_sa(hostf, (struct sockaddr *)&sin, sin.sin_len,
445 luser, ruser);
446}
447
448int
449__ivaliduser_sa(FILE *hostf, struct sockaddr *raddr, socklen_t salen,
450 const char *luser, const char *ruser)
451{
452 char *user, *p;
453 char *buf;
454 const char *auser, *ahost;
455 int hostok, userok;
456 char *rhost = (char *)-1;
457 char domain[MAXHOSTNAMELEN];
458 size_t buflen;
459
460 getdomainname(domain, sizeof(domain));
461
462 while ((buf = fgetln(hostf, &buflen))) {
463 p = buf;
464 if (*p == '#')
465 continue;
466 while (p < buf + buflen && *p != '\n' && *p != ' ' && *p != '\t') {
467 if (!isprint(*p))
468 goto bail;
469 *p = isupper(*p) ? tolower(*p) : *p;
470 p++;
471 }
472 if (p >= buf + buflen)
473 continue;
474 if (*p == ' ' || *p == '\t') {
475 *p++ = '\0';
476 while (p < buf + buflen && (*p == ' ' || *p == '\t'))
477 p++;
478 if (p >= buf + buflen)
479 continue;
480 user = p;
481 while (p < buf + buflen && *p != '\n' && *p != ' ' &&
482 *p != '\t') {
483 if (!isprint(*p))
484 goto bail;
485 p++;
486 }
487 } else
488 user = p;
489 *p = '\0';
490
491 if (p == buf)
492 continue;
493
494 auser = *user ? user : luser;
495 ahost = buf;
496
497 if (strlen(ahost) >= MAXHOSTNAMELEN)
498 continue;
499
500 /*
501 * innetgr() must lookup a hostname (we do not attempt
502 * to change the semantics so that netgroups may have
503 * #.#.#.# addresses in the list.)
504 */
505 if (ahost[0] == '+')
506 switch (ahost[1]) {
507 case '\0':
508 hostok = 1;
509 break;
510 case '@':
511 if (rhost == (char *)-1)
512 rhost = __gethostloop(raddr, salen);
513 hostok = 0;
514 if (rhost)
515 hostok = innetgr(&ahost[2], rhost,
516 NULL, domain);
517 break;
518 default:
519 hostok = __icheckhost(raddr, salen, &ahost[1]);
520 break;
521 }
522 else if (ahost[0] == '-')
523 switch (ahost[1]) {
524 case '\0':
525 hostok = -1;
526 break;
527 case '@':
528 if (rhost == (char *)-1)
529 rhost = __gethostloop(raddr, salen);
530 hostok = 0;
531 if (rhost)
532 hostok = -innetgr(&ahost[2], rhost,
533 NULL, domain);
534 break;
535 default:
536 hostok = -__icheckhost(raddr, salen, &ahost[1]);
537 break;
538 }
539 else
540 hostok = __icheckhost(raddr, salen, ahost);
541
542
543 if (auser[0] == '+')
544 switch (auser[1]) {
545 case '\0':
546 userok = 1;
547 break;
548 case '@':
549 userok = innetgr(&auser[2], NULL, ruser,
550 domain);
551 break;
552 default:
553 userok = strcmp(ruser, &auser[1]) ? 0 : 1;
554 break;
555 }
556 else if (auser[0] == '-')
557 switch (auser[1]) {
558 case '\0':
559 userok = -1;
560 break;
561 case '@':
562 userok = -innetgr(&auser[2], NULL, ruser,
563 domain);
564 break;
565 default:
566 userok = strcmp(ruser, &auser[1]) ? 0 : -1;
567 break;
568 }
569 else
570 userok = strcmp(ruser, auser) ? 0 : 1;
571
572 /* Check if one component did not match */
573 if (hostok == 0 || userok == 0)
574 continue;
575
576 /* Check if we got a forbidden pair */
577 if (userok <= -1 || hostok <= -1)
578 return (-1);
579
580 /* Check if we got a valid pair */
581 if (hostok >= 1 && userok >= 1)
582 return (0);
583 }
584bail:
585 return (-1);
586}
587
588/*
589 * Returns "true" if match, 0 if no match. If we do not find any
590 * semblance of an A->PTR->A loop, allow a simple #.#.#.# match to work.
591 */
592static int
593__icheckhost(struct sockaddr *raddr, socklen_t salen, const char *lhost)
594{
595 struct addrinfo hints, *res, *r;
596 char h1[NI_MAXHOST], h2[NI_MAXHOST];
597 int error;
598 const int niflags = NI_NUMERICHOST;
599
600 h1[0] = '\0';
601 if (getnameinfo(raddr, salen, h1, sizeof(h1), NULL, 0,
602 niflags) != 0)
603 return (0);
604
605 /* Resolve laddr into sockaddr */
606 memset(&hints, 0, sizeof(hints));
607 hints.ai_family = raddr->sa_family;
608 hints.ai_socktype = SOCK_DGRAM; /*dummy*/
609 res = NULL;
610 error = getaddrinfo(lhost, "0", &hints, &res);
611 if (error)
612 return (0);
613
614 /*
615 * Try string comparisons between raddr and laddr.
616 */
617 for (r = res; r; r = r->ai_next) {
618 h2[0] = '\0';
619 if (getnameinfo(r->ai_addr, r->ai_addrlen, h2, sizeof(h2),
620 NULL, 0, niflags) != 0)
621 continue;
622 if (strcmp(h1, h2) == 0) {
623 freeaddrinfo(res);
624 return (1);
625 }
626 }
627
628 /* No match. */
629 freeaddrinfo(res);
630 return (0);
631}
632
633/*
634 * Return the hostname associated with the supplied address.
635 * Do a reverse lookup as well for security. If a loop cannot
636 * be found, pack the result of inet_ntoa() into the string.
637 */
638static char *
639__gethostloop(struct sockaddr *raddr, socklen_t salen)
640{
641 static char remotehost[NI_MAXHOST];
642 char h1[NI_MAXHOST], h2[NI_MAXHOST];
643 struct addrinfo hints, *res, *r;
644 int error;
645 const int niflags = NI_NUMERICHOST;
646
647 h1[0] = remotehost[0] = '\0';
648 if (getnameinfo(raddr, salen, remotehost, sizeof(remotehost),
649 NULL, 0, NI_NAMEREQD) != 0)
650 return (NULL);
651 if (getnameinfo(raddr, salen, h1, sizeof(h1), NULL, 0,
652 niflags) != 0)
653 return (NULL);
654
655 /*
656 * Look up the name and check that the supplied
657 * address is in the list
658 */
659 memset(&hints, 0, sizeof(hints));
660 hints.ai_family = raddr->sa_family;
661 hints.ai_socktype = SOCK_DGRAM; /*dummy*/
662 hints.ai_flags = AI_CANONNAME;
663 res = NULL;
664 error = getaddrinfo(remotehost, "0", &hints, &res);
665 if (error)
666 return (NULL);
667
668 for (r = res; r; r = r->ai_next) {
669 h2[0] = '\0';
670 if (getnameinfo(r->ai_addr, r->ai_addrlen, h2, sizeof(h2),
671 NULL, 0, niflags) != 0)
672 continue;
673 if (strcmp(h1, h2) == 0) {
674 freeaddrinfo(res);
675 return (remotehost);
676 }
677 }
678
679 /*
680 * either the DNS adminstrator has made a configuration
681 * mistake, or someone has attempted to spoof us
682 */
683 syslog(LOG_NOTICE, "rcmd: address %s not listed for host %s",
684 h1, res->ai_canonname ? res->ai_canonname : remotehost);
685 freeaddrinfo(res);
686 return (NULL);
687}
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..34a228d1e9
--- /dev/null
+++ b/src/lib/libc/net/rcmdsh.c
@@ -0,0 +1,186 @@
1/* $OpenBSD: rcmdsh.c,v 1.11 2005/08/06 20:30:03 espie 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#include <sys/types.h>
37#include <sys/socket.h>
38#include <sys/wait.h>
39#include <signal.h>
40#include <errno.h>
41#include <netdb.h>
42#include <stdio.h>
43#include <stdlib.h>
44#include <string.h>
45#include <pwd.h>
46#include <paths.h>
47#include <unistd.h>
48
49/*
50 * This is a replacement rcmd() function that uses the rsh(1)
51 * program in place of a direct rcmd(3) function call so as to
52 * avoid having to be root. Note that rport is ignored.
53 */
54/* ARGSUSED */
55int
56rcmdsh(char **ahost, int rport, const char *locuser, const char *remuser,
57 const char *cmd, char *rshprog)
58{
59 struct hostent *hp;
60 int sp[2];
61 pid_t cpid;
62 char *p;
63 struct passwd *pw;
64
65 /* What rsh/shell to use. */
66 if (rshprog == NULL)
67 rshprog = _PATH_RSH;
68
69 /* locuser must exist on this host. */
70 if ((pw = getpwnam(locuser)) == NULL) {
71 (void) fprintf(stderr, "rcmdsh: unknown user: %s\n", locuser);
72 return(-1);
73 }
74
75 /* Validate remote hostname. */
76 if (strcmp(*ahost, "localhost") != 0) {
77 if (((hp = gethostbyname2(*ahost, AF_INET)) == NULL) &&
78 ((hp = gethostbyname2(*ahost, AF_INET6)) == NULL)) {
79 herror(*ahost);
80 return(-1);
81 }
82 *ahost = hp->h_name;
83 }
84
85 /* Get a socketpair we'll use for stdin and stdout. */
86 if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, sp) < 0) {
87 perror("rcmdsh: socketpair");
88 return(-1);
89 }
90
91 cpid = fork();
92 if (cpid < 0) {
93 perror("rcmdsh: fork failed");
94 return(-1);
95 } else if (cpid == 0) {
96 /*
97 * Child. We use sp[1] to be stdin/stdout, and close sp[0].
98 */
99 (void) close(sp[0]);
100 if (dup2(sp[1], 0) < 0 || dup2(0, 1) < 0) {
101 perror("rcmdsh: dup2 failed");
102 _exit(255);
103 }
104 /* Fork again to lose parent. */
105 cpid = fork();
106 if (cpid < 0) {
107 perror("rcmdsh: fork to lose parent failed");
108 _exit(255);
109 }
110 if (cpid > 0)
111 _exit(0);
112
113 /* In grandchild here. Become local user for rshprog. */
114 if (setuid(pw->pw_uid)) {
115 (void) fprintf(stderr, "rcmdsh: setuid(%u): %s\n",
116 pw->pw_uid, strerror(errno));
117 _exit(255);
118 }
119
120 /*
121 * If remote host is "localhost" and local and remote user
122 * are the same, avoid running remote shell for efficiency.
123 */
124 if (!strcmp(*ahost, "localhost") && !strcmp(locuser, remuser)) {
125 char *argv[4];
126 if (pw->pw_shell[0] == '\0')
127 rshprog = _PATH_BSHELL;
128 else
129 rshprog = pw->pw_shell;
130 p = strrchr(rshprog, '/');
131 argv[0] = p ? p + 1 : rshprog;
132 argv[1] = "-c";
133 argv[2] = (char *)cmd;
134 argv[3] = NULL;
135 execvp(rshprog, argv);
136 } else if ((p = strchr(rshprog, ' ')) == NULL) {
137 /* simple case */
138 char *argv[6];
139 p = strrchr(rshprog, '/');
140 argv[0] = p ? p + 1 : rshprog;
141 argv[1] = "-l";
142 argv[2] = (char *)remuser;
143 argv[3] = *ahost;
144 argv[4] = (char *)cmd;
145 argv[5] = NULL;
146 execvp(rshprog, argv);
147 } else {
148 /* must pull args out of rshprog and dyn alloc argv */
149 char **argv, **ap;
150 int n;
151 for (n = 7; (p = strchr(++p, ' ')) != NULL; n++)
152 continue;
153 rshprog = strdup(rshprog);
154 ap = argv = malloc(sizeof(char *) * n);
155 if (rshprog == NULL || argv == NULL) {
156 perror("rcmdsh");
157 _exit(255);
158 }
159 while ((p = strsep(&rshprog, " ")) != NULL) {
160 if (*p == '\0')
161 continue;
162 *ap++ = p;
163 }
164 if (ap != argv) /* all spaces?!? */
165 rshprog = argv[0];
166 if ((p = strrchr(argv[0], '/')) != NULL)
167 argv[0] = p + 1;
168 *ap++ = "-l";
169 *ap++ = (char *)remuser;
170 *ap++ = *ahost;
171 *ap++ = (char *)cmd;
172 *ap++ = NULL;
173 execvp(rshprog, argv);
174 }
175 (void) fprintf(stderr, "rcmdsh: execvp %s failed: %s\n",
176 rshprog, strerror(errno));
177 _exit(255);
178 } else {
179 /* Parent. close sp[1], return sp[0]. */
180 (void) close(sp[1]);
181 /* Reap child. */
182 (void) wait(NULL);
183 return(sp[0]);
184 }
185 /* NOTREACHED */
186}
diff --git a/src/lib/libc/net/recv.c b/src/lib/libc/net/recv.c
new file mode 100644
index 0000000000..6241cc6b12
--- /dev/null
+++ b/src/lib/libc/net/recv.c
@@ -0,0 +1,40 @@
1/* $OpenBSD: recv.c,v 1.5 2005/08/06 20:30:03 espie Exp $ */
2/*
3 * Copyright (c) 1988, 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
31#include <sys/types.h>
32#include <sys/socket.h>
33
34#include <stddef.h>
35
36ssize_t
37recv(int s, void *buf, size_t len, int flags)
38{
39 return (recvfrom(s, buf, len, flags, NULL, 0));
40}
diff --git a/src/lib/libc/net/res_comp.c b/src/lib/libc/net/res_comp.c
new file mode 100644
index 0000000000..9bdc26dd24
--- /dev/null
+++ b/src/lib/libc/net/res_comp.c
@@ -0,0 +1,474 @@
1/* $OpenBSD: res_comp.c,v 1.13 2005/08/06 20:30:03 espie 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#include <sys/types.h>
55#include <sys/param.h>
56#include <netinet/in.h>
57#include <arpa/nameser.h>
58
59#include <stdio.h>
60#include <resolv.h>
61#include <ctype.h>
62
63#include <unistd.h>
64#include <string.h>
65
66static int dn_find(u_char *, u_char *, u_char **, u_char **);
67
68/*
69 * Expand compressed domain name 'comp_dn' to full domain name.
70 * 'msg' is a pointer to the begining of the message,
71 * 'eomorig' points to the first location after the message,
72 * 'exp_dn' is a pointer to a buffer of size 'length' for the result.
73 * Return size of compressed name or -1 if there was an error.
74 */
75int
76dn_expand(const u_char *msg, const u_char *eomorig, const u_char *comp_dn,
77 char *exp_dn, int length)
78{
79 const u_char *cp;
80 char *dn;
81 int n, c;
82 char *eom;
83 int len = -1, checked = 0;
84
85 dn = exp_dn;
86 cp = comp_dn;
87 if (length > MAXHOSTNAMELEN-1)
88 length = MAXHOSTNAMELEN-1;
89 eom = exp_dn + length;
90 /*
91 * fetch next label in domain name
92 */
93 while ((n = *cp++)) {
94 /*
95 * Check for indirection
96 */
97 switch (n & INDIR_MASK) {
98 case 0:
99 if (dn != exp_dn) {
100 if (dn >= eom)
101 return (-1);
102 *dn++ = '.';
103 }
104 if (dn+n >= eom)
105 return (-1);
106 checked += n + 1;
107 while (--n >= 0) {
108 if (((c = *cp++) == '.') || (c == '\\')) {
109 if (dn + n + 2 >= eom)
110 return (-1);
111 *dn++ = '\\';
112 }
113 *dn++ = c;
114 if (cp >= eomorig) /* out of range */
115 return (-1);
116 }
117 break;
118
119 case INDIR_MASK:
120 if (len < 0)
121 len = cp - comp_dn + 1;
122 cp = msg + (((n & 0x3f) << 8) | (*cp & 0xff));
123 if (cp < msg || cp >= eomorig) /* out of range */
124 return (-1);
125 checked += 2;
126 /*
127 * Check for loops in the compressed name;
128 * if we've looked at the whole message,
129 * there must be a loop.
130 */
131 if (checked >= eomorig - msg)
132 return (-1);
133 break;
134
135 default:
136 return (-1); /* flag error */
137 }
138 }
139 *dn = '\0';
140 if (len < 0)
141 len = cp - comp_dn;
142 return (len);
143}
144
145/*
146 * Compress domain name 'exp_dn' into 'comp_dn'.
147 * Return the size of the compressed name or -1.
148 * 'length' is the size of the array pointed to by 'comp_dn'.
149 * 'dnptrs' is a list of pointers to previous compressed names. dnptrs[0]
150 * is a pointer to the beginning of the message. The list ends with NULL.
151 * 'lastdnptr' is a pointer to the end of the arrary pointed to
152 * by 'dnptrs'. Side effect is to update the list of pointers for
153 * labels inserted into the message as we compress the name.
154 * If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr'
155 * is NULL, we don't update the list.
156 */
157int
158dn_comp(const char *exp_dn, u_char *comp_dn, int length, u_char **dnptrs,
159 u_char **lastdnptr)
160{
161 u_char *cp, *dn;
162 int c, l;
163 u_char **cpp, **lpp, *sp, *eob;
164 u_char *msg;
165
166 dn = (u_char *)exp_dn;
167 cp = comp_dn;
168 eob = cp + length;
169 lpp = cpp = NULL;
170 if (dnptrs != NULL) {
171 if ((msg = *dnptrs++) != NULL) {
172 for (cpp = dnptrs; *cpp != NULL; cpp++)
173 ;
174 lpp = cpp; /* end of list to search */
175 }
176 } else
177 msg = NULL;
178 for (c = *dn++; c != '\0'; ) {
179 /* look to see if we can use pointers */
180 if (msg != NULL) {
181 if ((l = dn_find(dn-1, msg, dnptrs, lpp)) >= 0) {
182 if (cp+1 >= eob)
183 return (-1);
184 *cp++ = (l >> 8) | INDIR_MASK;
185 *cp++ = l % 256;
186 return (cp - comp_dn);
187 }
188 /* not found, save it */
189 if (lastdnptr != NULL && cpp < lastdnptr-1) {
190 *cpp++ = cp;
191 *cpp = NULL;
192 }
193 }
194 sp = cp++; /* save ptr to length byte */
195 do {
196 if (c == '.') {
197 c = *dn++;
198 break;
199 }
200 if (c == '\\') {
201 if ((c = *dn++) == '\0')
202 break;
203 }
204 if (cp >= eob) {
205 if (msg != NULL)
206 *lpp = NULL;
207 return (-1);
208 }
209 *cp++ = c;
210 } while ((c = *dn++) != '\0');
211 /* catch trailing '.'s but not '..' */
212 if ((l = cp - sp - 1) == 0 && c == '\0') {
213 cp--;
214 break;
215 }
216 if (l <= 0 || l > MAXLABEL) {
217 if (msg != NULL)
218 *lpp = NULL;
219 return (-1);
220 }
221 *sp = l;
222 }
223 if (cp >= eob) {
224 if (msg != NULL)
225 *lpp = NULL;
226 return (-1);
227 }
228 *cp++ = '\0';
229 return (cp - comp_dn);
230}
231
232/*
233 * Skip over a compressed domain name. Return the size or -1.
234 */
235int
236__dn_skipname(const u_char *comp_dn, const u_char *eom)
237{
238 const u_char *cp;
239 int n;
240
241 cp = comp_dn;
242 while (cp < eom && (n = *cp++)) {
243 /*
244 * check for indirection
245 */
246 switch (n & INDIR_MASK) {
247 case 0: /* normal case, n == len */
248 cp += n;
249 continue;
250 case INDIR_MASK: /* indirection */
251 cp++;
252 break;
253 default: /* illegal type */
254 return (-1);
255 }
256 break;
257 }
258 if (cp > eom)
259 return (-1);
260 return (cp - comp_dn);
261}
262
263static int
264mklower(int ch)
265{
266 if (isascii(ch) && isupper(ch))
267 return (tolower(ch));
268 return (ch);
269}
270
271/*
272 * Search for expanded name from a list of previously compressed names.
273 * Return the offset from msg if found or -1.
274 * dnptrs is the pointer to the first name on the list,
275 * not the pointer to the start of the message.
276 */
277static int
278dn_find(u_char *exp_dn, u_char *msg, u_char **dnptrs, u_char **lastdnptr)
279{
280 u_char *dn, *cp, **cpp;
281 int n;
282 u_char *sp;
283
284 for (cpp = dnptrs; cpp < lastdnptr; cpp++) {
285 dn = exp_dn;
286 sp = cp = *cpp;
287 while ((n = *cp++)) {
288 /*
289 * check for indirection
290 */
291 switch (n & INDIR_MASK) {
292 case 0: /* normal case, n == len */
293 while (--n >= 0) {
294 if (*dn == '.')
295 goto next;
296 if (*dn == '\\')
297 dn++;
298 if (mklower(*dn++) != mklower(*cp++))
299 goto next;
300 }
301 if ((n = *dn++) == '\0' && *cp == '\0')
302 return (sp - msg);
303 if (n == '.')
304 continue;
305 goto next;
306
307 case INDIR_MASK: /* indirection */
308 cp = msg + (((n & 0x3f) << 8) | *cp);
309 break;
310
311 default: /* illegal type */
312 return (-1);
313 }
314 }
315 if (*dn == '\0')
316 return (sp - msg);
317 next: ;
318 }
319 return (-1);
320}
321
322/*
323 * Verify that a domain name uses an acceptable character set.
324 */
325
326/*
327 * Note the conspicuous absence of ctype macros in these definitions. On
328 * non-ASCII hosts, we can't depend on string literals or ctype macros to
329 * tell us anything about network-format data. The rest of the BIND system
330 * is not careful about this, but for some reason, we're doing it right here.
331 */
332#define PERIOD 0x2e
333#define hyphenchar(c) ((c) == 0x2d)
334#define bslashchar(c) ((c) == 0x5c)
335#define periodchar(c) ((c) == PERIOD)
336#define asterchar(c) ((c) == 0x2a)
337#define alphachar(c) (((c) >= 0x41 && (c) <= 0x5a) \
338 || ((c) >= 0x61 && (c) <= 0x7a))
339#define digitchar(c) ((c) >= 0x30 && (c) <= 0x39)
340
341#define borderchar(c) (alphachar(c) || digitchar(c))
342#define middlechar(c) (borderchar(c) || hyphenchar(c))
343#define domainchar(c) ((c) > 0x20 && (c) < 0x7f)
344
345int
346res_hnok(const char *dn)
347{
348 int pch = PERIOD, ch = *dn++;
349
350 while (ch != '\0') {
351 int nch = *dn++;
352
353 if (periodchar(ch)) {
354 ;
355 } else if (periodchar(pch)) {
356 if (!borderchar(ch))
357 return (0);
358 } else if (periodchar(nch) || nch == '\0') {
359 if (!borderchar(ch))
360 return (0);
361 } else {
362 if (!middlechar(ch))
363 return (0);
364 }
365 pch = ch, ch = nch;
366 }
367 return (1);
368}
369
370/*
371 * hostname-like (A, MX, WKS) owners can have "*" as their first label
372 * but must otherwise be as a host name.
373 */
374int
375res_ownok(const char *dn)
376{
377 if (asterchar(dn[0])) {
378 if (periodchar(dn[1]))
379 return (res_hnok(dn+2));
380 if (dn[1] == '\0')
381 return (1);
382 }
383 return (res_hnok(dn));
384}
385
386/*
387 * SOA RNAMEs and RP RNAMEs can have any printable character in their first
388 * label, but the rest of the name has to look like a host name.
389 */
390int
391res_mailok(const char *dn)
392{
393 int ch, escaped = 0;
394
395 /* "." is a valid missing representation */
396 if (*dn == '\0')
397 return(1);
398
399 /* otherwise <label>.<hostname> */
400 while ((ch = *dn++) != '\0') {
401 if (!domainchar(ch))
402 return (0);
403 if (!escaped && periodchar(ch))
404 break;
405 if (escaped)
406 escaped = 0;
407 else if (bslashchar(ch))
408 escaped = 1;
409 }
410 if (periodchar(ch))
411 return (res_hnok(dn));
412 return(0);
413}
414
415/*
416 * This function is quite liberal, since RFC 1034's character sets are only
417 * recommendations.
418 */
419int
420res_dnok(const char *dn)
421{
422 int ch;
423
424 while ((ch = *dn++) != '\0')
425 if (!domainchar(ch))
426 return (0);
427 return (1);
428}
429
430/*
431 * Routines to insert/extract short/long's.
432 */
433
434u_int16_t
435_getshort(const u_char *msgp)
436{
437 u_int16_t u;
438
439 GETSHORT(u, msgp);
440 return (u);
441}
442
443#ifdef NeXT
444/*
445 * nExt machines have some funky library conventions, which we must maintain.
446 */
447u_int16_t
448res_getshort(msgp)
449 const u_char *msgp;
450{
451 return (_getshort(msgp));
452}
453#endif
454
455u_int32_t
456_getlong(const u_char *msgp)
457{
458 u_int32_t u;
459
460 GETLONG(u, msgp);
461 return (u);
462}
463
464void
465__putshort(u_int16_t s, u_char *msgp)
466{
467 PUTSHORT(s, msgp);
468}
469
470void
471__putlong(u_int32_t l, u_char *msgp)
472{
473 PUTLONG(l, msgp);
474}
diff --git a/src/lib/libc/net/res_data.c b/src/lib/libc/net/res_data.c
new file mode 100644
index 0000000000..a5f6b03a7f
--- /dev/null
+++ b/src/lib/libc/net/res_data.c
@@ -0,0 +1,105 @@
1/* $OpenBSD: res_data.c,v 1.3 2005/08/06 20:30:03 espie 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#include <sys/types.h>
55#include <sys/param.h>
56#include <sys/socket.h>
57#include <sys/time.h>
58#include <netinet/in.h>
59#include <arpa/inet.h>
60#include <arpa/nameser.h>
61
62#include <stdio.h>
63#include <ctype.h>
64#include <resolv.h>
65#include <unistd.h>
66#include <stdlib.h>
67#include <string.h>
68
69const char *_res_opcodes[] = {
70 "QUERY",
71 "IQUERY",
72 "CQUERYM",
73 "CQUERYU", /* experimental */
74 "NOTIFY", /* experimental */
75 "5",
76 "6",
77 "7",
78 "8",
79 "UPDATEA",
80 "UPDATED",
81 "UPDATEDA",
82 "UPDATEM",
83 "UPDATEMA",
84 "ZONEINIT",
85 "ZONEREF",
86};
87
88const char *_res_resultcodes[] = {
89 "NOERROR",
90 "FORMERR",
91 "SERVFAIL",
92 "NXDOMAIN",
93 "NOTIMP",
94 "REFUSED",
95 "6",
96 "7",
97 "8",
98 "9",
99 "10",
100 "11",
101 "12",
102 "13",
103 "14",
104 "NOCHANGE",
105};
diff --git a/src/lib/libc/net/res_debug.c b/src/lib/libc/net/res_debug.c
new file mode 100644
index 0000000000..8e72c2a5e5
--- /dev/null
+++ b/src/lib/libc/net/res_debug.c
@@ -0,0 +1,1394 @@
1/* $OpenBSD: res_debug.c,v 1.21 2005/08/06 20:30:04 espie 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#include <sys/param.h>
77#include <sys/types.h>
78#include <sys/socket.h>
79#include <netinet/in.h>
80#include <arpa/inet.h>
81#include <arpa/nameser.h>
82
83#include <ctype.h>
84#include <netdb.h>
85#include <resolv.h>
86#include <stdio.h>
87#include <time.h>
88
89#include <stdlib.h>
90#include <string.h>
91
92#include "thread_private.h"
93
94extern const char *_res_opcodes[];
95extern const char *_res_resultcodes[];
96
97static const char *loc_ntoal(const u_char *binary, char *ascii, int ascii_len);
98
99/* XXX: we should use getservbyport() instead. */
100static const char *
101dewks(int wks)
102{
103 static char nbuf[20];
104
105 switch (wks) {
106 case 5: return "rje";
107 case 7: return "echo";
108 case 9: return "discard";
109 case 11: return "systat";
110 case 13: return "daytime";
111 case 15: return "netstat";
112 case 17: return "qotd";
113 case 19: return "chargen";
114 case 20: return "ftp-data";
115 case 21: return "ftp";
116 case 23: return "telnet";
117 case 25: return "smtp";
118 case 37: return "time";
119 case 39: return "rlp";
120 case 42: return "name";
121 case 43: return "whois";
122 case 53: return "domain";
123 case 57: return "apts";
124 case 59: return "apfs";
125 case 67: return "bootps";
126 case 68: return "bootpc";
127 case 69: return "tftp";
128 case 77: return "rje";
129 case 79: return "finger";
130 case 87: return "link";
131 case 95: return "supdup";
132 case 100: return "newacct";
133 case 101: return "hostnames";
134 case 102: return "iso-tsap";
135 case 103: return "x400";
136 case 104: return "x400-snd";
137 case 105: return "csnet-ns";
138 case 109: return "pop-2";
139 case 111: return "sunrpc";
140 case 113: return "auth";
141 case 115: return "sftp";
142 case 117: return "uucp-path";
143 case 119: return "nntp";
144 case 121: return "erpc";
145 case 123: return "ntp";
146 case 133: return "statsrv";
147 case 136: return "profile";
148 case 144: return "NeWS";
149 case 161: return "snmp";
150 case 162: return "snmp-trap";
151 case 170: return "print-srv";
152 default:
153 (void) snprintf(nbuf, sizeof nbuf, "%d", wks);
154 return (nbuf);
155 }
156}
157
158/* XXX: we should use getprotobynumber() instead. */
159static const char *
160deproto(int protonum)
161{
162 static char nbuf[20];
163
164 switch (protonum) {
165 case 1: return "icmp";
166 case 2: return "igmp";
167 case 3: return "ggp";
168 case 5: return "st";
169 case 6: return "tcp";
170 case 7: return "ucl";
171 case 8: return "egp";
172 case 9: return "igp";
173 case 11: return "nvp-II";
174 case 12: return "pup";
175 case 16: return "chaos";
176 case 17: return "udp";
177 default:
178 (void) snprintf(nbuf, sizeof nbuf, "%d", protonum);
179 return (nbuf);
180 }
181}
182
183static const u_char *
184do_rrset(const u_char *msg, int len, const u_char *cp, int cnt, int pflag,
185 FILE *file, const char *hs)
186{
187 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
188 int n;
189 int sflag;
190
191 /*
192 * Print answer records.
193 */
194 sflag = (_resp->pfcode & pflag);
195 if ((n = ntohs(cnt))) {
196 if ((!_resp->pfcode) ||
197 ((sflag) && (_resp->pfcode & RES_PRF_HEAD1)))
198 fprintf(file, "%s", hs);
199 while (--n >= 0) {
200 if ((!_resp->pfcode) || sflag) {
201 cp = p_rr(cp, msg, file);
202 } else {
203 unsigned int dlen;
204 cp += __dn_skipname(cp, cp + MAXCDNAME);
205 cp += INT16SZ;
206 cp += INT16SZ;
207 cp += INT32SZ;
208 dlen = _getshort((u_char*)cp);
209 cp += INT16SZ;
210 cp += dlen;
211 }
212 if ((cp - msg) > len)
213 return (NULL);
214 }
215 if ((!_resp->pfcode) ||
216 ((sflag) && (_resp->pfcode & RES_PRF_HEAD1)))
217 putc('\n', file);
218 }
219 return (cp);
220}
221
222void
223__p_query(const u_char *msg)
224{
225 __fp_query(msg, stdout);
226}
227
228/*
229 * Print the current options.
230 * This is intended to be primarily a debugging routine.
231 */
232void
233__fp_resstat(struct __res_state *statp, FILE *file)
234{
235 u_long mask;
236
237 fprintf(file, ";; res options:");
238 if (!statp)
239 statp = &_res;
240 for (mask = 1; mask != 0; mask <<= 1)
241 if (statp->options & mask)
242 fprintf(file, " %s", p_option(mask));
243 putc('\n', file);
244}
245
246/*
247 * Print the contents of a query.
248 * This is intended to be primarily a debugging routine.
249 */
250void
251__fp_nquery(const u_char *msg, int len, FILE *file)
252{
253 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
254 const u_char *cp, *endMark;
255 const HEADER *hp;
256 int n;
257
258 if (_res_init(0) == -1)
259 return;
260
261#define TruncTest(x) if (x > endMark) goto trunc
262#define ErrorTest(x) if (x == NULL) goto error
263
264 /*
265 * Print header fields.
266 */
267 hp = (HEADER *)msg;
268 cp = msg + HFIXEDSZ;
269 endMark = msg + len;
270 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_HEADX) || hp->rcode) {
271 fprintf(file, ";; ->>HEADER<<- opcode: %s, status: %s, id: %u",
272 _res_opcodes[hp->opcode],
273 _res_resultcodes[hp->rcode],
274 ntohs(hp->id));
275 putc('\n', file);
276 }
277 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_HEADX))
278 putc(';', file);
279 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_HEAD2)) {
280 fprintf(file, "; flags:");
281 if (hp->qr)
282 fprintf(file, " qr");
283 if (hp->aa)
284 fprintf(file, " aa");
285 if (hp->tc)
286 fprintf(file, " tc");
287 if (hp->rd)
288 fprintf(file, " rd");
289 if (hp->ra)
290 fprintf(file, " ra");
291 if (hp->unused)
292 fprintf(file, " UNUSED-BIT-ON");
293 if (hp->ad)
294 fprintf(file, " ad");
295 if (hp->cd)
296 fprintf(file, " cd");
297 }
298 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_HEAD1)) {
299 fprintf(file, "; Ques: %u", ntohs(hp->qdcount));
300 fprintf(file, ", Ans: %u", ntohs(hp->ancount));
301 fprintf(file, ", Auth: %u", ntohs(hp->nscount));
302 fprintf(file, ", Addit: %u", ntohs(hp->arcount));
303 }
304 if ((!_resp->pfcode) || (_resp->pfcode &
305 (RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1))) {
306 putc('\n',file);
307 }
308 /*
309 * Print question records.
310 */
311 if ((n = ntohs(hp->qdcount))) {
312 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_QUES))
313 fprintf(file, ";; QUESTIONS:\n");
314 while (--n >= 0) {
315 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_QUES))
316 fprintf(file, ";;\t");
317 TruncTest(cp);
318 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_QUES))
319 cp = p_cdnname(cp, msg, len, file);
320 else {
321 int n;
322 char name[MAXDNAME];
323
324 if ((n = dn_expand(msg, msg+len, cp, name,
325 sizeof name)) < 0)
326 cp = NULL;
327 else
328 cp += n;
329 }
330 ErrorTest(cp);
331 TruncTest(cp);
332 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_QUES))
333 fprintf(file, ", type = %s",
334 __p_type(_getshort((u_char*)cp)));
335 cp += INT16SZ;
336 TruncTest(cp);
337 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_QUES))
338 fprintf(file, ", class = %s\n",
339 __p_class(_getshort((u_char*)cp)));
340 cp += INT16SZ;
341 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_QUES))
342 putc('\n', file);
343 }
344 }
345 /*
346 * Print authoritative answer records
347 */
348 TruncTest(cp);
349 cp = do_rrset(msg, len, cp, hp->ancount, RES_PRF_ANS, file,
350 ";; ANSWERS:\n");
351 ErrorTest(cp);
352
353 /*
354 * print name server records
355 */
356 TruncTest(cp);
357 cp = do_rrset(msg, len, cp, hp->nscount, RES_PRF_AUTH, file,
358 ";; AUTHORITY RECORDS:\n");
359 ErrorTest(cp);
360
361 TruncTest(cp);
362 /*
363 * print additional records
364 */
365 cp = do_rrset(msg, len, cp, hp->arcount, RES_PRF_ADD, file,
366 ";; ADDITIONAL RECORDS:\n");
367 ErrorTest(cp);
368 return;
369 trunc:
370 fprintf(file, "\n;; ...truncated\n");
371 return;
372 error:
373 fprintf(file, "\n;; ...malformed\n");
374}
375
376void
377__fp_query(const u_char *msg, FILE *file)
378{
379 fp_nquery(msg, PACKETSZ, file);
380}
381
382const u_char *
383__p_cdnname(const u_char *cp, const u_char *msg, int len, FILE *file)
384{
385 char name[MAXDNAME];
386 int n;
387
388 if ((n = dn_expand(msg, msg + len, cp, name, sizeof name)) < 0)
389 return (NULL);
390 if (name[0] == '\0')
391 putc('.', file);
392 else
393 fputs(name, file);
394 return (cp + n);
395}
396
397const u_char *
398__p_cdname(const u_char *cp, const u_char *msg, FILE *file)
399{
400 return (p_cdnname(cp, msg, PACKETSZ, file));
401}
402
403
404/* Return a fully-qualified domain name from a compressed name (with
405 length supplied). */
406
407const u_char *
408__p_fqnname(const u_char *cp, const u_char *msg, int msglen, char *name, int namelen)
409{
410 int n, newlen;
411
412 if ((n = dn_expand(msg, cp + msglen, cp, name, namelen)) < 0)
413 return (NULL);
414 newlen = strlen(name);
415 if (newlen == 0 || name[newlen - 1] != '.') {
416 if (newlen + 1 >= namelen) /* Lack space for final dot */
417 return (NULL);
418 else
419 strlcpy(name + newlen, ".", namelen - newlen);
420 }
421 return (cp + n);
422}
423
424/* XXX: the rest of these functions need to become length-limited, too. (vix)
425 */
426
427const u_char *
428__p_fqname(const u_char *cp, const u_char *msg, FILE *file)
429{
430 char name[MAXDNAME];
431 const u_char *n;
432
433 n = __p_fqnname(cp, msg, MAXCDNAME, name, sizeof name);
434 if (n == NULL)
435 return (NULL);
436 fputs(name, file);
437 return (n);
438}
439
440/*
441 * Print resource record fields in human readable form.
442 */
443const u_char *
444__p_rr(const u_char *cp, const u_char *msg, FILE *file)
445{
446 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
447 int type, class, dlen, n, c;
448 struct in_addr inaddr;
449 const u_char *cp1, *cp2;
450 u_int32_t tmpttl, t;
451 int lcnt;
452 u_int16_t keyflags;
453 char rrname[MAXDNAME]; /* The fqdn of this RR */
454 char base64_key[MAX_KEY_BASE64];
455
456 if (_res_init(0) == -1) {
457 h_errno = NETDB_INTERNAL;
458 return (NULL);
459 }
460 cp = __p_fqnname(cp, msg, MAXCDNAME, rrname, sizeof rrname);
461 if (!cp)
462 return (NULL); /* compression error */
463 fputs(rrname, file);
464
465 type = _getshort((u_char*)cp);
466 cp += INT16SZ;
467 class = _getshort((u_char*)cp);
468 cp += INT16SZ;
469 tmpttl = _getlong((u_char*)cp);
470 cp += INT32SZ;
471 dlen = _getshort((u_char*)cp);
472 cp += INT16SZ;
473 cp1 = cp;
474 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_TTLID))
475 fprintf(file, "\t%lu", (u_long)tmpttl);
476 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_CLASS))
477 fprintf(file, "\t%s", __p_class(class));
478 fprintf(file, "\t%s", __p_type(type));
479 /*
480 * Print type specific data, if appropriate
481 */
482 switch (type) {
483 case T_A:
484 switch (class) {
485 case C_IN:
486 case C_HS:
487 bcopy(cp, (char *)&inaddr, INADDRSZ);
488 if (dlen == 4) {
489 fprintf(file, "\t%s", inet_ntoa(inaddr));
490 cp += dlen;
491 } else if (dlen == 7) {
492 char *address;
493 u_char protocol;
494 in_port_t port;
495
496 address = inet_ntoa(inaddr);
497 cp += INADDRSZ;
498 protocol = *(u_char*)cp;
499 cp += sizeof (u_char);
500 port = _getshort((u_char*)cp);
501 cp += INT16SZ;
502 fprintf(file, "\t%s\t; proto %u, port %u",
503 address, protocol, port);
504 }
505 break;
506 default:
507 cp += dlen;
508 }
509 break;
510 case T_CNAME:
511 case T_MB:
512 case T_MG:
513 case T_MR:
514 case T_NS:
515 case T_PTR:
516 putc('\t', file);
517 if ((cp = p_fqname(cp, msg, file)) == NULL)
518 return (NULL);
519 break;
520
521 case T_HINFO:
522 case T_ISDN:
523 cp2 = cp + dlen;
524 (void) fputs("\t\"", file);
525 if ((n = (unsigned char) *cp++) != 0) {
526 for (c = n; c > 0 && cp < cp2; c--) {
527 if (strchr("\n\"\\", *cp))
528 (void) putc('\\', file);
529 (void) putc(*cp++, file);
530 }
531 }
532 putc('"', file);
533 if (cp < cp2 && (n = (unsigned char) *cp++) != 0) {
534 (void) fputs ("\t\"", file);
535 for (c = n; c > 0 && cp < cp2; c--) {
536 if (strchr("\n\"\\", *cp))
537 (void) putc('\\', file);
538 (void) putc(*cp++, file);
539 }
540 putc('"', file);
541 } else if (type == T_HINFO) {
542 (void) fputs("\"?\"", file);
543 fprintf(file, "\n;; *** Warning *** OS-type missing");
544 }
545 break;
546
547 case T_SOA:
548 putc('\t', file);
549 if ((cp = p_fqname(cp, msg, file)) == NULL)
550 return (NULL);
551 putc(' ', file);
552 if ((cp = p_fqname(cp, msg, file)) == NULL)
553 return (NULL);
554 fputs(" (\n", file);
555 t = _getlong((u_char*)cp); cp += INT32SZ;
556 fprintf(file, "\t\t\t%lu\t; serial\n", (u_long)t);
557 t = _getlong((u_char*)cp); cp += INT32SZ;
558 fprintf(file, "\t\t\t%lu\t; refresh (%s)\n",
559 (u_long)t, __p_time(t));
560 t = _getlong((u_char*)cp); cp += INT32SZ;
561 fprintf(file, "\t\t\t%lu\t; retry (%s)\n",
562 (u_long)t, __p_time(t));
563 t = _getlong((u_char*)cp); cp += INT32SZ;
564 fprintf(file, "\t\t\t%lu\t; expire (%s)\n",
565 (u_long)t, __p_time(t));
566 t = _getlong((u_char*)cp); cp += INT32SZ;
567 fprintf(file, "\t\t\t%lu )\t; minimum (%s)",
568 (u_long)t, __p_time(t));
569 break;
570
571 case T_MX:
572 case T_AFSDB:
573 case T_RT:
574 fprintf(file, "\t%u ", _getshort((u_char*)cp));
575 cp += INT16SZ;
576 if ((cp = p_fqname(cp, msg, file)) == NULL)
577 return (NULL);
578 break;
579
580 case T_PX:
581 fprintf(file, "\t%u ", _getshort((u_char*)cp));
582 cp += INT16SZ;
583 if ((cp = p_fqname(cp, msg, file)) == NULL)
584 return (NULL);
585 putc(' ', file);
586 if ((cp = p_fqname(cp, msg, file)) == NULL)
587 return (NULL);
588 break;
589
590 case T_X25:
591 cp2 = cp + dlen;
592 (void) fputs("\t\"", file);
593 if ((n = (unsigned char) *cp++) != 0) {
594 for (c = n; c > 0 && cp < cp2; c--) {
595 if (strchr("\n\"\\", *cp))
596 (void) putc('\\', file);
597 (void) putc(*cp++, file);
598 }
599 }
600 putc('"', file);
601 break;
602
603 case T_TXT:
604 (void) putc('\t', file);
605 cp2 = cp1 + dlen;
606 while (cp < cp2) {
607 putc('"', file);
608 if ((n = (unsigned char) *cp++)) {
609 for (c = n; c > 0 && cp < cp2; c--) {
610 if (strchr("\n\"\\", *cp))
611 (void) putc('\\', file);
612 (void) putc(*cp++, file);
613 }
614 }
615 putc('"', file);
616 if (cp < cp2)
617 putc(' ', file);
618 }
619 break;
620
621 case T_NSAP:
622 (void) fprintf(file, "\t%s", inet_nsap_ntoa(dlen, cp, NULL));
623 cp += dlen;
624 break;
625
626 case T_AAAA: {
627 char t[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"];
628
629 fprintf(file, "\t%s", inet_ntop(AF_INET6, cp, t, sizeof t));
630 cp += dlen;
631 break;
632 }
633
634 case T_LOC: {
635 char t[255];
636
637 fprintf(file, "\t%s", loc_ntoal(cp, t, sizeof t));
638 cp += dlen;
639 break;
640 }
641
642 case T_NAPTR: {
643 u_int order, preference;
644
645 order = _getshort(cp); cp += INT16SZ;
646 preference = _getshort(cp); cp += INT16SZ;
647 fprintf(file, "\t%u %u ",order, preference);
648 /* Flags */
649 n = *cp++;
650 fprintf(file,"\"%.*s\" ", (int)n, cp);
651 cp += n;
652 /* Service */
653 n = *cp++;
654 fprintf(file,"\"%.*s\" ", (int)n, cp);
655 cp += n;
656 /* Regexp */
657 n = *cp++;
658 fprintf(file,"\"%.*s\" ", (int)n, cp);
659 cp += n;
660 if ((cp = p_fqname(cp, msg, file)) == NULL)
661 return (NULL);
662 break;
663 }
664
665 case T_SRV: {
666 u_int priority, weight, port;
667
668 priority = _getshort(cp); cp += INT16SZ;
669 weight = _getshort(cp); cp += INT16SZ;
670 port = _getshort(cp); cp += INT16SZ;
671 fprintf(file, "\t%u %u %u ", priority, weight, port);
672 if ((cp = p_fqname(cp, msg, file)) == NULL)
673 return (NULL);
674 break;
675 }
676
677 case T_MINFO:
678 case T_RP:
679 putc('\t', file);
680 if ((cp = p_fqname(cp, msg, file)) == NULL)
681 return (NULL);
682 putc(' ', file);
683 if ((cp = p_fqname(cp, msg, file)) == NULL)
684 return (NULL);
685 break;
686
687 case T_UINFO:
688 putc('\t', file);
689 fputs((char *)cp, file);
690 cp += dlen;
691 break;
692
693 case T_UID:
694 case T_GID:
695 if (dlen == 4) {
696 fprintf(file, "\t%u", _getlong((u_char*)cp));
697 cp += INT32SZ;
698 }
699 break;
700
701 case T_WKS:
702 if (dlen < INT32SZ + 1)
703 break;
704 bcopy(cp, (char *)&inaddr, INADDRSZ);
705 cp += INT32SZ;
706 fprintf(file, "\t%s %s ( ",
707 inet_ntoa(inaddr),
708 deproto((int) *cp));
709 cp += sizeof (u_char);
710 n = 0;
711 lcnt = 0;
712 while (cp < cp1 + dlen) {
713 c = *cp++;
714 do {
715 if (c & 0200) {
716 if (lcnt == 0) {
717 fputs("\n\t\t\t", file);
718 lcnt = 5;
719 }
720 fputs(dewks(n), file);
721 putc(' ', file);
722 lcnt--;
723 }
724 c <<= 1;
725 } while (++n & 07);
726 }
727 putc(')', file);
728 break;
729
730 case T_KEY:
731 putc('\t', file);
732 keyflags = _getshort(cp);
733 cp += 2;
734 fprintf(file,"0x%04x", keyflags ); /* flags */
735 fprintf(file," %u", *cp++); /* protocol */
736 fprintf(file," %u (", *cp++); /* algorithm */
737
738 n = b64_ntop(cp, (cp1 + dlen) - cp,
739 base64_key, sizeof base64_key);
740 for (c = 0; c < n; ++c) {
741 if (0 == (c & 0x3F))
742 fprintf(file, "\n\t");
743 putc(base64_key[c], file); /* public key data */
744 }
745
746 fprintf(file, " )");
747 if (n < 0)
748 fprintf(file, "\t; BAD BASE64");
749 fflush(file);
750 cp = cp1 + dlen;
751 break;
752
753 case T_SIG:
754 type = _getshort((u_char*)cp);
755 cp += INT16SZ;
756 fprintf(file, " %s", p_type(type));
757 fprintf(file, "\t%u", *cp++); /* algorithm */
758 /* Check label value and print error if wrong. */
759 n = *cp++;
760 c = dn_count_labels (rrname);
761 if (n != c)
762 fprintf(file, "\t; LABELS WRONG (%d should be %d)\n\t",
763 n, c);
764 /* orig ttl */
765 n = _getlong((u_char*)cp);
766 if (n != tmpttl)
767 fprintf(file, " %u", n);
768 cp += INT32SZ;
769 /* sig expire */
770 fprintf(file, " (\n\t%s",
771 __p_secstodate(_getlong((u_char*)cp)));
772 cp += INT32SZ;
773 /* time signed */
774 fprintf(file, " %s", __p_secstodate(_getlong((u_char*)cp)));
775 cp += INT32SZ;
776 /* sig footprint */
777 fprintf(file," %u ", _getshort((u_char*)cp));
778 cp += INT16SZ;
779 /* signer's name */
780 cp = p_fqname(cp, msg, file);
781 n = b64_ntop(cp, (cp1 + dlen) - cp,
782 base64_key, sizeof base64_key);
783 for (c = 0; c < n; c++) {
784 if (0 == (c & 0x3F))
785 fprintf (file, "\n\t");
786 putc(base64_key[c], file); /* signature */
787 }
788 /* Clean up... */
789 fprintf(file, " )");
790 if (n < 0)
791 fprintf(file, "\t; BAD BASE64");
792 fflush(file);
793 cp = cp1+dlen;
794 break;
795
796#ifdef ALLOW_T_UNSPEC
797 case T_UNSPEC:
798 {
799 int NumBytes = 8;
800 u_char *DataPtr;
801 int i;
802
803 if (dlen < NumBytes) NumBytes = dlen;
804 fprintf(file, "\tFirst %d bytes of hex data:",
805 NumBytes);
806 for (i = 0, DataPtr = cp; i < NumBytes; i++, DataPtr++)
807 fprintf(file, " %x", *DataPtr);
808 cp += dlen;
809 }
810 break;
811#endif /* ALLOW_T_UNSPEC */
812
813 default:
814 fprintf(file, "\t?%d?", type);
815 cp += dlen;
816 }
817#if 0
818 fprintf(file, "\t; dlen=%d, ttl %s\n", dlen, __p_time(tmpttl));
819#else
820 putc('\n', file);
821#endif
822 if (cp - cp1 != dlen) {
823 fprintf(file, ";; packet size error (found %ld, dlen was %d)\n",
824 (long)(cp - cp1), dlen);
825 cp = NULL;
826 }
827 return (cp);
828}
829
830int
831__sym_ston(const struct res_sym *syms, char *name, int *success)
832{
833 for (; syms->name != 0; syms++) {
834 if (strcasecmp (name, syms->name) == 0) {
835 if (success)
836 *success = 1;
837 return (syms->number);
838 }
839 }
840 if (success)
841 *success = 0;
842 return (syms->number); /* The default value. */
843}
844
845
846const char *
847__sym_ntop(const struct res_sym *syms, int number, int *success)
848{
849 static char unname[20];
850
851 for (; syms->name != 0; syms++) {
852 if (number == syms->number) {
853 if (success)
854 *success = 1;
855 return (syms->humanname);
856 }
857 }
858 snprintf(unname, sizeof unname, "%d", number);
859 if (success)
860 *success = 0;
861 return (unname);
862}
863
864/*
865 * Return a mnemonic for an option
866 */
867const char *
868__p_option(u_long option)
869{
870 static char nbuf[40];
871
872 switch (option) {
873 case RES_INIT: return "init";
874 case RES_DEBUG: return "debug";
875 case RES_AAONLY: return "aaonly(unimpl)";
876 case RES_USEVC: return "usevc";
877 case RES_PRIMARY: return "primry(unimpl)";
878 case RES_IGNTC: return "igntc";
879 case RES_RECURSE: return "recurs";
880 case RES_DEFNAMES: return "defnam";
881 case RES_STAYOPEN: return "styopn";
882 case RES_DNSRCH: return "dnsrch";
883 case RES_INSECURE1: return "insecure1";
884 case RES_INSECURE2: return "insecure2";
885 case RES_USE_INET6: return "inet6";
886 case RES_USE_EDNS0: return "edns0";
887 default:
888 snprintf(nbuf, sizeof nbuf, "?0x%lx?", (u_long)option);
889 return (nbuf);
890 }
891}
892
893/*
894 * Return a mnemonic for a time to live
895 */
896const char *
897p_time(u_int32_t value)
898{
899 static char nbuf[40];
900 char *ebuf;
901 int secs, mins, hours, days;
902 char *p;
903 int tmp;
904
905 if (value == 0) {
906 strlcpy(nbuf, "0 secs", sizeof nbuf);
907 return (nbuf);
908 }
909
910 secs = value % 60;
911 value /= 60;
912 mins = value % 60;
913 value /= 60;
914 hours = value % 24;
915 value /= 24;
916 days = value;
917 value = 0;
918
919#define PLURALIZE(x) x, (x == 1) ? "" : "s"
920 p = nbuf;
921 ebuf = nbuf + sizeof(nbuf);
922 if (days) {
923 if ((tmp = snprintf(p, ebuf - p, "%d day%s",
924 PLURALIZE(days))) >= ebuf - p || tmp < 0)
925 goto full;
926 p += tmp;
927 }
928 if (hours) {
929 if (days)
930 *p++ = ' ';
931 if (p >= ebuf)
932 goto full;
933 if ((tmp = snprintf(p, ebuf - p, "%d hour%s",
934 PLURALIZE(hours))) >= ebuf - p || tmp < 0)
935 goto full;
936 p += tmp;
937 }
938 if (mins) {
939 if (days || hours)
940 *p++ = ' ';
941 if (p >= ebuf)
942 goto full;
943 if ((tmp = snprintf(p, ebuf - p, "%d min%s",
944 PLURALIZE(mins))) >= ebuf - p || tmp < 0)
945 goto full;
946 p += tmp;
947 }
948 if (secs || ! (days || hours || mins)) {
949 if (days || hours || mins)
950 *p++ = ' ';
951 if (p >= ebuf)
952 goto full;
953 if ((tmp = snprintf(p, ebuf - p, "%d sec%s",
954 PLURALIZE(secs))) >= ebuf - p || tmp < 0)
955 goto full;
956 }
957 return (nbuf);
958full:
959 p = nbuf + sizeof(nbuf) - 4;
960 *p++ = '.';
961 *p++ = '.';
962 *p++ = '.';
963 *p++ = '\0';
964 return (nbuf);
965}
966
967/*
968 * routines to convert between on-the-wire RR format and zone file format.
969 * Does not contain conversion to/from decimal degrees; divide or multiply
970 * by 60*60*1000 for that.
971 */
972
973static unsigned int poweroften[10] = {1, 10, 100, 1000, 10000, 100000,
974 1000000,10000000,100000000,1000000000};
975
976/* takes an XeY precision/size value, returns a string representation. */
977static const char *
978precsize_ntoa(u_int8_t prec)
979{
980 static char retbuf[sizeof "90000000.00"];
981 unsigned long val;
982 int mantissa, exponent;
983
984 mantissa = (int)((prec >> 4) & 0x0f) % 10;
985 exponent = (int)((prec >> 0) & 0x0f) % 10;
986
987 val = mantissa * poweroften[exponent];
988
989 (void) snprintf(retbuf, sizeof retbuf, "%ld.%.2ld", val/100, val%100);
990 return (retbuf);
991}
992
993/* converts ascii size/precision X * 10**Y(cm) to 0xXY. moves pointer. */
994static u_int8_t
995precsize_aton(char **strptr)
996{
997 unsigned int mval = 0, cmval = 0;
998 u_int8_t retval = 0;
999 char *cp;
1000 int exponent;
1001 int mantissa;
1002
1003 cp = *strptr;
1004
1005 while (isdigit(*cp))
1006 mval = mval * 10 + (*cp++ - '0');
1007
1008 if (*cp == '.') { /* centimeters */
1009 cp++;
1010 if (isdigit(*cp)) {
1011 cmval = (*cp++ - '0') * 10;
1012 if (isdigit(*cp)) {
1013 cmval += (*cp++ - '0');
1014 }
1015 }
1016 }
1017 cmval = (mval * 100) + cmval;
1018
1019 for (exponent = 0; exponent < 9; exponent++)
1020 if (cmval < poweroften[exponent+1])
1021 break;
1022
1023 mantissa = cmval / poweroften[exponent];
1024 if (mantissa > 9)
1025 mantissa = 9;
1026
1027 retval = (mantissa << 4) | exponent;
1028
1029 *strptr = cp;
1030
1031 return (retval);
1032}
1033
1034/* converts ascii lat/lon to unsigned encoded 32-bit number. moves pointer. */
1035static u_int32_t
1036latlon2ul(char **latlonstrptr, int *which)
1037{
1038 char *cp;
1039 u_int32_t retval;
1040 int deg = 0, min = 0, secs = 0, secsfrac = 0;
1041
1042 cp = *latlonstrptr;
1043
1044 while (isdigit(*cp))
1045 deg = deg * 10 + (*cp++ - '0');
1046
1047 while (isspace(*cp))
1048 cp++;
1049
1050 if (!(isdigit(*cp)))
1051 goto fndhemi;
1052
1053 while (isdigit(*cp))
1054 min = min * 10 + (*cp++ - '0');
1055
1056 while (isspace(*cp))
1057 cp++;
1058
1059 if (!(isdigit(*cp)))
1060 goto fndhemi;
1061
1062 while (isdigit(*cp))
1063 secs = secs * 10 + (*cp++ - '0');
1064
1065 if (*cp == '.') { /* decimal seconds */
1066 cp++;
1067 if (isdigit(*cp)) {
1068 secsfrac = (*cp++ - '0') * 100;
1069 if (isdigit(*cp)) {
1070 secsfrac += (*cp++ - '0') * 10;
1071 if (isdigit(*cp)) {
1072 secsfrac += (*cp++ - '0');
1073 }
1074 }
1075 }
1076 }
1077
1078 while (!isspace(*cp)) /* if any trailing garbage */
1079 cp++;
1080
1081 while (isspace(*cp))
1082 cp++;
1083
1084 fndhemi:
1085 switch (*cp) {
1086 case 'N': case 'n':
1087 case 'E': case 'e':
1088 retval = ((unsigned)1<<31)
1089 + (((((deg * 60) + min) * 60) + secs) * 1000)
1090 + secsfrac;
1091 break;
1092 case 'S': case 's':
1093 case 'W': case 'w':
1094 retval = ((unsigned)1<<31)
1095 - (((((deg * 60) + min) * 60) + secs) * 1000)
1096 - secsfrac;
1097 break;
1098 default:
1099 retval = 0; /* invalid value -- indicates error */
1100 break;
1101 }
1102
1103 switch (*cp) {
1104 case 'N': case 'n':
1105 case 'S': case 's':
1106 *which = 1; /* latitude */
1107 break;
1108 case 'E': case 'e':
1109 case 'W': case 'w':
1110 *which = 2; /* longitude */
1111 break;
1112 default:
1113 *which = 0; /* error */
1114 break;
1115 }
1116
1117 cp++; /* skip the hemisphere */
1118
1119 while (!isspace(*cp)) /* if any trailing garbage */
1120 cp++;
1121
1122 while (isspace(*cp)) /* move to next field */
1123 cp++;
1124
1125 *latlonstrptr = cp;
1126
1127 return (retval);
1128}
1129
1130/* converts a zone file representation in a string to an RDATA on-the-wire
1131 * representation. */
1132int
1133loc_aton(const char *ascii, u_char *binary)
1134{
1135 const char *maxcp;
1136 u_char *bcp;
1137 char *cp;
1138
1139 u_int32_t latit = 0, longit = 0, alt = 0;
1140 u_int32_t lltemp1 = 0, lltemp2 = 0;
1141 int altmeters = 0, altfrac = 0, altsign = 1;
1142 u_int8_t hp = 0x16; /* default = 1e6 cm = 10000.00m = 10km */
1143 u_int8_t vp = 0x13; /* default = 1e3 cm = 10.00m */
1144 u_int8_t siz = 0x12; /* default = 1e2 cm = 1.00m */
1145 int which1 = 0, which2 = 0;
1146
1147 cp = (char *)ascii;
1148 maxcp = cp + strlen(ascii);
1149
1150 lltemp1 = latlon2ul(&cp, &which1);
1151
1152 lltemp2 = latlon2ul(&cp, &which2);
1153
1154 switch (which1 + which2) {
1155 case 3: /* 1 + 2, the only valid combination */
1156 if ((which1 == 1) && (which2 == 2)) { /* normal case */
1157 latit = lltemp1;
1158 longit = lltemp2;
1159 } else if ((which1 == 2) && (which2 == 1)) { /* reversed */
1160 longit = lltemp1;
1161 latit = lltemp2;
1162 } else { /* some kind of brokenness */
1163 return (0);
1164 }
1165 break;
1166 default: /* we didn't get one of each */
1167 return (0);
1168 }
1169
1170 /* altitude */
1171 if (*cp == '-') {
1172 altsign = -1;
1173 cp++;
1174 }
1175
1176 if (*cp == '+')
1177 cp++;
1178
1179 while (isdigit(*cp))
1180 altmeters = altmeters * 10 + (*cp++ - '0');
1181
1182 if (*cp == '.') { /* decimal meters */
1183 cp++;
1184 if (isdigit(*cp)) {
1185 altfrac = (*cp++ - '0') * 10;
1186 if (isdigit(*cp)) {
1187 altfrac += (*cp++ - '0');
1188 }
1189 }
1190 }
1191
1192 alt = (10000000 + (altsign * (altmeters * 100 + altfrac)));
1193
1194 while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
1195 cp++;
1196
1197 while (isspace(*cp) && (cp < maxcp))
1198 cp++;
1199
1200 if (cp >= maxcp)
1201 goto defaults;
1202
1203 siz = precsize_aton(&cp);
1204
1205 while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
1206 cp++;
1207
1208 while (isspace(*cp) && (cp < maxcp))
1209 cp++;
1210
1211 if (cp >= maxcp)
1212 goto defaults;
1213
1214 hp = precsize_aton(&cp);
1215
1216 while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
1217 cp++;
1218
1219 while (isspace(*cp) && (cp < maxcp))
1220 cp++;
1221
1222 if (cp >= maxcp)
1223 goto defaults;
1224
1225 vp = precsize_aton(&cp);
1226
1227 defaults:
1228
1229 bcp = binary;
1230 *bcp++ = (u_int8_t) 0; /* version byte */
1231 *bcp++ = siz;
1232 *bcp++ = hp;
1233 *bcp++ = vp;
1234 PUTLONG(latit,bcp);
1235 PUTLONG(longit,bcp);
1236 PUTLONG(alt,bcp);
1237
1238 return (16); /* size of RR in octets */
1239}
1240
1241const char *
1242loc_ntoa(const u_char *binary, char *ascii)
1243{
1244 return loc_ntoal(binary, ascii, 255);
1245}
1246
1247/* takes an on-the-wire LOC RR and formats it in a human readable format. */
1248static const char *
1249loc_ntoal(const u_char *binary, char *ascii, int ascii_len)
1250{
1251 static char *error = "?";
1252 const u_char *cp = binary;
1253
1254 int latdeg, latmin, latsec, latsecfrac;
1255 int longdeg, longmin, longsec, longsecfrac;
1256 char northsouth, eastwest;
1257 int altmeters, altfrac, altsign;
1258
1259 const int referencealt = 100000 * 100;
1260
1261 int32_t latval, longval, altval;
1262 u_int32_t templ;
1263 u_int8_t sizeval, hpval, vpval, versionval;
1264
1265 char *sizestr, *hpstr, *vpstr;
1266
1267 versionval = *cp++;
1268
1269 if (versionval) {
1270 snprintf(ascii, ascii_len, "; error: unknown LOC RR version");
1271 return (ascii);
1272 }
1273
1274 sizeval = *cp++;
1275
1276 hpval = *cp++;
1277 vpval = *cp++;
1278
1279 GETLONG(templ, cp);
1280 latval = (templ - ((unsigned)1<<31));
1281
1282 GETLONG(templ, cp);
1283 longval = (templ - ((unsigned)1<<31));
1284
1285 GETLONG(templ, cp);
1286 if (templ < referencealt) { /* below WGS 84 spheroid */
1287 altval = referencealt - templ;
1288 altsign = -1;
1289 } else {
1290 altval = templ - referencealt;
1291 altsign = 1;
1292 }
1293
1294 if (latval < 0) {
1295 northsouth = 'S';
1296 latval = -latval;
1297 } else
1298 northsouth = 'N';
1299
1300 latsecfrac = latval % 1000;
1301 latval = latval / 1000;
1302 latsec = latval % 60;
1303 latval = latval / 60;
1304 latmin = latval % 60;
1305 latval = latval / 60;
1306 latdeg = latval;
1307
1308 if (longval < 0) {
1309 eastwest = 'W';
1310 longval = -longval;
1311 } else
1312 eastwest = 'E';
1313
1314 longsecfrac = longval % 1000;
1315 longval = longval / 1000;
1316 longsec = longval % 60;
1317 longval = longval / 60;
1318 longmin = longval % 60;
1319 longval = longval / 60;
1320 longdeg = longval;
1321
1322 altfrac = altval % 100;
1323 altmeters = (altval / 100) * altsign;
1324
1325 if ((sizestr = strdup(precsize_ntoa(sizeval))) == NULL)
1326 sizestr = error;
1327 if ((hpstr = strdup(precsize_ntoa(hpval))) == NULL)
1328 hpstr = error;
1329 if ((vpstr = strdup(precsize_ntoa(vpval))) == NULL)
1330 vpstr = error;
1331
1332 snprintf(ascii, ascii_len,
1333 "%d %.2d %.2d.%.3d %c %d %.2d %.2d.%.3d %c %d.%.2dm %sm %sm %sm",
1334 latdeg, latmin, latsec, latsecfrac, northsouth,
1335 longdeg, longmin, longsec, longsecfrac, eastwest,
1336 altmeters, altfrac, sizestr, hpstr, vpstr);
1337
1338 if (sizestr != error)
1339 free(sizestr);
1340 if (hpstr != error)
1341 free(hpstr);
1342 if (vpstr != error)
1343 free(vpstr);
1344
1345 return (ascii);
1346}
1347
1348
1349/* Return the number of DNS hierarchy levels in the name. */
1350int
1351__dn_count_labels(char *name)
1352{
1353 int i, len, count;
1354
1355 len = strlen(name);
1356
1357 for(i = 0, count = 0; i < len; i++) {
1358 if (name[i] == '.')
1359 count++;
1360 }
1361
1362 /* don't count initial wildcard */
1363 if (name[0] == '*')
1364 if (count)
1365 count--;
1366
1367 /* don't count the null label for root. */
1368 /* if terminating '.' not found, must adjust */
1369 /* count to include last label */
1370 if (len > 0 && name[len-1] != '.')
1371 count++;
1372 return (count);
1373}
1374
1375
1376/*
1377 * Make dates expressed in seconds-since-Jan-1-1970 easy to read.
1378 * SIG records are required to be printed like this, by the Secure DNS RFC.
1379 */
1380char *
1381__p_secstodate (long unsigned int secs)
1382{
1383 static char output[15]; /* YYYYMMDDHHMMSS and null */
1384 time_t clock = secs;
1385 struct tm *time;
1386
1387 time = gmtime(&clock);
1388 time->tm_year += 1900;
1389 time->tm_mon += 1;
1390 snprintf(output, sizeof output, "%04d%02d%02d%02d%02d%02d",
1391 time->tm_year, time->tm_mon, time->tm_mday,
1392 time->tm_hour, time->tm_min, time->tm_sec);
1393 return (output);
1394}
diff --git a/src/lib/libc/net/res_debug_syms.c b/src/lib/libc/net/res_debug_syms.c
new file mode 100644
index 0000000000..7e7d22c914
--- /dev/null
+++ b/src/lib/libc/net/res_debug_syms.c
@@ -0,0 +1,189 @@
1/* $OpenBSD: res_debug_syms.c,v 1.1 2005/08/06 20:30:04 espie 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
77#include <sys/types.h>
78#include <netinet/in.h>
79#include <arpa/nameser.h>
80
81#include <resolv.h>
82#include <stdio.h>
83
84/*
85 * Names of RR classes and qclasses. Classes and qclasses are the same, except
86 * that C_ANY is a qclass but not a class. (You can ask for records of class
87 * C_ANY, but you can't have any records of that class in the database.)
88 */
89const struct res_sym __p_class_syms[] = {
90 {C_IN, "IN"},
91 {C_CHAOS, "CHAOS"},
92 {C_HS, "HS"},
93 {C_HS, "HESIOD"},
94 {C_ANY, "ANY"},
95 {C_IN, (char *)0}
96};
97
98/*
99 * Names of RR types and qtypes. Types and qtypes are the same, except
100 * that T_ANY is a qtype but not a type. (You can ask for records of type
101 * T_ANY, but you can't have any records of that type in the database.)
102 */
103const struct res_sym __p_type_syms[] = {
104 {T_A, "A", "address"},
105 {T_NS, "NS", "name server"},
106 {T_MD, "MD", "mail destination (deprecated)"},
107 {T_MF, "MF", "mail forwarder (deprecated)"},
108 {T_CNAME, "CNAME", "canonical name"},
109 {T_SOA, "SOA", "start of authority"},
110 {T_MB, "MB", "mailbox"},
111 {T_MG, "MG", "mail group member"},
112 {T_MR, "MR", "mail rename"},
113 {T_NULL, "NULL", "null"},
114 {T_WKS, "WKS", "well-known service (deprecated)"},
115 {T_PTR, "PTR", "domain name pointer"},
116 {T_HINFO, "HINFO", "host information"},
117 {T_MINFO, "MINFO", "mailbox information"},
118 {T_MX, "MX", "mail exchanger"},
119 {T_TXT, "TXT", "text"},
120 {T_RP, "RP", "responsible person"},
121 {T_AFSDB, "AFSDB", "DCE or AFS server"},
122 {T_X25, "X25", "X25 address"},
123 {T_ISDN, "ISDN", "ISDN address"},
124 {T_RT, "RT", "router"},
125 {T_NSAP, "NSAP", "nsap address"},
126 {T_NSAP_PTR, "NSAP_PTR", "domain name pointer"},
127 {T_SIG, "SIG", "signature"},
128 {T_KEY, "KEY", "key"},
129 {T_PX, "PX", "mapping information"},
130 {T_GPOS, "GPOS", "geographical position (withdrawn)"},
131 {T_AAAA, "AAAA", "IPv6 address"},
132 {T_LOC, "LOC", "location"},
133 {T_NXT, "NXT", "next valid name (unimplemented)"},
134 {T_EID, "EID", "endpoint identifier (unimplemented)"},
135 {T_NIMLOC, "NIMLOC", "NIMROD locator (unimplemented)"},
136 {T_SRV, "SRV", "server selection"},
137 {T_ATMA, "ATMA", "ATM address (unimplemented)"},
138 {T_IXFR, "IXFR", "incremental zone transfer"},
139 {T_AXFR, "AXFR", "zone transfer"},
140 {T_MAILB, "MAILB", "mailbox-related data (deprecated)"},
141 {T_MAILA, "MAILA", "mail agent (deprecated)"},
142 {T_UINFO, "UINFO", "user information (nonstandard)"},
143 {T_UID, "UID", "user ID (nonstandard)"},
144 {T_GID, "GID", "group ID (nonstandard)"},
145 {T_NAPTR, "NAPTR", "URN Naming Authority"},
146#ifdef ALLOW_T_UNSPEC
147 {T_UNSPEC, "UNSPEC", "unspecified data (nonstandard)"},
148#endif /* ALLOW_T_UNSPEC */
149 {T_ANY, "ANY", "\"any\""},
150 {0, NULL, NULL}
151};
152
153const char *
154__sym_ntos(const struct res_sym *syms, int number, int *success)
155{
156 static char unname[20];
157
158 for (; syms->name != 0; syms++) {
159 if (number == syms->number) {
160 if (success)
161 *success = 1;
162 return (syms->name);
163 }
164 }
165
166 snprintf(unname, sizeof unname, "%d", number);
167 if (success)
168 *success = 0;
169 return (unname);
170}
171
172/*
173 * Return a string for the type
174 */
175const char *
176__p_type(int type)
177{
178 return (__sym_ntos (__p_type_syms, type, (int *)0));
179}
180
181/*
182 * Return a mnemonic for class
183 */
184const char *
185__p_class(int class)
186{
187 return (__sym_ntos (__p_class_syms, class, (int *)0));
188}
189
diff --git a/src/lib/libc/net/res_init.c b/src/lib/libc/net/res_init.c
new file mode 100644
index 0000000000..43ee5ac6bb
--- /dev/null
+++ b/src/lib/libc/net/res_init.c
@@ -0,0 +1,666 @@
1/* $OpenBSD: res_init.c,v 1.34 2005/12/22 06:52:11 tedu 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#include <sys/types.h>
59#include <sys/param.h>
60#include <sys/socket.h>
61#include <sys/time.h>
62#include <sys/stat.h>
63#include <netinet/in.h>
64#include <arpa/inet.h>
65#include <arpa/nameser.h>
66
67#include <stdio.h>
68#include <ctype.h>
69#include <resolv.h>
70#include <unistd.h>
71#include <stdlib.h>
72#include <string.h>
73#ifdef INET6
74#include <netdb.h>
75#endif /* INET6 */
76
77#include "thread_private.h"
78
79/*-------------------------------------- info about "sortlist" --------------
80 * Marc Majka 1994/04/16
81 * Allan Nathanson 1994/10/29 (BIND 4.9.3.x)
82 *
83 * NetInfo resolver configuration directory support.
84 *
85 * Allow a NetInfo directory to be created in the hierarchy which
86 * contains the same information as the resolver configuration file.
87 *
88 * - The local domain name is stored as the value of the "domain" property.
89 * - The Internet address(es) of the name server(s) are stored as values
90 * of the "nameserver" property.
91 * - The name server addresses are stored as values of the "nameserver"
92 * property.
93 * - The search list for host-name lookup is stored as values of the
94 * "search" property.
95 * - The sortlist comprised of IP address netmask pairs are stored as
96 * values of the "sortlist" property. The IP address and optional netmask
97 * should be separated by a slash (/) or ampersand (&) character.
98 * - Internal resolver variables can be set from the value of the "options"
99 * property.
100 */
101
102static void res_setoptions(char *, char *);
103
104#ifdef RESOLVSORT
105static const char sort_mask[] = "/&";
106#define ISSORTMASK(ch) (strchr(sort_mask, ch) != NULL)
107static u_int32_t net_mask(struct in_addr);
108#endif
109
110/*
111 * Resolver state default settings.
112 */
113void *__THREAD_NAME(_res);
114
115struct __res_state _res
116# if defined(__BIND_RES_TEXT)
117 = { RES_TIMEOUT, } /* Motorola, et al. */
118# endif
119 ;
120#ifdef INET6
121void *__THREAD_NAME(_res_ext);
122
123struct __res_state_ext _res_ext;
124#endif /* INET6 */
125
126int __res_chktime = 30;
127
128/*
129 * Set up default settings. If the configuration file exist, the values
130 * there will have precedence. Otherwise, the server address is set to
131 * INADDR_ANY and the default domain name comes from the gethostname().
132 *
133 * An interrim version of this code (BIND 4.9, pre-4.4BSD) used 127.0.0.1
134 * rather than INADDR_ANY ("0.0.0.0") as the default name server address
135 * since it was noted that INADDR_ANY actually meant ``the first interface
136 * you "ifconfig"'d at boot time'' and if this was a SLIP or PPP interface,
137 * it had to be "up" in order for you to reach your own name server. It
138 * was later decided that since the recommended practice is to always
139 * install local static routes through 127.0.0.1 for all your network
140 * interfaces, that we could solve this problem without a code change.
141 *
142 * The configuration file should always be used, since it is the only way
143 * to specify a default domain. If you are running a server on your local
144 * machine, you should say "nameserver 0.0.0.0" or "nameserver 127.0.0.1"
145 * in the configuration file.
146 *
147 * Return 0 if completes successfully, -1 on error
148 */
149int
150res_init(void)
151{
152
153 return (_res_init(1));
154}
155
156int
157_res_init(int usercall)
158{
159 struct stat sb;
160 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
161#ifdef INET6
162 struct __res_state_ext *_res_extp = _THREAD_PRIVATE(_res_ext, _res_ext,
163 &_res_ext);
164#endif
165 FILE *fp;
166 char *cp, **pp;
167 int n;
168 char buf[BUFSIZ];
169 int nserv = 0; /* number of nameserver records read from file */
170 int haveenv = 0;
171 int havesearch = 0;
172 size_t len;
173#ifdef RESOLVSORT
174 int nsort = 0;
175 char *net;
176#endif
177#ifndef RFC1535
178 int dots;
179#endif
180
181 if (!usercall && _resp->options & RES_INIT &&
182 _resp->reschktime >= time(NULL))
183 return (0);
184 _resp->reschktime = time(NULL) + __res_chktime;
185 if (stat(_PATH_RESCONF, &sb) != -1) {
186 if (!usercall && timespeccmp(&sb.st_mtimespec,
187 &_resp->restimespec, ==))
188 return (0);
189 else
190 _resp->restimespec = sb.st_mtimespec;
191 } else {
192 /*
193 * Lost the file, in chroot?
194 * Don't trash settings
195 */
196 if (!usercall && timespecisset(&_resp->restimespec))
197 return (0);
198 }
199
200
201 /*
202 * These three fields used to be statically initialized. This made
203 * it hard to use this code in a shared library. It is necessary,
204 * now that we're doing dynamic initialization here, that we preserve
205 * the old semantics: if an application modifies one of these three
206 * fields of _res before res_init() is called, res_init() will not
207 * alter them. Of course, if an application is setting them to
208 * _zero_ before calling res_init(), hoping to override what used
209 * to be the static default, we can't detect it and unexpected results
210 * will follow. Zero for any of these fields would make no sense,
211 * so one can safely assume that the applications were already getting
212 * unexpected results.
213 *
214 * _res.options is tricky since some apps were known to diddle the bits
215 * before res_init() was first called. We can't replicate that semantic
216 * with dynamic initialization (they may have turned bits off that are
217 * set in RES_DEFAULT). Our solution is to declare such applications
218 * "broken". They could fool us by setting RES_INIT but none do (yet).
219 */
220 if (!_resp->retrans)
221 _resp->retrans = RES_TIMEOUT;
222 if (!_resp->retry)
223 _resp->retry = 4;
224 if (!(_resp->options & RES_INIT))
225 _resp->options = RES_DEFAULT;
226
227#ifdef USELOOPBACK
228 _resp->nsaddr.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1);
229#else
230 _resp->nsaddr.sin_addr.s_addr = INADDR_ANY;
231#endif
232 _resp->nsaddr.sin_family = AF_INET;
233 _resp->nsaddr.sin_port = htons(NAMESERVER_PORT);
234 _resp->nsaddr.sin_len = sizeof(struct sockaddr_in);
235#ifdef INET6
236 if (sizeof(_res_extp->nsaddr) >= _resp->nsaddr.sin_len)
237 memcpy(&_res_extp->nsaddr, &_resp->nsaddr, _resp->nsaddr.sin_len);
238#endif
239 _resp->nscount = 1;
240 _resp->ndots = 1;
241 _resp->pfcode = 0;
242 strlcpy(_resp->lookups, "f", sizeof _resp->lookups);
243
244 /* Allow user to override the local domain definition */
245 if (issetugid() == 0 && (cp = getenv("LOCALDOMAIN")) != NULL) {
246 strlcpy(_resp->defdname, cp, sizeof(_resp->defdname));
247 haveenv++;
248
249 /*
250 * Set search list to be blank-separated strings
251 * from rest of env value. Permits users of LOCALDOMAIN
252 * to still have a search list, and anyone to set the
253 * one that they want to use as an individual (even more
254 * important now that the rfc1535 stuff restricts searches)
255 */
256 cp = _resp->defdname;
257 pp = _resp->dnsrch;
258 *pp++ = cp;
259 for (n = 0; *cp && pp < _resp->dnsrch + MAXDNSRCH; cp++) {
260 if (*cp == '\n') /* silly backwards compat */
261 break;
262 else if (*cp == ' ' || *cp == '\t') {
263 *cp = 0;
264 n = 1;
265 } else if (n) {
266 *pp++ = cp;
267 n = 0;
268 havesearch = 1;
269 }
270 }
271 /* null terminate last domain if there are excess */
272 while (*cp != '\0' && *cp != ' ' && *cp != '\t' && *cp != '\n')
273 cp++;
274 *cp = '\0';
275 *pp++ = 0;
276 }
277
278#define MATCH(line, name) \
279 (!strncmp(line, name, sizeof(name) - 1) && \
280 (line[sizeof(name) - 1] == ' ' || \
281 line[sizeof(name) - 1] == '\t'))
282
283 if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) {
284 strlcpy(_resp->lookups, "bf", sizeof _resp->lookups);
285
286 /* read the config file */
287 buf[0] = '\0';
288 while ((cp = fgetln(fp, &len)) != NULL) {
289 /* skip lines that are too long or zero length */
290 if (len >= sizeof(buf) || len == 0)
291 continue;
292 (void)memcpy(buf, cp, len);
293 buf[len] = '\0';
294 /* skip comments */
295 if ((cp = strpbrk(buf, ";#")) != NULL)
296 *cp = '\0';
297 if (buf[0] == '\0')
298 continue;
299 /* read default domain name */
300 if (MATCH(buf, "domain")) {
301 if (haveenv) /* skip if have from environ */
302 continue;
303 cp = buf + sizeof("domain") - 1;
304 while (*cp == ' ' || *cp == '\t')
305 cp++;
306 if ((*cp == '\0') || (*cp == '\n'))
307 continue;
308 strlcpy(_resp->defdname, cp, sizeof(_resp->defdname));
309 if ((cp = strpbrk(_resp->defdname, " \t\n")) != NULL)
310 *cp = '\0';
311 havesearch = 0;
312 continue;
313 }
314 /* lookup types */
315 if (MATCH(buf, "lookup")) {
316 char *sp = NULL;
317
318 bzero(_resp->lookups, sizeof _resp->lookups);
319 cp = buf + sizeof("lookup") - 1;
320 for (n = 0;; cp++) {
321 if (n == MAXDNSLUS)
322 break;
323 if ((*cp == '\0') || (*cp == '\n')) {
324 if (sp) {
325 if (*sp=='y' || *sp=='b' || *sp=='f')
326 _resp->lookups[n++] = *sp;
327 sp = NULL;
328 }
329 break;
330 } else if ((*cp == ' ') || (*cp == '\t') || (*cp == ',')) {
331 if (sp) {
332 if (*sp=='y' || *sp=='b' || *sp=='f')
333 _resp->lookups[n++] = *sp;
334 sp = NULL;
335 }
336 } else if (sp == NULL)
337 sp = cp;
338 }
339 continue;
340 }
341 /* set search list */
342 if (MATCH(buf, "search")) {
343 if (haveenv) /* skip if have from environ */
344 continue;
345 cp = buf + sizeof("search") - 1;
346 while (*cp == ' ' || *cp == '\t')
347 cp++;
348 if ((*cp == '\0') || (*cp == '\n'))
349 continue;
350 strlcpy(_resp->defdname, cp, sizeof(_resp->defdname));
351 if ((cp = strchr(_resp->defdname, '\n')) != NULL)
352 *cp = '\0';
353 /*
354 * Set search list to be blank-separated strings
355 * on rest of line.
356 */
357 cp = _resp->defdname;
358 pp = _resp->dnsrch;
359 *pp++ = cp;
360 for (n = 0; *cp && pp < _resp->dnsrch + MAXDNSRCH; cp++) {
361 if (*cp == ' ' || *cp == '\t') {
362 *cp = 0;
363 n = 1;
364 } else if (n) {
365 *pp++ = cp;
366 n = 0;
367 }
368 }
369 /* null terminate last domain if there are excess */
370 while (*cp != '\0' && *cp != ' ' && *cp != '\t')
371 cp++;
372 *cp = '\0';
373 *pp++ = 0;
374 havesearch = 1;
375 continue;
376 }
377 /* read nameservers to query */
378 if (MATCH(buf, "nameserver") && nserv < MAXNS) {
379#ifdef INET6
380 char *q;
381 struct addrinfo hints, *res;
382 char pbuf[NI_MAXSERV];
383#else
384 struct in_addr a;
385#endif /* INET6 */
386
387 cp = buf + sizeof("nameserver") - 1;
388 while (*cp == ' ' || *cp == '\t')
389 cp++;
390#ifdef INET6
391 if ((*cp == '\0') || (*cp == '\n'))
392 continue;
393 for (q = cp; *q; q++) {
394 if (isspace(*q)) {
395 *q = '\0';
396 break;
397 }
398 }
399 memset(&hints, 0, sizeof(hints));
400 hints.ai_flags = AI_NUMERICHOST;
401 hints.ai_socktype = SOCK_DGRAM;
402 snprintf(pbuf, sizeof(pbuf), "%u", NAMESERVER_PORT);
403 res = NULL;
404 if (getaddrinfo(cp, pbuf, &hints, &res) == 0 &&
405 res->ai_next == NULL) {
406 if (res->ai_addrlen <= sizeof(_res_extp->nsaddr_list[nserv])) {
407 memcpy(&_res_extp->nsaddr_list[nserv], res->ai_addr,
408 res->ai_addrlen);
409 } else {
410 memset(&_res_extp->nsaddr_list[nserv], 0,
411 sizeof(_res_extp->nsaddr_list[nserv]));
412 }
413 if (res->ai_addrlen <= sizeof(_resp->nsaddr_list[nserv])) {
414 memcpy(&_resp->nsaddr_list[nserv], res->ai_addr,
415 res->ai_addrlen);
416 } else {
417 memset(&_resp->nsaddr_list[nserv], 0,
418 sizeof(_resp->nsaddr_list[nserv]));
419 }
420 nserv++;
421 }
422 if (res)
423 freeaddrinfo(res);
424#else /* INET6 */
425 if ((*cp != '\0') && (*cp != '\n') && inet_aton(cp, &a)) {
426 _resp->nsaddr_list[nserv].sin_addr = a;
427 _resp->nsaddr_list[nserv].sin_family = AF_INET;
428 _resp->nsaddr_list[nserv].sin_port =
429 htons(NAMESERVER_PORT);
430 _resp->nsaddr_list[nserv].sin_len =
431 sizeof(struct sockaddr_in);
432 nserv++;
433 }
434#endif /* INET6 */
435 continue;
436 }
437#ifdef RESOLVSORT
438 if (MATCH(buf, "sortlist")) {
439 struct in_addr a;
440#ifdef INET6
441 struct in6_addr a6;
442 int m, i;
443 u_char *u;
444#endif /* INET6 */
445
446 cp = buf + sizeof("sortlist") - 1;
447 while (nsort < MAXRESOLVSORT) {
448 while (*cp == ' ' || *cp == '\t')
449 cp++;
450 if (*cp == '\0' || *cp == '\n' || *cp == ';')
451 break;
452 net = cp;
453 while (*cp && !ISSORTMASK(*cp) && *cp != ';' &&
454 isascii(*cp) && !isspace(*cp))
455 cp++;
456 n = *cp;
457 *cp = 0;
458 if (inet_aton(net, &a)) {
459 _resp->sort_list[nsort].addr = a;
460 if (ISSORTMASK(n)) {
461 *cp++ = n;
462 net = cp;
463 while (*cp && *cp != ';' &&
464 isascii(*cp) && !isspace(*cp))
465 cp++;
466 n = *cp;
467 *cp = 0;
468 if (inet_aton(net, &a)) {
469 _resp->sort_list[nsort].mask = a.s_addr;
470 } else {
471 _resp->sort_list[nsort].mask =
472 net_mask(_resp->sort_list[nsort].addr);
473 }
474 } else {
475 _resp->sort_list[nsort].mask =
476 net_mask(_resp->sort_list[nsort].addr);
477 }
478#ifdef INET6
479 _res_extp->sort_list[nsort].af = AF_INET;
480 _res_extp->sort_list[nsort].addr.ina =
481 _resp->sort_list[nsort].addr;
482 _res_extp->sort_list[nsort].mask.ina.s_addr =
483 _resp->sort_list[nsort].mask;
484#endif /* INET6 */
485 nsort++;
486 }
487#ifdef INET6
488 else if (inet_pton(AF_INET6, net, &a6) == 1) {
489 _res_extp->sort_list[nsort].af = AF_INET6;
490 _res_extp->sort_list[nsort].addr.in6a = a6;
491 u = (u_char *)&_res_extp->sort_list[nsort].mask.in6a;
492 *cp++ = n;
493 net = cp;
494 while (*cp && *cp != ';' &&
495 isascii(*cp) && !isspace(*cp))
496 cp++;
497 m = n;
498 n = *cp;
499 *cp = 0;
500 switch (m) {
501 case '/':
502 m = atoi(net);
503 break;
504 case '&':
505 if (inet_pton(AF_INET6, net, u) == 1) {
506 m = -1;
507 break;
508 }
509 /*FALLTHRU*/
510 default:
511 m = sizeof(struct in6_addr) * NBBY;
512 break;
513 }
514 if (m >= 0) {
515 for (i = 0; i < sizeof(struct in6_addr); i++) {
516 if (m <= 0) {
517 *u = 0;
518 } else {
519 m -= NBBY;
520 *u = (u_char)~0;
521 if (m < 0)
522 *u <<= -m;
523 }
524 u++;
525 }
526 }
527 nsort++;
528 }
529#endif /* INET6 */
530 *cp = n;
531 }
532 continue;
533 }
534#endif
535 if (MATCH(buf, "options")) {
536 res_setoptions(buf + sizeof("options") - 1, "conf");
537 continue;
538 }
539 }
540 if (nserv > 1)
541 _resp->nscount = nserv;
542#ifdef RESOLVSORT
543 _resp->nsort = nsort;
544#endif
545 (void) fclose(fp);
546 }
547 if (_resp->defdname[0] == 0 &&
548 gethostname(buf, sizeof(_resp->defdname) - 1) == 0 &&
549 (cp = strchr(buf, '.')) != NULL)
550 {
551 strlcpy(_resp->defdname, cp + 1,
552 sizeof(_resp->defdname));
553 }
554
555 /* find components of local domain that might be searched */
556 if (havesearch == 0) {
557 pp = _resp->dnsrch;
558 *pp++ = _resp->defdname;
559 *pp = NULL;
560
561#ifndef RFC1535
562 dots = 0;
563 for (cp = _resp->defdname; *cp; cp++)
564 dots += (*cp == '.');
565
566 cp = _resp->defdname;
567 while (pp < _resp->dnsrch + MAXDFLSRCH) {
568 if (dots < LOCALDOMAINPARTS)
569 break;
570 cp = strchr(cp, '.') + 1; /* we know there is one */
571 *pp++ = cp;
572 dots--;
573 }
574 *pp = NULL;
575#ifdef DEBUG
576 if (_resp->options & RES_DEBUG) {
577 printf(";; res_init()... default dnsrch list:\n");
578 for (pp = _resp->dnsrch; *pp; pp++)
579 printf(";;\t%s\n", *pp);
580 printf(";;\t..END..\n");
581 }
582#endif /* DEBUG */
583#endif /* !RFC1535 */
584 }
585
586 if (issetugid())
587 _resp->options |= RES_NOALIASES;
588 else if ((cp = getenv("RES_OPTIONS")) != NULL)
589 res_setoptions(cp, "env");
590 _resp->options |= RES_INIT;
591 return (0);
592}
593
594/* ARGSUSED */
595static void
596res_setoptions(char *options, char *source)
597{
598 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
599 char *cp = options;
600 char *endp;
601 long l;
602
603#ifdef DEBUG
604 if (_resp->options & RES_DEBUG)
605 printf(";; res_setoptions(\"%s\", \"%s\")...\n",
606 options, source);
607#endif
608 while (*cp) {
609 /* skip leading and inner runs of spaces */
610 while (*cp == ' ' || *cp == '\t')
611 cp++;
612 /* search for and process individual options */
613 if (!strncmp(cp, "ndots:", sizeof("ndots:") - 1)) {
614 char *p = cp + sizeof("ndots:") - 1;
615 l = strtol(p, &endp, 10);
616 if (l >= 0 && endp != p &&
617 (*endp = '\0' || isspace(*endp))) {
618 if (l <= RES_MAXNDOTS)
619 _resp->ndots = l;
620 else
621 _resp->ndots = RES_MAXNDOTS;
622#ifdef DEBUG
623 if (_resp->options & RES_DEBUG)
624 printf(";;\tndots=%u\n", _resp->ndots);
625#endif
626 }
627 } else if (!strncmp(cp, "debug", sizeof("debug") - 1)) {
628#ifdef DEBUG
629 if (!(_resp->options & RES_DEBUG)) {
630 printf(";; res_setoptions(\"%s\", \"%s\")..\n",
631 options, source);
632 _resp->options |= RES_DEBUG;
633 }
634 printf(";;\tdebug\n");
635#endif
636 } else if (!strncmp(cp, "inet6", sizeof("inet6") - 1)) {
637 _resp->options |= RES_USE_INET6;
638 } else if (!strncmp(cp, "insecure1", sizeof("insecure1") - 1)) {
639 _resp->options |= RES_INSECURE1;
640 } else if (!strncmp(cp, "insecure2", sizeof("insecure2") - 1)) {
641 _resp->options |= RES_INSECURE2;
642 } else if (!strncmp(cp, "edns0", sizeof("edns0") - 1)) {
643 _resp->options |= RES_USE_EDNS0;
644 } else {
645 /* XXX - print a warning here? */
646 }
647 /* skip to next run of spaces */
648 while (*cp && *cp != ' ' && *cp != '\t')
649 cp++;
650 }
651}
652
653#ifdef RESOLVSORT
654/* XXX - should really support CIDR which means explicit masks always. */
655static u_int32_t
656net_mask(struct in_addr in) /* XXX - should really use system's version of this */
657{
658 u_int32_t i = ntohl(in.s_addr);
659
660 if (IN_CLASSA(i))
661 return (htonl(IN_CLASSA_NET));
662 else if (IN_CLASSB(i))
663 return (htonl(IN_CLASSB_NET));
664 return (htonl(IN_CLASSC_NET));
665}
666#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..5c6b273abe
--- /dev/null
+++ b/src/lib/libc/net/res_mkquery.c
@@ -0,0 +1,232 @@
1/* $OpenBSD: res_mkquery.c,v 1.17 2005/08/06 20:30:04 espie 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#include <sys/types.h>
55#include <sys/param.h>
56#include <netinet/in.h>
57#include <arpa/nameser.h>
58
59#include <stdio.h>
60#include <netdb.h>
61#include <resolv.h>
62#include <string.h>
63
64#include "thread_private.h"
65
66/*
67 * Form all types of queries.
68 * Returns the size of the result or -1.
69 */
70/* ARGSUSED */
71int
72res_mkquery(int op,
73 const char *dname, /* opcode of query */
74 int class, /* domain name */
75 int type, /* class and type of query */
76 const u_char *data, /* resource record data */
77 int datalen, /* length of data */
78 const u_char *newrr_in, /* new rr for modify or append */
79 u_char *buf, /* buffer to put query */
80 int buflen) /* size of buffer */
81{
82 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
83 HEADER *hp;
84 u_char *cp, *ep;
85 int n;
86 u_char *dnptrs[20], **dpp, **lastdnptr;
87
88 if (_res_init(0) == -1) {
89 h_errno = NETDB_INTERNAL;
90 return (-1);
91 }
92#ifdef DEBUG
93 if (_resp->options & RES_DEBUG)
94 printf(";; res_mkquery(%d, %s, %d, %d)\n",
95 op, dname, class, type);
96#endif
97 /*
98 * Initialize header fields.
99 *
100 * A special random number generator is used to create non predictable
101 * and non repeating ids over a long period. It also avoids reuse
102 * by switching between two distinct number cycles.
103 */
104
105 if ((buf == NULL) || (buflen < HFIXEDSZ))
106 return (-1);
107 bzero(buf, HFIXEDSZ);
108 hp = (HEADER *) buf;
109 _resp->id = res_randomid();
110 hp->id = htons(_resp->id);
111 hp->opcode = op;
112 hp->rd = (_resp->options & RES_RECURSE) != 0;
113 hp->rcode = NOERROR;
114 cp = buf + HFIXEDSZ;
115 ep = buf + buflen;
116 dpp = dnptrs;
117 *dpp++ = buf;
118 *dpp++ = NULL;
119 lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0];
120 /*
121 * perform opcode specific processing
122 */
123 switch (op) {
124 case QUERY: /*FALLTHROUGH*/
125 case NS_NOTIFY_OP:
126 if (ep - cp < QFIXEDSZ)
127 return (-1);
128 if ((n = dn_comp(dname, cp, ep - cp - QFIXEDSZ, dnptrs,
129 lastdnptr)) < 0)
130 return (-1);
131 cp += n;
132 __putshort(type, cp);
133 cp += INT16SZ;
134 __putshort(class, cp);
135 cp += INT16SZ;
136 hp->qdcount = htons(1);
137 if (op == QUERY || data == NULL)
138 break;
139 /*
140 * Make an additional record for completion domain.
141 */
142 if (ep - cp < RRFIXEDSZ)
143 return (-1);
144 n = dn_comp((char *)data, cp, ep - cp - RRFIXEDSZ, dnptrs,
145 lastdnptr);
146 if (n < 0)
147 return (-1);
148 cp += n;
149 __putshort(T_NULL, cp);
150 cp += INT16SZ;
151 __putshort(class, cp);
152 cp += INT16SZ;
153 __putlong(0, cp);
154 cp += INT32SZ;
155 __putshort(0, cp);
156 cp += INT16SZ;
157 hp->arcount = htons(1);
158 break;
159
160 case IQUERY:
161 /*
162 * Initialize answer section
163 */
164 if (ep - cp < 1 + RRFIXEDSZ + datalen)
165 return (-1);
166 *cp++ = '\0'; /* no domain name */
167 __putshort(type, cp);
168 cp += INT16SZ;
169 __putshort(class, cp);
170 cp += INT16SZ;
171 __putlong(0, cp);
172 cp += INT32SZ;
173 __putshort(datalen, cp);
174 cp += INT16SZ;
175 if (datalen) {
176 bcopy(data, cp, datalen);
177 cp += datalen;
178 }
179 hp->ancount = htons(1);
180 break;
181
182 default:
183 return (-1);
184 }
185 return (cp - buf);
186}
187
188/* attach OPT pseudo-RR, as documented in RFC2671 (EDNS0). */
189int
190res_opt(int n0,
191 u_char *buf, /* buffer to put query */
192 int buflen, /* size of buffer */
193 int anslen) /* answer buffer length */
194{
195 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
196 HEADER *hp;
197 u_char *cp, *ep;
198
199 hp = (HEADER *) buf;
200 cp = buf + n0;
201 ep = buf + buflen;
202
203 if (ep - cp < 1 + RRFIXEDSZ)
204 return -1;
205
206 *cp++ = 0; /* "." */
207
208 __putshort(T_OPT, cp); /* TYPE */
209 cp += INT16SZ;
210 if (anslen > 0xffff)
211 anslen = 0xffff; /* limit to 16bit value */
212 __putshort(anslen & 0xffff, cp); /* CLASS = UDP payload size */
213 cp += INT16SZ;
214 *cp++ = NOERROR; /* extended RCODE */
215 *cp++ = 0; /* EDNS version */
216 if (_resp->options & RES_USE_DNSSEC) {
217#ifdef DEBUG
218 if (_resp->options & RES_DEBUG)
219 printf(";; res_opt()... ENDS0 DNSSEC OK\n");
220#endif /* DEBUG */
221 __putshort(DNS_MESSAGEEXTFLAG_DO, cp); /* EDNS Z field */
222 cp += INT16SZ;
223 } else {
224 __putshort(0, cp); /* EDNS Z field */
225 cp += INT16SZ;
226 }
227 __putshort(0, cp); /* RDLEN */
228 cp += INT16SZ;
229 hp->arcount = htons(ntohs(hp->arcount) + 1);
230
231 return cp - buf;
232}
diff --git a/src/lib/libc/net/res_query.c b/src/lib/libc/net/res_query.c
new file mode 100644
index 0000000000..32cd04306c
--- /dev/null
+++ b/src/lib/libc/net/res_query.c
@@ -0,0 +1,398 @@
1/* $OpenBSD: res_query.c,v 1.24 2005/08/06 20:30:04 espie 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#include <sys/types.h>
55#include <sys/param.h>
56#include <netinet/in.h>
57#include <arpa/inet.h>
58#include <arpa/nameser.h>
59
60#include <stdio.h>
61#include <netdb.h>
62#include <resolv.h>
63#include <ctype.h>
64#include <errno.h>
65#include <stdlib.h>
66#include <string.h>
67#include <unistd.h>
68
69#include "thread_private.h"
70
71#if PACKETSZ > 1024
72#define MAXPACKET PACKETSZ
73#else
74#define MAXPACKET 1024
75#endif
76
77const char *hostalias(const char *);
78int h_errno;
79extern int res_opt(int, u_char *, int, int);
80
81/*
82 * Formulate a normal query, send, and await answer.
83 * Returned answer is placed in supplied buffer "answer".
84 * Perform preliminary check of answer, returning success only
85 * if no error is indicated and the answer count is nonzero.
86 * Return the size of the response on success, -1 on error.
87 * Error number is left in h_errno.
88 *
89 * Caller must parse answer and determine whether it answers the question.
90 */
91int
92res_query(const char *name,
93 int class, /* domain name */
94 int type, /* class and type of query */
95 u_char *answer, /* buffer to put answer */
96 int anslen) /* size of answer buffer */
97{
98 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
99 u_char buf[MAXPACKET];
100 HEADER *hp = (HEADER *) answer;
101 int n;
102
103 hp->rcode = NOERROR; /* default */
104
105 if (_res_init(0) == -1) {
106 h_errno = NETDB_INTERNAL;
107 return (-1);
108 }
109#ifdef DEBUG
110 if (_resp->options & RES_DEBUG)
111 printf(";; res_query(%s, %d, %d)\n", name, class, type);
112#endif
113
114 n = res_mkquery(QUERY, name, class, type, NULL, 0, NULL,
115 buf, sizeof(buf));
116 if (n > 0 && ((_resp->options & RES_USE_EDNS0) ||
117 (_resp->options & RES_USE_DNSSEC))) {
118 n = res_opt(n, buf, sizeof(buf), anslen);
119 }
120
121 if (n <= 0) {
122#ifdef DEBUG
123 if (_resp->options & RES_DEBUG)
124 printf(";; res_query: mkquery failed\n");
125#endif
126 h_errno = NO_RECOVERY;
127 return (n);
128 }
129 n = res_send(buf, n, answer, anslen);
130 if (n < 0) {
131#ifdef DEBUG
132 if (_resp->options & RES_DEBUG)
133 printf(";; res_query: send error\n");
134#endif
135 h_errno = TRY_AGAIN;
136 return (n);
137 }
138
139 if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
140#ifdef DEBUG
141 if (_resp->options & RES_DEBUG)
142 printf(";; rcode = %u, ancount=%u\n", hp->rcode,
143 ntohs(hp->ancount));
144#endif
145 switch (hp->rcode) {
146 case NXDOMAIN:
147 h_errno = HOST_NOT_FOUND;
148 break;
149 case SERVFAIL:
150 h_errno = TRY_AGAIN;
151 break;
152 case NOERROR:
153 h_errno = NO_DATA;
154 break;
155 case FORMERR:
156 case NOTIMP:
157 case REFUSED:
158 default:
159 h_errno = NO_RECOVERY;
160 break;
161 }
162 return (-1);
163 }
164 return (n);
165}
166
167/*
168 * Formulate a normal query, send, and retrieve answer in supplied buffer.
169 * Return the size of the response on success, -1 on error.
170 * If enabled, implement search rules until answer or unrecoverable failure
171 * is detected. Error code, if any, is left in h_errno.
172 */
173int
174res_search(const char *name,
175 int class, /* domain name */
176 int type, /* class and type of query */
177 u_char *answer, /* buffer to put answer */
178 int anslen) /* size of answer */
179{
180 const char *cp, * const *domain;
181 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
182 HEADER *hp = (HEADER *) answer;
183 u_int dots;
184 int trailing_dot, ret, saved_herrno;
185 int got_nodata = 0, got_servfail = 0, tried_as_is = 0;
186
187 if (_res_init(0) == -1) {
188 h_errno = NETDB_INTERNAL;
189 return (-1);
190 }
191 errno = 0;
192 h_errno = HOST_NOT_FOUND; /* default, if we never query */
193 dots = 0;
194 for (cp = name; *cp; cp++)
195 dots += (*cp == '.');
196 trailing_dot = 0;
197 if (cp > name && *--cp == '.')
198 trailing_dot++;
199
200 /*
201 * if there aren't any dots, it could be a user-level alias
202 */
203 if (!dots && (cp = __hostalias(name)) != NULL)
204 return (res_query(cp, class, type, answer, anslen));
205
206 /*
207 * If there are dots in the name already, let's just give it a try
208 * 'as is'. The threshold can be set with the "ndots" option.
209 */
210 saved_herrno = -1;
211 if (dots >= _resp->ndots) {
212 ret = res_querydomain(name, NULL, class, type, answer, anslen);
213 if (ret > 0)
214 return (ret);
215 saved_herrno = h_errno;
216 tried_as_is++;
217 }
218
219 /*
220 * We do at least one level of search if
221 * - there is no dot and RES_DEFNAME is set, or
222 * - there is at least one dot, there is no trailing dot,
223 * and RES_DNSRCH is set.
224 */
225 if ((!dots && (_resp->options & RES_DEFNAMES)) ||
226 (dots && !trailing_dot && (_resp->options & RES_DNSRCH))) {
227 int done = 0;
228
229 for (domain = (const char * const *)_resp->dnsrch;
230 *domain && !done;
231 domain++) {
232
233 ret = res_querydomain(name, *domain, class, type,
234 answer, anslen);
235 if (ret > 0)
236 return (ret);
237
238 /*
239 * If no server present, give up.
240 * If name isn't found in this domain,
241 * keep trying higher domains in the search list
242 * (if that's enabled).
243 * On a NO_DATA error, keep trying, otherwise
244 * a wildcard entry of another type could keep us
245 * from finding this entry higher in the domain.
246 * If we get some other error (negative answer or
247 * server failure), then stop searching up,
248 * but try the input name below in case it's
249 * fully-qualified.
250 */
251 if (errno == ECONNREFUSED) {
252 h_errno = TRY_AGAIN;
253 return (-1);
254 }
255
256 switch (h_errno) {
257 case NO_DATA:
258 got_nodata++;
259 /* FALLTHROUGH */
260 case HOST_NOT_FOUND:
261 /* keep trying */
262 break;
263 case TRY_AGAIN:
264 if (hp->rcode == SERVFAIL) {
265 /* try next search element, if any */
266 got_servfail++;
267 break;
268 }
269 /* FALLTHROUGH */
270 default:
271 /* anything else implies that we're done */
272 done++;
273 }
274
275 /* if we got here for some reason other than DNSRCH,
276 * we only wanted one iteration of the loop, so stop.
277 */
278 if (!(_resp->options & RES_DNSRCH))
279 done++;
280 }
281 }
282
283 /* if we have not already tried the name "as is", do that now.
284 * note that we do this regardless of how many dots were in the
285 * name or whether it ends with a dot.
286 */
287 if (!tried_as_is) {
288 ret = res_querydomain(name, NULL, class, type, answer, anslen);
289 if (ret > 0)
290 return (ret);
291 }
292
293 /* if we got here, we didn't satisfy the search.
294 * if we did an initial full query, return that query's h_errno
295 * (note that we wouldn't be here if that query had succeeded).
296 * else if we ever got a nodata, send that back as the reason.
297 * else send back meaningless h_errno, that being the one from
298 * the last DNSRCH we did.
299 */
300 if (saved_herrno != -1)
301 h_errno = saved_herrno;
302 else if (got_nodata)
303 h_errno = NO_DATA;
304 else if (got_servfail)
305 h_errno = TRY_AGAIN;
306 return (-1);
307}
308
309/*
310 * Perform a call on res_query on the concatenation of name and domain,
311 * removing a trailing dot from name if domain is NULL.
312 */
313int
314res_querydomain(const char *name,
315 const char *domain,
316 int class, /* class and type of query */
317 int type,
318 u_char *answer, /* buffer to put answer */
319 int anslen) /* size of answer */
320{
321 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
322 char nbuf[MAXDNAME*2+1+1];
323 const char *longname = nbuf;
324 int n;
325
326 if (_res_init(0) == -1) {
327 h_errno = NETDB_INTERNAL;
328 return (-1);
329 }
330#ifdef DEBUG
331 if (_resp->options & RES_DEBUG)
332 printf(";; res_querydomain(%s, %s, %d, %d)\n",
333 name, domain?domain:"<Nil>", class, type);
334#endif
335 if (domain == NULL) {
336 /*
337 * Check for trailing '.';
338 * copy without '.' if present.
339 */
340 n = strlen(name) - 1;
341 if (n != (0 - 1) && name[n] == '.' && n < sizeof(nbuf) - 1) {
342 bcopy(name, nbuf, n);
343 nbuf[n] = '\0';
344 } else
345 longname = name;
346 } else
347 snprintf(nbuf, sizeof nbuf, "%.*s.%.*s",
348 MAXDNAME, name, MAXDNAME, domain);
349
350 return (res_query(longname, class, type, answer, anslen));
351}
352
353const char *
354hostalias(const char *name)
355{
356 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
357 char *cp1, *cp2;
358 FILE *fp;
359 char *file;
360 char buf[BUFSIZ];
361 static char abuf[MAXDNAME];
362 size_t len;
363
364 if (_resp->options & RES_NOALIASES)
365 return (NULL);
366 file = getenv("HOSTALIASES");
367 if (issetugid() != 0 || file == NULL || (fp = fopen(file, "r")) == NULL)
368 return (NULL);
369 setbuf(fp, NULL);
370 while ((cp1 = fgetln(fp, &len)) != NULL) {
371 if (cp1[len-1] == '\n')
372 len--;
373 if (len >= sizeof(buf) || len == 0)
374 continue;
375 (void)memcpy(buf, cp1, len);
376 buf[len] = '\0';
377
378 for (cp1 = buf; *cp1 && !isspace(*cp1); ++cp1)
379 ;
380 if (!*cp1)
381 break;
382 *cp1 = '\0';
383 if (!strcasecmp(buf, name)) {
384 while (isspace(*++cp1))
385 ;
386 if (!*cp1)
387 break;
388 for (cp2 = cp1 + 1; *cp2 && !isspace(*cp2); ++cp2)
389 ;
390 *cp2 = '\0';
391 strlcpy(abuf, cp1, sizeof(abuf));
392 fclose(fp);
393 return (abuf);
394 }
395 }
396 fclose(fp);
397 return (NULL);
398}
diff --git a/src/lib/libc/net/res_random.c b/src/lib/libc/net/res_random.c
new file mode 100644
index 0000000000..4dc1d33462
--- /dev/null
+++ b/src/lib/libc/net/res_random.c
@@ -0,0 +1,228 @@
1/* $OpenBSD: res_random.c,v 1.16 2005/03/25 13:24:12 otto 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 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33/*
34 * seed = random 15bit
35 * n = prime, g0 = generator to n,
36 * j = random so that gcd(j,n-1) == 1
37 * g = g0^j mod n will be a generator again.
38 *
39 * X[0] = random seed.
40 * X[n] = a*X[n-1]+b mod m is a Linear Congruential Generator
41 * with a = 7^(even random) mod m,
42 * b = random with gcd(b,m) == 1
43 * m = 31104 and a maximal period of m-1.
44 *
45 * The transaction id is determined by:
46 * id[n] = seed xor (g^X[n] mod n)
47 *
48 * Effectivly the id is restricted to the lower 15 bits, thus
49 * yielding two different cycles by toggling the msb on and off.
50 * This avoids reuse issues caused by reseeding.
51 *
52 * The 16 bit space is very small and brute force attempts are
53 * entirly feasible, we skip a random number of transaction ids
54 * so that an attacker will not get sequential ids.
55 */
56
57#include <sys/types.h>
58#include <netinet/in.h>
59#include <sys/time.h>
60#include <resolv.h>
61
62#include <unistd.h>
63#include <stdlib.h>
64#include <string.h>
65
66#define RU_OUT 180 /* Time after wich will be reseeded */
67#define RU_MAX 30000 /* Uniq cycle, avoid blackjack prediction */
68#define RU_GEN 2 /* Starting generator */
69#define RU_N 32749 /* RU_N-1 = 2*2*3*2729 */
70#define RU_AGEN 7 /* determine ru_a as RU_AGEN^(2*rand) */
71#define RU_M 31104 /* RU_M = 2^7*3^5 - don't change */
72
73#define PFAC_N 3
74const static u_int16_t pfacts[PFAC_N] = {
75 2,
76 3,
77 2729
78};
79
80static u_int16_t ru_x;
81static u_int16_t ru_seed, ru_seed2;
82static u_int16_t ru_a, ru_b;
83static u_int16_t ru_g;
84static u_int16_t ru_counter = 0;
85static u_int16_t ru_msb = 0;
86static long ru_reseed;
87static u_int32_t tmp; /* Storage for unused random */
88static struct timeval tv;
89
90static u_int16_t pmod(u_int16_t, u_int16_t, u_int16_t);
91static void res_initid(void);
92
93/*
94 * Do a fast modular exponation, returned value will be in the range
95 * of 0 - (mod-1)
96 */
97
98static u_int16_t
99pmod(u_int16_t gen, u_int16_t exp, u_int16_t mod)
100{
101 u_int16_t s, t, u;
102
103 s = 1;
104 t = gen;
105 u = exp;
106
107 while (u) {
108 if (u & 1)
109 s = (s * t) % mod;
110 u >>= 1;
111 t = (t * t) % mod;
112 }
113 return (s);
114}
115
116/*
117 * Initializes the seed and chooses a suitable generator. Also toggles
118 * the msb flag. The msb flag is used to generate two distinct
119 * cycles of random numbers and thus avoiding reuse of ids.
120 *
121 * This function is called from res_randomid() when needed, an
122 * application does not have to worry about it.
123 */
124static void
125res_initid(void)
126{
127 u_int16_t j, i;
128 int noprime = 1;
129
130 tmp = arc4random();
131 ru_x = (tmp & 0xFFFF) % RU_M;
132
133 /* 15 bits of random seed */
134 ru_seed = (tmp >> 16) & 0x7FFF;
135 tmp = arc4random();
136 ru_seed2 = tmp & 0x7FFF;
137
138 tmp = arc4random();
139
140 /* Determine the LCG we use */
141 ru_b = (tmp & 0xfffe) | 1;
142 ru_a = pmod(RU_AGEN, (tmp >> 16) & 0xfffe, RU_M);
143 while (ru_b % 3 == 0)
144 ru_b += 2;
145
146 tmp = arc4random();
147 j = tmp % RU_N;
148 tmp = tmp >> 16;
149
150 /*
151 * Do a fast gcd(j,RU_N-1), so we can find a j with
152 * gcd(j, RU_N-1) == 1, giving a new generator for
153 * RU_GEN^j mod RU_N
154 */
155
156 while (noprime) {
157 for (i = 0; i < PFAC_N; i++)
158 if (j % pfacts[i] == 0)
159 break;
160
161 if (i >= PFAC_N)
162 noprime = 0;
163 else
164 j = (j + 1) % RU_N;
165 }
166
167 ru_g = pmod(RU_GEN, j, RU_N);
168 ru_counter = 0;
169
170 gettimeofday(&tv, NULL);
171 ru_reseed = tv.tv_sec + RU_OUT;
172 ru_msb = ru_msb == 0x8000 ? 0 : 0x8000;
173}
174
175u_int
176res_randomid(void)
177{
178 int i, n;
179
180 gettimeofday(&tv, NULL);
181 if (ru_counter >= RU_MAX || tv.tv_sec > ru_reseed)
182 res_initid();
183
184#if 0
185 if (!tmp)
186 tmp = arc4random();
187
188 /* Skip a random number of ids */
189 n = tmp & 0x7; tmp = tmp >> 3;
190 if (ru_counter + n >= RU_MAX)
191 res_initid();
192#else
193 n = 0;
194#endif
195
196 for (i = 0; i <= n; i++)
197 /* Linear Congruential Generator */
198 ru_x = (ru_a * ru_x + ru_b) % RU_M;
199
200 ru_counter += i;
201
202 return (ru_seed ^ pmod(ru_g, ru_seed2 + ru_x, RU_N)) | ru_msb;
203}
204
205#if 0
206void
207main(int argc, char **argv)
208{
209 int i, n;
210 u_int16_t wert;
211
212 res_initid();
213
214 printf("Generator: %u\n", ru_g);
215 printf("Seed: %u\n", ru_seed);
216 printf("Reseed at %ld\n", ru_reseed);
217 printf("Ru_X: %u\n", ru_x);
218 printf("Ru_A: %u\n", ru_a);
219 printf("Ru_B: %u\n", ru_b);
220
221 n = atoi(argv[1]);
222 for (i=0;i<n;i++) {
223 wert = res_randomid();
224 printf("%06d\n", wert);
225 }
226}
227#endif
228
diff --git a/src/lib/libc/net/res_send.c b/src/lib/libc/net/res_send.c
new file mode 100644
index 0000000000..f7631350bc
--- /dev/null
+++ b/src/lib/libc/net/res_send.c
@@ -0,0 +1,870 @@
1/* $OpenBSD: res_send.c,v 1.19 2005/08/06 20:30:04 espie 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 /* change this to "0"
59 * if you talk to a lot
60 * of multi-homed SunOS
61 * ("broken") name servers.
62 */
63#define CHECK_SRVR_ADDR 1 /* XXX - should be in options.h */
64
65/*
66 * Send query to name server and wait for reply.
67 */
68
69#include <sys/types.h>
70#include <sys/param.h>
71#include <sys/time.h>
72#include <sys/socket.h>
73#include <sys/uio.h>
74#include <netinet/in.h>
75#include <arpa/nameser.h>
76#include <arpa/inet.h>
77
78#include <stdio.h>
79#include <netdb.h>
80#include <errno.h>
81#include <resolv.h>
82#include <stdlib.h>
83#include <string.h>
84#include <unistd.h>
85
86#include "thread_private.h"
87
88static int s = -1; /* socket used for communications */
89static int connected = 0; /* is the socket connected */
90static int vc = 0; /* is the socket a virtual ciruit? */
91static int af = 0; /* address family of socket */
92
93#ifndef FD_SET
94/* XXX - should be in portability.h */
95#define NFDBITS 32
96#define FD_SETSIZE 32
97#define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
98#define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
99#define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
100#define FD_ZERO(p) bzero((char *)(p), sizeof(*(p)))
101#endif
102
103#define CAN_RECONNECT 1
104
105#ifndef DEBUG
106# define Dprint(cond, args) /*empty*/
107# define DprintQ(cond, args, query, size) /*empty*/
108# define Aerror(file, string, error, address) /*empty*/
109# define Perror(file, string, error) /*empty*/
110#else
111# define Dprint(cond, args) if (cond) {fprintf args;} else {}
112# define DprintQ(cond, args, query, size) if (cond) {\
113 fprintf args;\
114 __fp_nquery(query, size, stdout);\
115 } else {}
116static char abuf[NI_MAXHOST];
117static char pbuf[NI_MAXSERV];
118static void Aerror(FILE *, char *, int, struct sockaddr *);
119static void Perror(FILE *, char *, int);
120
121 static void
122 Aerror(FILE *file, char *string, int error, struct sockaddr *address)
123 {
124 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
125 int save = errno;
126
127 if (_resp->options & RES_DEBUG) {
128 if (getnameinfo(address, address->sa_len, abuf, sizeof(abuf),
129 pbuf, sizeof(pbuf), NI_NUMERICHOST | NI_NUMERICSERV) != 0) {
130 strlcpy(abuf, "?", sizeof(abuf));
131 strlcpy(pbuf, "?", sizeof(pbuf));
132 }
133 fprintf(file, "res_send: %s ([%s].%s): %s\n",
134 string, abuf, pbuf, strerror(error));
135 }
136 errno = save;
137 }
138 static void
139 Perror(FILE *file, char *string, int error)
140 {
141 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
142 int save = errno;
143
144 if (_resp->options & RES_DEBUG) {
145 fprintf(file, "res_send: %s: %s\n",
146 string, strerror(error));
147 }
148 errno = save;
149 }
150#endif
151
152static res_send_qhook Qhook = NULL;
153static res_send_rhook Rhook = NULL;
154
155void
156res_send_setqhook(res_send_qhook hook)
157{
158
159 Qhook = hook;
160}
161
162void
163res_send_setrhook(res_send_rhook hook)
164{
165
166 Rhook = hook;
167}
168
169#ifdef INET6
170static struct sockaddr * get_nsaddr(size_t);
171
172/*
173 * pick appropriate nsaddr_list for use. see res_init() for initialization.
174 */
175static struct sockaddr *
176get_nsaddr(size_t n)
177{
178 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
179 struct __res_state_ext *_res_extp = _THREAD_PRIVATE(_res_ext, _res_ext,
180 &_res_ext);
181
182 if (!_resp->nsaddr_list[n].sin_family) {
183 /*
184 * - _res_extp->nsaddr_list[n] holds an address that is larger
185 * than struct sockaddr, and
186 * - user code did not update _resp->nsaddr_list[n].
187 */
188 return (struct sockaddr *)&_res_extp->nsaddr_list[n];
189 } else {
190 /*
191 * - user code updated _res.nsaddr_list[n], or
192 * - _resp->nsaddr_list[n] has the same content as
193 * _res_extp->nsaddr_list[n].
194 */
195 return (struct sockaddr *)&_resp->nsaddr_list[n];
196 }
197}
198#else
199#define get_nsaddr(n) ((struct sockaddr *)&_resp->nsaddr_list[(n)])
200#endif
201
202/* int
203 * res_isourserver(ina)
204 * looks up "ina" in _resp->ns_addr_list[]
205 * returns:
206 * 0 : not found
207 * >0 : found
208 * author:
209 * paul vixie, 29may94
210 */
211int
212res_isourserver(const struct sockaddr_in *inp)
213{
214 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
215#ifdef INET6
216 const struct sockaddr_in6 *in6p = (const struct sockaddr_in6 *)inp;
217 const struct sockaddr_in6 *srv6;
218#endif
219 const struct sockaddr_in *srv;
220 int ns, ret;
221
222 ret = 0;
223 switch (inp->sin_family) {
224#ifdef INET6
225 case AF_INET6:
226 for (ns = 0; ns < _resp->nscount; ns++) {
227 srv6 = (struct sockaddr_in6 *)get_nsaddr(ns);
228 if (srv6->sin6_family == in6p->sin6_family &&
229 srv6->sin6_port == in6p->sin6_port &&
230 srv6->sin6_scope_id == in6p->sin6_scope_id &&
231 (IN6_IS_ADDR_UNSPECIFIED(&srv6->sin6_addr) ||
232 IN6_ARE_ADDR_EQUAL(&srv6->sin6_addr,
233 &in6p->sin6_addr))) {
234 ret++;
235 break;
236 }
237 }
238 break;
239#endif
240 case AF_INET:
241 for (ns = 0; ns < _resp->nscount; ns++) {
242 srv = (struct sockaddr_in *)get_nsaddr(ns);
243 if (srv->sin_family == inp->sin_family &&
244 srv->sin_port == inp->sin_port &&
245 (srv->sin_addr.s_addr == INADDR_ANY ||
246 srv->sin_addr.s_addr == inp->sin_addr.s_addr)) {
247 ret++;
248 break;
249 }
250 }
251 break;
252 }
253 return (ret);
254}
255
256/* int
257 * res_nameinquery(name, type, class, buf, eom)
258 * look for (name,type,class) in the query section of packet (buf,eom)
259 * returns:
260 * -1 : format error
261 * 0 : not found
262 * >0 : found
263 * author:
264 * paul vixie, 29may94
265 */
266int
267res_nameinquery(const char *name, int type, int class, const u_char *buf,
268 const u_char *eom)
269{
270 const u_char *cp = buf + HFIXEDSZ;
271 int qdcount = ntohs(((HEADER*)buf)->qdcount);
272
273 while (qdcount-- > 0) {
274 char tname[MAXDNAME+1];
275 int n, ttype, tclass;
276
277 n = dn_expand(buf, eom, cp, tname, sizeof tname);
278 if (n < 0)
279 return (-1);
280 cp += n;
281 ttype = _getshort(cp); cp += INT16SZ;
282 tclass = _getshort(cp); cp += INT16SZ;
283 if (ttype == type &&
284 tclass == class &&
285 strcasecmp(tname, name) == 0)
286 return (1);
287 }
288 return (0);
289}
290
291/* int
292 * res_queriesmatch(buf1, eom1, buf2, eom2)
293 * is there a 1:1 mapping of (name,type,class)
294 * in (buf1,eom1) and (buf2,eom2)?
295 * returns:
296 * -1 : format error
297 * 0 : not a 1:1 mapping
298 * >0 : is a 1:1 mapping
299 * author:
300 * paul vixie, 29may94
301 */
302int
303res_queriesmatch(const u_char *buf1, const u_char *eom1, const u_char *buf2,
304 const u_char *eom2)
305{
306 const u_char *cp = buf1 + HFIXEDSZ;
307 int qdcount = ntohs(((HEADER*)buf1)->qdcount);
308
309 if (qdcount != ntohs(((HEADER*)buf2)->qdcount))
310 return (0);
311 while (qdcount-- > 0) {
312 char tname[MAXDNAME+1];
313 int n, ttype, tclass;
314
315 n = dn_expand(buf1, eom1, cp, tname, sizeof tname);
316 if (n < 0)
317 return (-1);
318 cp += n;
319 ttype = _getshort(cp); cp += INT16SZ;
320 tclass = _getshort(cp); cp += INT16SZ;
321 if (!res_nameinquery(tname, ttype, tclass, buf2, eom2))
322 return (0);
323 }
324 return (1);
325}
326
327int
328res_send(const u_char *buf, int buflen, u_char *ans, int anssiz)
329{
330 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
331 HEADER *hp = (HEADER *) buf;
332 HEADER *anhp = (HEADER *) ans;
333 int gotsomewhere, connreset, terrno, try, v_circuit, resplen, ns;
334 int n;
335 u_int badns; /* XXX NSMAX can't exceed #/bits in this var */
336
337 if (_res_init(0) == -1) {
338 /* errno should have been set by res_init() in this case. */
339 return (-1);
340 }
341 DprintQ((_resp->options & RES_DEBUG) || (_resp->pfcode & RES_PRF_QUERY),
342 (stdout, ";; res_send()\n"), buf, buflen);
343 v_circuit = (_resp->options & RES_USEVC) || buflen > PACKETSZ;
344 gotsomewhere = 0;
345 connreset = 0;
346 terrno = ETIMEDOUT;
347 badns = 0;
348
349 /*
350 * Send request, RETRY times, or until successful
351 */
352 for (try = 0; try < _resp->retry; try++) {
353 for (ns = 0; ns < _resp->nscount; ns++) {
354 struct sockaddr *nsap = get_nsaddr(ns);
355 socklen_t salen;
356
357 if (nsap->sa_len)
358 salen = nsap->sa_len;
359#ifdef INET6
360 else if (nsap->sa_family == AF_INET6)
361 salen = sizeof(struct sockaddr_in6);
362#endif
363 else if (nsap->sa_family == AF_INET)
364 salen = sizeof(struct sockaddr_in);
365 else
366 salen = 0; /*unknown, die on connect*/
367
368 same_ns:
369 if (badns & (1 << ns)) {
370 res_close();
371 goto next_ns;
372 }
373
374 if (Qhook) {
375 int done = 0, loops = 0;
376
377 do {
378 res_sendhookact act;
379
380 act = (*Qhook)((struct sockaddr_in **)&nsap,
381 &buf, &buflen,
382 ans, anssiz, &resplen);
383 switch (act) {
384 case res_goahead:
385 done = 1;
386 break;
387 case res_nextns:
388 res_close();
389 goto next_ns;
390 case res_done:
391 return (resplen);
392 case res_modified:
393 /* give the hook another try */
394 if (++loops < 42) /*doug adams*/
395 break;
396 /*FALLTHROUGH*/
397 case res_error:
398 /*FALLTHROUGH*/
399 default:
400 return (-1);
401 }
402 } while (!done);
403 }
404
405 Dprint((_resp->options & RES_DEBUG) &&
406 getnameinfo(nsap, salen, abuf, sizeof(abuf),
407 NULL, 0, NI_NUMERICHOST) == 0,
408 (stdout, ";; Querying server (# %d) address = %s\n",
409 ns + 1, abuf));
410
411 if (v_circuit) {
412 int truncated;
413 struct iovec iov[2];
414 u_short len;
415 u_char *cp;
416
417 /*
418 * Use virtual circuit;
419 * at most one attempt per server.
420 */
421 try = _resp->retry;
422 truncated = 0;
423 if ((s < 0) || (!vc) || (af != nsap->sa_family)) {
424 if (s >= 0)
425 res_close();
426
427 af = nsap->sa_family;
428 s = socket(af, SOCK_STREAM, 0);
429 if (s < 0) {
430 terrno = errno;
431 Perror(stderr, "socket(vc)", errno);
432#if 0
433 return (-1);
434#else
435 badns |= (1 << ns);
436 res_close();
437 goto next_ns;
438#endif
439 }
440 errno = 0;
441 if (connect(s, nsap, salen) < 0) {
442 terrno = errno;
443 Aerror(stderr, "connect/vc",
444 errno, nsap);
445 badns |= (1 << ns);
446 res_close();
447 goto next_ns;
448 }
449 vc = 1;
450 }
451 /*
452 * Send length & message
453 */
454 putshort((u_short)buflen, (u_char*)&len);
455 iov[0].iov_base = (caddr_t)&len;
456 iov[0].iov_len = INT16SZ;
457 iov[1].iov_base = (caddr_t)buf;
458 iov[1].iov_len = buflen;
459 if (writev(s, iov, 2) != (INT16SZ + buflen)) {
460 terrno = errno;
461 Perror(stderr, "write failed", errno);
462 badns |= (1 << ns);
463 res_close();
464 goto next_ns;
465 }
466 /*
467 * Receive length & response
468 */
469read_len:
470 cp = ans;
471 len = INT16SZ;
472 while ((n = read(s, (char *)cp, (int)len)) > 0) {
473 cp += n;
474 if ((len -= n) <= 0)
475 break;
476 }
477 if (n <= 0) {
478 terrno = errno;
479 Perror(stderr, "read failed", errno);
480 res_close();
481 /*
482 * A long running process might get its TCP
483 * connection reset if the remote server was
484 * restarted. Requery the server instead of
485 * trying a new one. When there is only one
486 * server, this means that a query might work
487 * instead of failing. We only allow one reset
488 * per query to prevent looping.
489 */
490 if (terrno == ECONNRESET && !connreset) {
491 connreset = 1;
492 res_close();
493 goto same_ns;
494 }
495 res_close();
496 goto next_ns;
497 }
498 resplen = _getshort(ans);
499 if (resplen > anssiz) {
500 Dprint(_resp->options & RES_DEBUG,
501 (stdout, ";; response truncated\n")
502 );
503 truncated = 1;
504 len = anssiz;
505 } else
506 len = resplen;
507 cp = ans;
508 while (len != 0 &&
509 (n = read(s, (char *)cp, (int)len)) > 0) {
510 cp += n;
511 len -= n;
512 }
513 if (n <= 0) {
514 terrno = errno;
515 Perror(stderr, "read(vc)", errno);
516 res_close();
517 goto next_ns;
518 }
519 if (truncated) {
520 /*
521 * Flush rest of answer
522 * so connection stays in synch.
523 */
524 anhp->tc = 1;
525 len = resplen - anssiz;
526 while (len != 0) {
527 char junk[PACKETSZ];
528
529 n = (len > sizeof(junk)
530 ? sizeof(junk)
531 : len);
532 if ((n = read(s, junk, n)) > 0)
533 len -= n;
534 else
535 break;
536 }
537 }
538 /*
539 * The calling applicating has bailed out of
540 * a previous call and failed to arrange to have
541 * the circuit closed or the server has got
542 * itself confused. Anyway drop the packet and
543 * wait for the correct one.
544 */
545 if (hp->id != anhp->id) {
546 DprintQ((_resp->options & RES_DEBUG) ||
547 (_resp->pfcode & RES_PRF_REPLY),
548 (stdout, ";; old answer (unexpected):\n"),
549 ans, (resplen>anssiz)?anssiz:resplen);
550 goto read_len;
551 }
552 } else {
553 /*
554 * Use datagrams.
555 */
556 struct timeval timeout;
557 fd_set *dsmaskp;
558 struct sockaddr_storage from;
559 socklen_t fromlen;
560
561 if ((s < 0) || vc || (af != nsap->sa_family)) {
562 if (vc)
563 res_close();
564 af = nsap->sa_family;
565 s = socket(af, SOCK_DGRAM, 0);
566 if (s < 0) {
567#if !CAN_RECONNECT
568 bad_dg_sock:
569#endif
570 terrno = errno;
571 Perror(stderr, "socket(dg)", errno);
572#if 0
573 return (-1);
574#else
575 badns |= (1 << ns);
576 res_close();
577 goto next_ns;
578#endif
579 }
580#ifdef IPV6_MINMTU
581 if (af == AF_INET6) {
582 const int yes = 1;
583 (void)setsockopt(s, IPPROTO_IPV6,
584 IPV6_USE_MIN_MTU, &yes,
585 sizeof(yes));
586 }
587#endif
588 connected = 0;
589 }
590 /*
591 * On a 4.3BSD+ machine (client and server,
592 * actually), sending to a nameserver datagram
593 * port with no nameserver will cause an
594 * ICMP port unreachable message to be returned.
595 * If our datagram socket is "connected" to the
596 * server, we get an ECONNREFUSED error on the next
597 * socket operation, and select returns if the
598 * error message is received. We can thus detect
599 * the absence of a nameserver without timing out.
600 * If we have sent queries to at least two servers,
601 * however, we don't want to remain connected,
602 * as we wish to receive answers from the first
603 * server to respond.
604 */
605 if (!(_resp->options & RES_INSECURE1) &&
606 (_resp->nscount == 1 || (try == 0 && ns == 0))) {
607 /*
608 * Connect only if we are sure we won't
609 * receive a response from another server.
610 */
611 if (!connected) {
612 if (connect(s, nsap, salen) < 0) {
613 Aerror(stderr,
614 "connect(dg)",
615 errno, nsap);
616 badns |= (1 << ns);
617 res_close();
618 goto next_ns;
619 }
620 connected = 1;
621 }
622 if (send(s, (char*)buf, buflen, 0) != buflen) {
623 Perror(stderr, "send", errno);
624 badns |= (1 << ns);
625 res_close();
626 goto next_ns;
627 }
628 } else {
629 /*
630 * Disconnect if we want to listen
631 * for responses from more than one server.
632 */
633 if (connected) {
634#if CAN_RECONNECT
635#ifdef INET6
636 /* XXX: any errornous address */
637#endif /* INET6 */
638 struct sockaddr_in no_addr;
639
640 no_addr.sin_family = AF_INET;
641 no_addr.sin_addr.s_addr = INADDR_ANY;
642 no_addr.sin_port = 0;
643 (void) connect(s,
644 (struct sockaddr *)
645 &no_addr,
646 sizeof(no_addr));
647#else
648 int s1 = socket(af, SOCK_DGRAM,0);
649 if (s1 < 0)
650 goto bad_dg_sock;
651 (void) dup2(s1, s);
652 (void) close(s1);
653 Dprint(_resp->options & RES_DEBUG,
654 (stdout, ";; new DG socket\n"))
655#endif
656#ifdef IPV6_MINMTU
657 if (af == AF_INET6) {
658 const int yes = 1;
659 (void)setsockopt(s, IPPROTO_IPV6,
660 IPV6_USE_MIN_MTU, &yes,
661 sizeof(yes));
662 }
663#endif
664 connected = 0;
665 errno = 0;
666 }
667 if (sendto(s, (char*)buf, buflen, 0,
668 nsap, salen) != buflen) {
669 Aerror(stderr, "sendto", errno, nsap);
670 badns |= (1 << ns);
671 res_close();
672 goto next_ns;
673 }
674 }
675
676 /*
677 * Wait for reply
678 */
679 timeout.tv_sec = (_resp->retrans << try);
680 if (try > 0)
681 timeout.tv_sec /= _resp->nscount;
682 if ((long) timeout.tv_sec <= 0)
683 timeout.tv_sec = 1;
684 timeout.tv_usec = 0;
685 wait:
686 dsmaskp = (fd_set *)calloc(howmany(s+1, NFDBITS),
687 sizeof(fd_mask));
688 if (dsmaskp == NULL) {
689 res_close();
690 goto next_ns;
691 }
692 FD_SET(s, dsmaskp);
693 n = select(s+1, dsmaskp, (fd_set *)NULL,
694 (fd_set *)NULL, &timeout);
695 free(dsmaskp);
696 if (n < 0) {
697 if (errno == EINTR)
698 goto wait;
699 Perror(stderr, "select", errno);
700 res_close();
701 goto next_ns;
702 }
703 if (n == 0) {
704 /*
705 * timeout
706 */
707 Dprint(_resp->options & RES_DEBUG,
708 (stdout, ";; timeout\n"));
709 gotsomewhere = 1;
710 res_close();
711 goto next_ns;
712 }
713 errno = 0;
714 fromlen = sizeof(from);
715 resplen = recvfrom(s, (char*)ans, anssiz, 0,
716 (struct sockaddr *)&from, &fromlen);
717 if (resplen <= 0) {
718 Perror(stderr, "recvfrom", errno);
719 res_close();
720 goto next_ns;
721 }
722 gotsomewhere = 1;
723 if (hp->id != anhp->id) {
724 /*
725 * response from old query, ignore it.
726 * XXX - potential security hazard could
727 * be detected here.
728 */
729 DprintQ((_resp->options & RES_DEBUG) ||
730 (_resp->pfcode & RES_PRF_REPLY),
731 (stdout, ";; old answer:\n"),
732 ans, (resplen>anssiz)?anssiz:resplen);
733 goto wait;
734 }
735#if CHECK_SRVR_ADDR
736 if (!(_resp->options & RES_INSECURE1) &&
737 !res_isourserver((struct sockaddr_in *)&from)) {
738 /*
739 * response from wrong server? ignore it.
740 * XXX - potential security hazard could
741 * be detected here.
742 */
743 DprintQ((_resp->options & RES_DEBUG) ||
744 (_resp->pfcode & RES_PRF_REPLY),
745 (stdout, ";; not our server:\n"),
746 ans, (resplen>anssiz)?anssiz:resplen);
747 goto wait;
748 }
749#endif
750 if (!(_resp->options & RES_INSECURE2) &&
751 !res_queriesmatch(buf, buf + buflen,
752 ans, ans + anssiz)) {
753 /*
754 * response contains wrong query? ignore it.
755 * XXX - potential security hazard could
756 * be detected here.
757 */
758 DprintQ((_resp->options & RES_DEBUG) ||
759 (_resp->pfcode & RES_PRF_REPLY),
760 (stdout, ";; wrong query name:\n"),
761 ans, (resplen>anssiz)?anssiz:resplen);
762 goto wait;
763 }
764 if (anhp->rcode == SERVFAIL ||
765 anhp->rcode == NOTIMP ||
766 anhp->rcode == REFUSED) {
767 DprintQ(_resp->options & RES_DEBUG,
768 (stdout, "server rejected query:\n"),
769 ans, (resplen>anssiz)?anssiz:resplen);
770 badns |= (1 << ns);
771 res_close();
772 /* don't retry if called from dig */
773 if (!_resp->pfcode)
774 goto next_ns;
775 }
776 if (!(_resp->options & RES_IGNTC) && anhp->tc) {
777 /*
778 * get rest of answer;
779 * use TCP with same server.
780 */
781 Dprint(_resp->options & RES_DEBUG,
782 (stdout, ";; truncated answer\n"));
783 v_circuit = 1;
784 res_close();
785 goto same_ns;
786 }
787 } /*if vc/dg*/
788 Dprint((_resp->options & RES_DEBUG) ||
789 ((_resp->pfcode & RES_PRF_REPLY) &&
790 (_resp->pfcode & RES_PRF_HEAD1)),
791 (stdout, ";; got answer:\n"));
792 DprintQ((_resp->options & RES_DEBUG) ||
793 (_resp->pfcode & RES_PRF_REPLY),
794 (stdout, "%s", ""),
795 ans, (resplen>anssiz)?anssiz:resplen);
796 /*
797 * If using virtual circuits, we assume that the first server
798 * is preferred over the rest (i.e. it is on the local
799 * machine) and only keep that one open.
800 * If we have temporarily opened a virtual circuit,
801 * or if we haven't been asked to keep a socket open,
802 * close the socket.
803 */
804 if ((v_circuit && (!(_resp->options & RES_USEVC) || ns != 0)) ||
805 !(_resp->options & RES_STAYOPEN)) {
806 res_close();
807 }
808 if (Rhook) {
809 int done = 0, loops = 0;
810
811 do {
812 res_sendhookact act;
813
814 act = (*Rhook)((struct sockaddr_in *)nsap,
815 buf, buflen,
816 ans, anssiz, &resplen);
817 switch (act) {
818 case res_goahead:
819 case res_done:
820 done = 1;
821 break;
822 case res_nextns:
823 res_close();
824 goto next_ns;
825 case res_modified:
826 /* give the hook another try */
827 if (++loops < 42) /*doug adams*/
828 break;
829 /*FALLTHROUGH*/
830 case res_error:
831 /*FALLTHROUGH*/
832 default:
833 return (-1);
834 }
835 } while (!done);
836
837 }
838 return (resplen);
839 next_ns: ;
840 } /*foreach ns*/
841 } /*foreach retry*/
842 res_close();
843 if (!v_circuit) {
844 if (!gotsomewhere)
845 errno = ECONNREFUSED; /* no nameservers found */
846 else
847 errno = ETIMEDOUT; /* no answer obtained */
848 } else
849 errno = terrno;
850 return (-1);
851}
852
853/*
854 * This routine is for closing the socket if a virtual circuit is used and
855 * the program wants to close it. This provides support for endhostent()
856 * which expects to close the socket.
857 *
858 * This routine is not expected to be user visible.
859 */
860void
861res_close(void)
862{
863 if (s >= 0) {
864 (void) close(s);
865 s = -1;
866 connected = 0;
867 vc = 0;
868 af = 0;
869 }
870}
diff --git a/src/lib/libc/net/resolver.3 b/src/lib/libc/net/resolver.3
new file mode 100644
index 0000000000..c9532e9c94
--- /dev/null
+++ b/src/lib/libc/net/resolver.3
@@ -0,0 +1,354 @@
1.\" $OpenBSD: resolver.3,v 1.20 2005/07/22 04:50:51 jaredy 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 "const char *dname"
50.Fa "int class"
51.Fa "int type"
52.Fa "unsigned char *answer"
53.Fa "int anslen"
54.Fc
55.Ft int
56.Fo res_search
57.Fa "const char *dname"
58.Fa "int class"
59.Fa "int type"
60.Fa "unsigned char *answer"
61.Fa "int anslen"
62.Fc
63.Ft int
64.Fo res_mkquery
65.Fa "int op"
66.Fa "const char *dname"
67.Fa "int class"
68.Fa "int type"
69.Fa "const unsigned char *data"
70.Fa "int datalen"
71.Fa "const unsigned char *newrr"
72.Fa "unsigned char *buf"
73.Fa "int buflen"
74.Fc
75.Ft int
76.Fo res_send
77.Fa "const unsigned char *msg"
78.Fa "int msglen"
79.Fa "unsigned 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 "const char *exp_dn"
87.Fa "unsigned char *comp_dn"
88.Fa "int length"
89.Fa "unsigned char **dnptrs"
90.Fa "unsigned char **lastdnptr"
91.Fc
92.Ft int
93.Fo dn_expand
94.Fa "const unsigned char *msg"
95.Fa "const unsigned char *eomorig"
96.Fa "const unsigned char *comp_dn"
97.Fa "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.It Dv RES_USE_EDNS0
175Enables support for OPT pseudo-RR for EDNS0 extension.
176With this option, resolver code will attach OPT pseudo-RR into DNS queries,
177to inform of our receive buffer size.
178The option will allow DNS servers to take advantage of non-default receive
179buffer size, and to send larger replies.
180DNS query packets with EDNS0 extension is not compatible with
181non-EDNS0 DNS servers.
182.El
183.Pp
184The
185.Fn res_init
186routine reads the configuration file (if any; see
187.Xr resolv.conf 5 )
188to get the default domain name, search list, and the Internet address
189of the local name server(s).
190If no server is configured, the host running
191the resolver is tried.
192The current domain name is defined by the hostname
193if not specified in the configuration file;
194it can be overridden by the environment variable
195.Ev LOCALDOMAIN .
196This environment variable may contain several blank-separated
197tokens if you wish to override the
198.Fa search list
199on a per-process basis.
200This is similar to the
201.Fa search
202command in the configuration file.
203Another environment variable
204.Ev RES_OPTIONS
205can be set to override certain internal resolver options which
206are otherwise set by changing fields in the
207.Fa _res
208structure or are inherited from the configuration file's
209.Fa options
210command.
211The syntax of the
212.Ev RES_OPTIONS
213environment variable is explained in
214.Xr resolv.conf 5 .
215Initialization normally occurs on the first call
216to one of the following routines.
217.Pp
218The
219.Fn res_query
220function provides an interface to the server query mechanism.
221It constructs a query, sends it to the local server,
222awaits a response, and makes preliminary checks on the reply.
223The query requests information of the specified
224.Fa type
225and
226.Fa class
227for the specified fully qualified domain name
228.Fa dname .
229The reply message is left in the
230.Fa answer
231buffer with length
232.Fa anslen
233supplied by the caller.
234Values for the
235.Fa class
236and
237.Fa type
238fields
239are defined in
240.Aq Pa arpa/nameser.h .
241.Pp
242The
243.Fn res_search
244routine makes a query and awaits a response like
245.Fn res_query ,
246but in addition, it implements the default and search rules controlled by the
247.Dv RES_DEFNAMES
248and
249.Dv RES_DNSRCH
250options.
251It returns the first successful reply.
252.Pp
253The remaining routines are lower-level routines used by
254.Fn res_query .
255The
256.Fn res_mkquery
257function constructs a standard query message and places it in
258.Fa buf .
259It returns the size of the query, or \-1 if the query is larger than
260.Fa buflen .
261The query type
262.Fa op
263is usually
264.Dv QUERY ,
265but can be any of the query types defined in
266.Aq Pa arpa/nameser.h .
267The domain name for the query is given by
268.Fa dname .
269.Fa newrr
270is currently unused but is intended for making update messages.
271.Pp
272The
273.Fn res_send
274routine sends a pre-formatted query and returns an answer.
275It will call
276.Fn res_init
277if
278.Dv RES_INIT
279is not set, send the query to the local name server, and
280handle timeouts and retries.
281The length of the reply message is returned, or \-1 if there were errors.
282.Pp
283The
284.Fn dn_comp
285function compresses the domain name
286.Fa exp_dn
287and stores it in
288.Fa comp_dn .
289The size of the compressed name is returned or \-1 if there were errors.
290The size of the array pointed to by
291.Fa comp_dn
292is given by
293.Fa length .
294The compression uses an array of pointers
295.Fa dnptrs
296to previously compressed names in the current message.
297The first pointer points
298to the beginning of the message and the list ends with
299.Dv NULL .
300The limit to the array is specified by
301.Fa lastdnptr .
302A side effect of
303.Fn dn_comp
304is to update the list of pointers for labels inserted into the message
305as the name is compressed.
306If
307.Fa dnptrs
308is
309.Dv NULL ,
310names are not compressed.
311If
312.Fa lastdnptr
313is
314.Dv NULL ,
315the list of labels is not updated.
316.Pp
317The
318.Fn dn_expand
319entry expands the compressed domain name
320.Fa comp_dn
321to a full domain name.
322The compressed name is contained in a query or reply message;
323.Fa msg
324is a pointer to the beginning of the message.
325The uncompressed name is placed in the buffer indicated by
326.Fa exp_dn
327which is of size
328.Fa length .
329The size of compressed name is returned or \-1 if there was an error.
330.Sh FILES
331.Bl -tag -width "/etc/resolv.confXX"
332.It Pa /etc/resolv.conf
333The configuration file.
334.El
335.Sh SEE ALSO
336.Xr gethostbyname 3 ,
337.Xr resolv.conf 5 ,
338.Xr hostname 7 ,
339.Xr named 8
340.Pp
341.%T RFC 974 ,
342.%T RFC 1032 ,
343.%T RFC 1033 ,
344.%T RFC 1034 ,
345.%T RFC 1035 ,
346.%T RFC 1535
347.Rs
348.%T "Name Server Operations Guide for BIND"
349.Re
350.Sh HISTORY
351The
352.Nm
353function appeared in
354.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..ccc411500b
--- /dev/null
+++ b/src/lib/libc/net/rresvport.c
@@ -0,0 +1,107 @@
1/* $OpenBSD: rresvport.c,v 1.9 2005/11/10 10:00:17 espie Exp $ */
2/*
3 * Copyright (c) 1995, 1996, 1998 Theo de Raadt. All rights reserved.
4 * Copyright (c) 1983, 1993, 1994
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
32#include <sys/param.h>
33#include <sys/socket.h>
34#include <sys/stat.h>
35
36#include <netinet/in.h>
37#include <arpa/inet.h>
38
39#include <signal.h>
40#include <fcntl.h>
41#include <netdb.h>
42#include <unistd.h>
43#include <pwd.h>
44#include <errno.h>
45#include <stdio.h>
46#include <ctype.h>
47#include <string.h>
48#include <syslog.h>
49#include <stdlib.h>
50#include <netgroup.h>
51
52int
53rresvport(int *alport)
54{
55 return rresvport_af(alport, AF_INET);
56}
57
58
59int
60rresvport_af(int *alport, int af)
61{
62 struct sockaddr_storage ss;
63 struct sockaddr *sa;
64 u_int16_t *portp;
65 int s;
66
67 bzero(&ss, sizeof ss);
68 sa = (struct sockaddr *)&ss;
69
70 switch (af) {
71 case AF_INET:
72 sa->sa_len = sizeof(struct sockaddr_in);
73 portp = &((struct sockaddr_in *)sa)->sin_port;
74 break;
75 case AF_INET6:
76 sa->sa_len = sizeof(struct sockaddr_in6);
77 portp = &((struct sockaddr_in6 *)sa)->sin6_port;
78 break;
79 default:
80 errno = EPFNOSUPPORT;
81 return (-1);
82 }
83 sa->sa_family = af;
84
85 s = socket(af, SOCK_STREAM, 0);
86 if (s < 0)
87 return (-1);
88
89 *portp = htons(*alport);
90 if (*alport < IPPORT_RESERVED - 1) {
91 if (bind(s, sa, sa->sa_len) >= 0)
92 return (s);
93 if (errno != EADDRINUSE) {
94 (void)close(s);
95 return (-1);
96 }
97 }
98
99 *portp = 0;
100 sa->sa_family = af;
101 if (bindresvport_sa(s, sa) == -1) {
102 (void)close(s);
103 return (-1);
104 }
105 *alport = ntohs(*portp);
106 return (s);
107}
diff --git a/src/lib/libc/net/rthdr.c b/src/lib/libc/net/rthdr.c
new file mode 100644
index 0000000000..36ac5a3554
--- /dev/null
+++ b/src/lib/libc/net/rthdr.c
@@ -0,0 +1,215 @@
1/* $OpenBSD: rthdr.c,v 1.7 2005/03/25 13:24:12 otto 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(int type, int seg)
44{
45 switch (type) {
46 case IPV6_RTHDR_TYPE_0:
47 if (seg < 1 || seg > 23)
48 return (0);
49 return (CMSG_SPACE(sizeof(struct in6_addr) * seg +
50 sizeof(struct ip6_rthdr0)));
51 default:
52 return (0);
53 }
54}
55
56struct cmsghdr *
57inet6_rthdr_init(void *bp, int type)
58{
59 struct cmsghdr *ch = (struct cmsghdr *)bp;
60 struct ip6_rthdr *rthdr;
61
62 rthdr = (struct ip6_rthdr *)CMSG_DATA(ch);
63
64 ch->cmsg_level = IPPROTO_IPV6;
65 ch->cmsg_type = IPV6_RTHDR;
66
67 switch (type) {
68 case IPV6_RTHDR_TYPE_0:
69 ch->cmsg_len = CMSG_LEN(sizeof(struct ip6_rthdr0));
70 bzero(rthdr, sizeof(struct ip6_rthdr0));
71 rthdr->ip6r_type = IPV6_RTHDR_TYPE_0;
72 return (ch);
73 default:
74 return (NULL);
75 }
76}
77
78int
79inet6_rthdr_add(struct cmsghdr *cmsg, const struct in6_addr *addr, u_int flags)
80{
81 struct ip6_rthdr *rthdr;
82
83 rthdr = (struct ip6_rthdr *)CMSG_DATA(cmsg);
84
85 switch (rthdr->ip6r_type) {
86 case IPV6_RTHDR_TYPE_0:
87 {
88 struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr;
89 if (flags != IPV6_RTHDR_LOOSE)
90 return (-1);
91 if (rt0->ip6r0_segleft == 23)
92 return (-1);
93 rt0->ip6r0_segleft++;
94 bcopy(addr, (caddr_t)rt0 + ((rt0->ip6r0_len + 1) << 3),
95 sizeof(struct in6_addr));
96 rt0->ip6r0_len += sizeof(struct in6_addr) >> 3;
97 cmsg->cmsg_len = CMSG_LEN((rt0->ip6r0_len + 1) << 3);
98 break;
99 }
100 default:
101 return (-1);
102 }
103
104 return (0);
105}
106
107int
108inet6_rthdr_lasthop(struct cmsghdr *cmsg, unsigned int flags)
109{
110 struct ip6_rthdr *rthdr;
111
112 rthdr = (struct ip6_rthdr *)CMSG_DATA(cmsg);
113
114 switch (rthdr->ip6r_type) {
115 case IPV6_RTHDR_TYPE_0:
116 {
117 struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr;
118 if (flags != IPV6_RTHDR_LOOSE)
119 return (-1);
120 if (rt0->ip6r0_segleft > 23)
121 return (-1);
122 break;
123 }
124 default:
125 return (-1);
126 }
127
128 return (0);
129}
130
131#if 0
132int
133inet6_rthdr_reverse(in, out)
134 const struct cmsghdr *in;
135 struct cmsghdr *out;
136{
137
138 return (-1);
139}
140#endif
141
142int
143inet6_rthdr_segments(const struct cmsghdr *cmsg)
144{
145 struct ip6_rthdr *rthdr;
146
147 rthdr = (struct ip6_rthdr *)CMSG_DATA(cmsg);
148
149 switch (rthdr->ip6r_type) {
150 case IPV6_RTHDR_TYPE_0:
151 {
152 struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr;
153
154 if (rt0->ip6r0_len % 2 || 46 < rt0->ip6r0_len)
155 return (-1);
156
157 return (rt0->ip6r0_len * 8) / sizeof(struct in6_addr);
158 }
159
160 default:
161 return (-1);
162 }
163}
164
165struct in6_addr *
166inet6_rthdr_getaddr(struct cmsghdr *cmsg, int index)
167{
168 struct ip6_rthdr *rthdr;
169
170 rthdr = (struct ip6_rthdr *)CMSG_DATA(cmsg);
171
172 switch (rthdr->ip6r_type) {
173 case IPV6_RTHDR_TYPE_0:
174 {
175 struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr;
176 int naddr;
177
178 if (rt0->ip6r0_len % 2 || 46 < rt0->ip6r0_len)
179 return NULL;
180 naddr = (rt0->ip6r0_len * 8) / sizeof(struct in6_addr);
181 if (index <= 0 || naddr < index)
182 return NULL;
183 return ((struct in6_addr *)(rt0 + 1)) + index;
184 }
185
186 default:
187 return NULL;
188 }
189}
190
191int
192inet6_rthdr_getflags(const struct cmsghdr *cmsg, int index)
193{
194 struct ip6_rthdr *rthdr;
195
196 rthdr = (struct ip6_rthdr *)CMSG_DATA(cmsg);
197
198 switch (rthdr->ip6r_type) {
199 case IPV6_RTHDR_TYPE_0:
200 {
201 struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr;
202 int naddr;
203
204 if (rt0->ip6r0_len % 2 || 46 < rt0->ip6r0_len)
205 return (-1);
206 naddr = (rt0->ip6r0_len * 8) / sizeof(struct in6_addr);
207 if (index < 0 || naddr < index)
208 return (-1);
209 return IPV6_RTHDR_LOOSE;
210 }
211
212 default:
213 return (-1);
214 }
215}
diff --git a/src/lib/libc/net/send.c b/src/lib/libc/net/send.c
new file mode 100644
index 0000000000..1bfc80b87a
--- /dev/null
+++ b/src/lib/libc/net/send.c
@@ -0,0 +1,40 @@
1/* $OpenBSD: send.c,v 1.5 2005/08/06 20:30:04 espie Exp $ */
2/*
3 * Copyright (c) 1988, 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
31#include <sys/types.h>
32#include <sys/socket.h>
33
34#include <stddef.h>
35
36ssize_t
37send(int s, const void *msg, size_t len, int flags)
38{
39 return (sendto(s, msg, len, flags, NULL, 0));
40}
diff --git a/src/lib/libc/net/sethostent.c b/src/lib/libc/net/sethostent.c
new file mode 100644
index 0000000000..6f6d0e405a
--- /dev/null
+++ b/src/lib/libc/net/sethostent.c
@@ -0,0 +1,57 @@
1/* $OpenBSD: sethostent.c,v 1.9 2005/08/06 20:30:04 espie Exp $ */
2/*
3 * Copyright (c) 1985, 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
31#include <sys/param.h>
32#include <netinet/in.h>
33#include <arpa/nameser.h>
34#include <netdb.h>
35#include <resolv.h>
36
37#include "thread_private.h"
38
39void
40sethostent(int stayopen)
41{
42 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
43
44 if (_res_init(0) == -1)
45 return;
46 if (stayopen)
47 _resp->options |= RES_STAYOPEN | RES_USEVC;
48}
49
50void
51endhostent(void)
52{
53 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
54
55 _resp->options &= ~(RES_STAYOPEN | RES_USEVC);
56 res_close();
57}
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