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.inc97
-rw-r--r--src/lib/libc/net/base64.c308
-rw-r--r--src/lib/libc/net/byteorder.3186
-rw-r--r--src/lib/libc/net/ethers.382
-rw-r--r--src/lib/libc/net/ethers.c188
-rw-r--r--src/lib/libc/net/freeaddrinfo.c50
-rw-r--r--src/lib/libc/net/gai_strerror.395
-rw-r--r--src/lib/libc/net/gai_strerror.c78
-rw-r--r--src/lib/libc/net/getaddrinfo.3470
-rw-r--r--src/lib/libc/net/getaddrinfo.c1755
-rw-r--r--src/lib/libc/net/gethostbyname.3239
-rw-r--r--src/lib/libc/net/gethostnamadr.c977
-rw-r--r--src/lib/libc/net/getifaddrs.3157
-rw-r--r--src/lib/libc/net/getifaddrs.c284
-rw-r--r--src/lib/libc/net/getnameinfo.3265
-rw-r--r--src/lib/libc/net/getnameinfo.c351
-rw-r--r--src/lib/libc/net/getnetbyaddr.c25
-rw-r--r--src/lib/libc/net/getnetbyname.c30
-rw-r--r--src/lib/libc/net/getnetent.383
-rw-r--r--src/lib/libc/net/getnetent.c52
-rw-r--r--src/lib/libc/net/getnetnamadr.c384
-rw-r--r--src/lib/libc/net/getpeereid.3119
-rw-r--r--src/lib/libc/net/getpeereid.c36
-rw-r--r--src/lib/libc/net/getproto.c50
-rw-r--r--src/lib/libc/net/getprotoent.3153
-rw-r--r--src/lib/libc/net/getprotoent.c145
-rw-r--r--src/lib/libc/net/getprotoname.c57
-rw-r--r--src/lib/libc/net/getrrsetbyname.3166
-rw-r--r--src/lib/libc/net/getrrsetbyname.c517
-rw-r--r--src/lib/libc/net/getservbyname.c59
-rw-r--r--src/lib/libc/net/getservbyport.c56
-rw-r--r--src/lib/libc/net/getservent.3163
-rw-r--r--src/lib/libc/net/getservent.c147
-rw-r--r--src/lib/libc/net/herror.c53
-rw-r--r--src/lib/libc/net/htonl.c20
-rw-r--r--src/lib/libc/net/htons.c14
-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.c146
-rw-r--r--src/lib/libc/net/if_nametoindex.c81
-rw-r--r--src/lib/libc/net/inet.3264
-rw-r--r--src/lib/libc/net/inet6_opt_init.3338
-rw-r--r--src/lib/libc/net/inet6_option_space.3444
-rw-r--r--src/lib/libc/net/inet6_rth_space.3219
-rw-r--r--src/lib/libc/net/inet6_rthdr_space.3314
-rw-r--r--src/lib/libc/net/inet_addr.c111
-rw-r--r--src/lib/libc/net/inet_lnaof.c24
-rw-r--r--src/lib/libc/net/inet_makeaddr.c22
-rw-r--r--src/lib/libc/net/inet_net.3176
-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.c24
-rw-r--r--src/lib/libc/net/inet_network.c41
-rw-r--r--src/lib/libc/net/inet_ntoa.c24
-rw-r--r--src/lib/libc/net/inet_ntop.c195
-rw-r--r--src/lib/libc/net/inet_pton.c213
-rw-r--r--src/lib/libc/net/ip6opt.c596
-rw-r--r--src/lib/libc/net/iso_addr.3112
-rw-r--r--src/lib/libc/net/iso_addr.c125
-rw-r--r--src/lib/libc/net/link_addr.3 (renamed from src/lib/libc/net/linkaddr.3)40
-rw-r--r--src/lib/libc/net/linkaddr.c34
-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/ns.3132
-rw-r--r--src/lib/libc/net/ns_addr.c233
-rw-r--r--src/lib/libc/net/ns_ntoa.c106
-rw-r--r--src/lib/libc/net/nsap_addr.c94
-rw-r--r--src/lib/libc/net/ntohl.c20
-rw-r--r--src/lib/libc/net/ntohs.c14
-rw-r--r--src/lib/libc/net/rcmd.3174
-rw-r--r--src/lib/libc/net/rcmd.c538
-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.c22
-rw-r--r--src/lib/libc/net/res_comp.c269
-rw-r--r--src/lib/libc/net/res_data.c105
-rw-r--r--src/lib/libc/net/res_debug.c1432
-rw-r--r--src/lib/libc/net/res_debug_syms.c189
-rw-r--r--src/lib/libc/net/res_init.c593
-rw-r--r--src/lib/libc/net/res_mkquery.c258
-rw-r--r--src/lib/libc/net/res_query.c265
-rw-r--r--src/lib/libc/net/res_random.c264
-rw-r--r--src/lib/libc/net/res_send.c863
-rw-r--r--src/lib/libc/net/resolver.3172
-rw-r--r--src/lib/libc/net/rresvport.c107
-rw-r--r--src/lib/libc/net/rthdr.c378
-rw-r--r--src/lib/libc/net/ruserok.c437
-rw-r--r--src/lib/libc/net/send.c22
-rw-r--r--src/lib/libc/net/sethostent.c35
-rw-r--r--src/lib/libc/net/vars6.c42
91 files changed, 15649 insertions, 3641 deletions
diff --git a/src/lib/libc/net/Makefile.inc b/src/lib/libc/net/Makefile.inc
index 2d220067e4..530bc3f3f0 100644
--- a/src/lib/libc/net/Makefile.inc
+++ b/src/lib/libc/net/Makefile.inc
@@ -1,46 +1,101 @@
1# $NetBSD: Makefile.inc,v 1.23 1995/03/02 09:09:07 chopps Exp $ 1# $OpenBSD: Makefile.inc,v 1.48 2010/07/01 19:15:30 deraadt Exp $
2# @(#)Makefile.inc 8.2 (Berkeley) 9/5/93
3 2
4# net sources 3# net sources
5.PATH: ${.CURDIR}/arch/${MACHINE_ARCH}/net ${.CURDIR}/net 4.PATH: ${LIBCSRCDIR}/arch/${MACHINE_CPU}/net ${LIBCSRCDIR}/net
6 5
7SRCS+= gethostnamadr.c getnetbyaddr.c getnetbyname.c getnetent.c \ 6CFLAGS+=-DRESOLVSORT
8 getproto.c getprotoent.c getprotoname.c getservbyname.c \ 7
9 getservbyport.c getservent.c herror.c inet_addr.c inet_lnaof.c \ 8SRCS+= base64.c freeaddrinfo.c gai_strerror.c getaddrinfo.c gethostnamadr.c \
10 inet_makeaddr.c inet_netof.c inet_network.c inet_ntoa.c \ 9 getifaddrs.c getnameinfo.c getnetbyaddr.c getnetbyname.c getnetent.c \
11 iso_addr.c linkaddr.c ns_addr.c ns_ntoa.c rcmd.c recv.c res_comp.c \ 10 getnetnamadr.c getpeereid.c getproto.c getprotoent.c getprotoname.c \
12 res_debug.c res_init.c res_mkquery.c res_query.c res_send.c \ 11 getservbyname.c getservbyport.c getservent.c getrrsetbyname.c \
13 send.c sethostent.c ethers.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 linkaddr.c net_addrcmp.c nsap_addr.c \
16 rcmd.c ruserok.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
14 23
15# machine-dependent net sources 24# machine-dependent net sources
16# m-d Makefile.inc must include sources for: 25# m-d Makefile.inc must include sources for:
17# htonl() htons() ntohl() ntohs() 26# htonl() htons() ntohl() ntohs()
18 27
19.include "${.CURDIR}/arch/${MACHINE_ARCH}/net/Makefile.inc" 28.include "${LIBCSRCDIR}/arch/${MACHINE_CPU}/net/Makefile.inc"
20 29
21MAN+= byteorder.3 gethostbyname.3 getnetent.3 getprotoent.3 getservent.3 \ 30MAN+= byteorder.3 ethers.3 gai_strerror.3 getaddrinfo.3 gethostbyname.3 \
22 inet.3 linkaddr.3 ns.3 rcmd.3 resolver.3 ethers.3 31 getifaddrs.3 getnameinfo.3 getnetent.3 getpeereid.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 inet6_opt_init.3 inet6_rth_space.3 \
35 link_addr.3 net_addrcmp.3 \
36 rcmd.3 rcmdsh.3 resolver.3
23 37
24MLINKS+=byteorder.3 htonl.3 byteorder.3 htons.3 byteorder.3 ntohl.3 \ 38MLINKS+=byteorder.3 htonl.3 byteorder.3 htons.3 byteorder.3 ntohl.3 \
25 byteorder.3 ntohs.3 39 byteorder.3 ntohs.3 byteorder.3 htobe16.3 byteorder.3 htobe32.3 \
40 byteorder.3 htobe64.3 byteorder.3 betoh16.3 byteorder.3 betoh32.3 \
41 byteorder.3 betoh64.3 byteorder.3 htole16.3 byteorder.3 htole32.3 \
42 byteorder.3 htole64.3 byteorder.3 letoh16.3 byteorder.3 letoh32.3 \
43 byteorder.3 letoh64.3 byteorder.3 swap16.3 byteorder.3 swap32.3 \
44 byteorder.3 swap64.3
26MLINKS+=ethers.3 ether_aton.3 ethers.3 ether_hostton.3 ethers.3 ether_line.3 \ 45MLINKS+=ethers.3 ether_aton.3 ethers.3 ether_hostton.3 ethers.3 ether_line.3 \
27 ethers.3 ether_ntoa.3 ethers.3 ether_ntohost.3 46 ethers.3 ether_ntoa.3 ethers.3 ether_ntohost.3
47MLINKS+=getaddrinfo.3 freeaddrinfo.3
28MLINKS+=gethostbyname.3 endhostent.3 gethostbyname.3 gethostbyaddr.3 \ 48MLINKS+=gethostbyname.3 endhostent.3 gethostbyname.3 gethostbyaddr.3 \
29 gethostbyname.3 sethostent.3 gethostbyname.3 gethostent.3 \ 49 gethostbyname.3 sethostent.3 gethostbyname.3 gethostent.3 \
30 gethostbyname.3 herror.3 50 gethostbyname.3 herror.3 gethostbyname.3 gethostbyname2.3 \
51 gethostbyname.3 hstrerror.3
52MLINKS+=getifaddrs.3 freeifaddrs.3
31MLINKS+=getnetent.3 endnetent.3 getnetent.3 getnetbyaddr.3 \ 53MLINKS+=getnetent.3 endnetent.3 getnetent.3 getnetbyaddr.3 \
32 getnetent.3 getnetbyname.3 getnetent.3 setnetent.3 54 getnetent.3 getnetbyname.3 getnetent.3 setnetent.3
33MLINKS+=getprotoent.3 endprotoent.3 getprotoent.3 getprotobyname.3 \ 55MLINKS+=getprotoent.3 endprotoent.3 getprotoent.3 getprotobyname.3 \
34 getprotoent.3 getprotobynumber.3 getprotoent.3 setprotoent.3 56 getprotoent.3 getprotobynumber.3 getprotoent.3 setprotoent.3 \
57 getprotoent.3 getprotoent_r.3 getprotoent.3 getprotobyname_r.3 \
58 getprotoent.3 getprotobynumber_r.3 getprotoent.3 setprotoent_r.3 \
59 getprotoent.3 endprotoent_r.3
35MLINKS+=getservent.3 endservent.3 getservent.3 getservbyname.3 \ 60MLINKS+=getservent.3 endservent.3 getservent.3 getservbyname.3 \
36 getservent.3 getservbyport.3 getservent.3 setservent.3 61 getservent.3 getservbyport.3 getservent.3 setservent.3 \
62 getservent.3 getservent_r.3 getservent.3 getservbyname_r.3 \
63 getservent.3 getservbyport_r.3 getservent.3 setservent_r.3 \
64 getservent.3 endservent_r.3
65MLINKS+= if_indextoname.3 if_nametoindex.3 if_indextoname.3 if_nameindex.3 \
66 if_indextoname.3 if_freenameindex.3
37MLINKS+=inet.3 addr.3 inet.3 inet_addr.3 inet.3 inet_aton.3 \ 67MLINKS+=inet.3 addr.3 inet.3 inet_addr.3 inet.3 inet_aton.3 \
38 inet.3 inet_lnaof.3 inet.3 inet_makeaddr.3 inet.3 inet_netof.3 \ 68 inet.3 inet_lnaof.3 inet.3 inet_makeaddr.3 inet.3 inet_netof.3 \
39 inet.3 inet_network.3 inet.3 inet_ntoa.3 inet.3 network.3 \ 69 inet.3 inet_network.3 inet.3 inet_ntoa.3 inet.3 network.3 \
40 inet.3 ntoa.3 70 inet.3 ntoa.3 inet.3 inet_ntop.3 inet.3 inet_pton.3
41MLINKS+=linkaddr.3 linkntoa.3 71MLINKS+=inet_net.3 inet_net_ntop.3 inet_net.3 inet_net_pton.3
42MLINKS+=ns.3 ns_addr.3 ns.3 ns_ntoa.3 72MLINKS+=link_addr.3 link_ntoa.3
43MLINKS+=rcmd.3 iruserok.3 rcmd.3 rresvport.3 rcmd.3 ruserok.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
44MLINKS+=resolver.3 dn_comp.3 resolver.3 dn_expand.3 resolver.3 res_init.3 \ 75MLINKS+=resolver.3 dn_comp.3 resolver.3 dn_expand.3 resolver.3 res_init.3 \
45 resolver.3 res_mkquery.3 resolver.3 res_send.3 resolver.3 res_query.3 \ 76 resolver.3 res_mkquery.3 resolver.3 res_send.3 resolver.3 res_query.3 \
46 resolver.3 res_search.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
91MLINKS+=inet6_opt_init.3 inet6_opt_append.3 \
92 inet6_opt_init.3 inet6_opt_finish.3 \
93 inet6_opt_init.3 inet6_opt_set_val.3 \
94 inet6_opt_init.3 inet6_opt_next.3 \
95 inet6_opt_init.3 inet6_opt_find.3 \
96 inet6_opt_init.3 inet6_opt_get_val.3
97MLINKS+=inet6_rth_space.3 inet6_rth_init.3 \
98 inet6_rth_space.3 inet6_rth_add.3 \
99 inet6_rth_space.3 inet6_rth_reverse.3 \
100 inet6_rth_space.3 inet6_rth_segments.3 \
101 inet6_rth_space.3 inet6_rth_getaddr.3 \
diff --git a/src/lib/libc/net/base64.c b/src/lib/libc/net/base64.c
new file mode 100644
index 0000000000..d432c48d5c
--- /dev/null
+++ b/src/lib/libc/net/base64.c
@@ -0,0 +1,308 @@
1/* $OpenBSD: base64.c,v 1.5 2006/10/21 09:55:03 otto 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
59static const char Base64[] =
60 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
61static const char Pad64 = '=';
62
63/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
64 The following encoding technique is taken from RFC 1521 by Borenstein
65 and Freed. It is reproduced here in a slightly edited form for
66 convenience.
67
68 A 65-character subset of US-ASCII is used, enabling 6 bits to be
69 represented per printable character. (The extra 65th character, "=",
70 is used to signify a special processing function.)
71
72 The encoding process represents 24-bit groups of input bits as output
73 strings of 4 encoded characters. Proceeding from left to right, a
74 24-bit input group is formed by concatenating 3 8-bit input groups.
75 These 24 bits are then treated as 4 concatenated 6-bit groups, each
76 of which is translated into a single digit in the base64 alphabet.
77
78 Each 6-bit group is used as an index into an array of 64 printable
79 characters. The character referenced by the index is placed in the
80 output string.
81
82 Table 1: The Base64 Alphabet
83
84 Value Encoding Value Encoding Value Encoding Value Encoding
85 0 A 17 R 34 i 51 z
86 1 B 18 S 35 j 52 0
87 2 C 19 T 36 k 53 1
88 3 D 20 U 37 l 54 2
89 4 E 21 V 38 m 55 3
90 5 F 22 W 39 n 56 4
91 6 G 23 X 40 o 57 5
92 7 H 24 Y 41 p 58 6
93 8 I 25 Z 42 q 59 7
94 9 J 26 a 43 r 60 8
95 10 K 27 b 44 s 61 9
96 11 L 28 c 45 t 62 +
97 12 M 29 d 46 u 63 /
98 13 N 30 e 47 v
99 14 O 31 f 48 w (pad) =
100 15 P 32 g 49 x
101 16 Q 33 h 50 y
102
103 Special processing is performed if fewer than 24 bits are available
104 at the end of the data being encoded. A full encoding quantum is
105 always completed at the end of a quantity. When fewer than 24 input
106 bits are available in an input group, zero bits are added (on the
107 right) to form an integral number of 6-bit groups. Padding at the
108 end of the data is performed using the '=' character.
109
110 Since all base64 input is an integral number of octets, only the
111 -------------------------------------------------
112 following cases can arise:
113
114 (1) the final quantum of encoding input is an integral
115 multiple of 24 bits; here, the final unit of encoded
116 output will be an integral multiple of 4 characters
117 with no "=" padding,
118 (2) the final quantum of encoding input is exactly 8 bits;
119 here, the final unit of encoded output will be two
120 characters followed by two "=" padding characters, or
121 (3) the final quantum of encoding input is exactly 16 bits;
122 here, the final unit of encoded output will be three
123 characters followed by one "=" padding character.
124 */
125
126int
127b64_ntop(src, srclength, target, targsize)
128 u_char const *src;
129 size_t srclength;
130 char *target;
131 size_t targsize;
132{
133 size_t datalength = 0;
134 u_char input[3];
135 u_char output[4];
136 int i;
137
138 while (2 < srclength) {
139 input[0] = *src++;
140 input[1] = *src++;
141 input[2] = *src++;
142 srclength -= 3;
143
144 output[0] = input[0] >> 2;
145 output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
146 output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
147 output[3] = input[2] & 0x3f;
148
149 if (datalength + 4 > targsize)
150 return (-1);
151 target[datalength++] = Base64[output[0]];
152 target[datalength++] = Base64[output[1]];
153 target[datalength++] = Base64[output[2]];
154 target[datalength++] = Base64[output[3]];
155 }
156
157 /* Now we worry about padding. */
158 if (0 != srclength) {
159 /* Get what's left. */
160 input[0] = input[1] = input[2] = '\0';
161 for (i = 0; i < srclength; i++)
162 input[i] = *src++;
163
164 output[0] = input[0] >> 2;
165 output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
166 output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
167
168 if (datalength + 4 > targsize)
169 return (-1);
170 target[datalength++] = Base64[output[0]];
171 target[datalength++] = Base64[output[1]];
172 if (srclength == 1)
173 target[datalength++] = Pad64;
174 else
175 target[datalength++] = Base64[output[2]];
176 target[datalength++] = Pad64;
177 }
178 if (datalength >= targsize)
179 return (-1);
180 target[datalength] = '\0'; /* Returned value doesn't count \0. */
181 return (datalength);
182}
183
184/* skips all whitespace anywhere.
185 converts characters, four at a time, starting at (or after)
186 src from base - 64 numbers into three 8 bit bytes in the target area.
187 it returns the number of data bytes stored at the target, or -1 on error.
188 */
189
190int
191b64_pton(src, target, targsize)
192 char const *src;
193 u_char *target;
194 size_t targsize;
195{
196 int tarindex, state, ch;
197 char *pos;
198
199 state = 0;
200 tarindex = 0;
201
202 while ((ch = *src++) != '\0') {
203 if (isspace(ch)) /* Skip whitespace anywhere. */
204 continue;
205
206 if (ch == Pad64)
207 break;
208
209 pos = strchr(Base64, ch);
210 if (pos == 0) /* A non-base64 character. */
211 return (-1);
212
213 switch (state) {
214 case 0:
215 if (target) {
216 if (tarindex >= targsize)
217 return (-1);
218 target[tarindex] = (pos - Base64) << 2;
219 }
220 state = 1;
221 break;
222 case 1:
223 if (target) {
224 if (tarindex + 1 >= targsize)
225 return (-1);
226 target[tarindex] |= (pos - Base64) >> 4;
227 target[tarindex+1] = ((pos - Base64) & 0x0f)
228 << 4 ;
229 }
230 tarindex++;
231 state = 2;
232 break;
233 case 2:
234 if (target) {
235 if (tarindex + 1 >= targsize)
236 return (-1);
237 target[tarindex] |= (pos - Base64) >> 2;
238 target[tarindex+1] = ((pos - Base64) & 0x03)
239 << 6;
240 }
241 tarindex++;
242 state = 3;
243 break;
244 case 3:
245 if (target) {
246 if (tarindex >= targsize)
247 return (-1);
248 target[tarindex] |= (pos - Base64);
249 }
250 tarindex++;
251 state = 0;
252 break;
253 }
254 }
255
256 /*
257 * We are done decoding Base-64 chars. Let's see if we ended
258 * on a byte boundary, and/or with erroneous trailing characters.
259 */
260
261 if (ch == Pad64) { /* We got a pad char. */
262 ch = *src++; /* Skip it, get next. */
263 switch (state) {
264 case 0: /* Invalid = in first position */
265 case 1: /* Invalid = in second position */
266 return (-1);
267
268 case 2: /* Valid, means one byte of info */
269 /* Skip any number of spaces. */
270 for (; ch != '\0'; ch = *src++)
271 if (!isspace(ch))
272 break;
273 /* Make sure there is another trailing = sign. */
274 if (ch != Pad64)
275 return (-1);
276 ch = *src++; /* Skip the = */
277 /* Fall through to "single trailing =" case. */
278 /* FALLTHROUGH */
279
280 case 3: /* Valid, means two bytes of info */
281 /*
282 * We know this char is an =. Is there anything but
283 * whitespace after it?
284 */
285 for (; ch != '\0'; ch = *src++)
286 if (!isspace(ch))
287 return (-1);
288
289 /*
290 * Now make sure for cases 2 and 3 that the "extra"
291 * bits that slopped past the last full byte were
292 * zeros. If we don't check them, they become a
293 * subliminal channel.
294 */
295 if (target && target[tarindex] != 0)
296 return (-1);
297 }
298 } else {
299 /*
300 * We ended by seeing the end of the string. Make sure we
301 * have no partial bytes lying around.
302 */
303 if (state != 0)
304 return (-1);
305 }
306
307 return (tarindex);
308}
diff --git a/src/lib/libc/net/byteorder.3 b/src/lib/libc/net/byteorder.3
index 701a69f688..6625ea1442 100644
--- a/src/lib/libc/net/byteorder.3
+++ b/src/lib/libc/net/byteorder.3
@@ -1,4 +1,4 @@
1.\" $NetBSD: byteorder.3,v 1.3 1995/02/25 06:20:27 cgd Exp $ 1.\" $OpenBSD: byteorder.3,v 1.16 2009/03/17 21:33:04 jmc Exp $
2.\" 2.\"
3.\" Copyright (c) 1983, 1991, 1993 3.\" Copyright (c) 1983, 1991, 1993
4.\" The Regents of the University of California. All rights reserved. 4.\" The Regents of the University of California. All rights reserved.
@@ -11,11 +11,7 @@
11.\" 2. Redistributions in binary form must reproduce the above copyright 11.\" 2. Redistributions in binary form must reproduce the above copyright
12.\" notice, this list of conditions and the following disclaimer in the 12.\" notice, this list of conditions and the following disclaimer in the
13.\" documentation and/or other materials provided with the distribution. 13.\" documentation and/or other materials provided with the distribution.
14.\" 3. All advertising materials mentioning features or use of this software 14.\" 3. Neither the name of the University nor the names of its contributors
15.\" must display the following acknowledgement:
16.\" This product includes software developed by the University of
17.\" California, Berkeley and its contributors.
18.\" 4. Neither the name of the University nor the names of its contributors
19.\" may be used to endorse or promote products derived from this software 15.\" may be used to endorse or promote products derived from this software
20.\" without specific prior written permission. 16.\" without specific prior written permission.
21.\" 17.\"
@@ -31,48 +27,180 @@
31.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32.\" SUCH DAMAGE. 28.\" SUCH DAMAGE.
33.\" 29.\"
34.\" @(#)byteorder.3 8.1 (Berkeley) 6/4/93 30.Dd $Mdocdate: March 17 2009 $
35.\"
36.Dd June 4, 1993
37.Dt BYTEORDER 3 31.Dt BYTEORDER 3
38.Os BSD 4.2 32.Os
39.Sh NAME 33.Sh NAME
40.Nm htonl , 34.Nm htonl ,
41.Nm htons , 35.Nm htons ,
42.Nm ntohl , 36.Nm ntohl ,
43.Nm ntohs 37.Nm ntohs ,
44.Nd convert values between host and network byte order 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
45.Sh SYNOPSIS 54.Sh SYNOPSIS
46.Fd #include <sys/param.h> 55.Fd #include <sys/types.h>
47.Ft u_long 56.Ft u_int32_t
48.Fn htonl "u_long hostlong" 57.Fn htonl "u_int32_t host32"
49.Ft u_short 58.Ft u_int16_t
50.Fn htons "u_short hostshort" 59.Fn htons "u_int16_t host16"
51.Ft u_long 60.Ft u_int32_t
52.Fn ntohl "u_long netlong" 61.Fn ntohl "u_int32_t net32"
53.Ft u_short 62.Ft u_int16_t
54.Fn ntohs "u_short netshort" 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_int64_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"
55.Sh DESCRIPTION 94.Sh DESCRIPTION
56These routines convert 16 and 32 bit quantities between network 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
57byte order and host byte order. 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.
58On machines which have a byte order which is the same as the network 159On machines which have a byte order which is the same as the network
59order, routines are defined as null macros. 160order, routines are defined as null macros.
60.Pp 161.Pp
61These routines are most often used in conjunction with Internet 162The functions involving either
62addresses and ports as returned by 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
63.Xr gethostbyname 3 181.Xr gethostbyname 3
64and 182and
65.Xr getservent 3 . 183.Xr getservent 3 .
66.Sh SEE ALSO 184.Sh SEE ALSO
67.Xr gethostbyname 3 , 185.Xr gethostbyname 3 ,
68.Xr getservent 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.
69.Sh HISTORY 198.Sh HISTORY
70The 199The
71.Nm byteorder 200.Nm byteorder
72functions appeared in 201functions appeared in
73.Bx 4.2 . 202.Bx 4.2 .
74.Sh BUGS 203.Sh BUGS
75On the 204On the vax, alpha, i386, and some mips architectures,
76.Tn VAX 205bytes are handled backwards from most everyone else in the world.
77bytes are handled backwards from most everyone else in 206This is not expected to be fixed in the near future.
78the world. This 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
index 81e6c65935..041ee981ec 100644
--- a/src/lib/libc/net/ethers.3
+++ b/src/lib/libc/net/ethers.3
@@ -1,65 +1,87 @@
1.\" $OpenBSD: ethers.3,v 1.21 2011/04/19 22:38:26 matthew Exp $
1.\" 2.\"
2.\" Written by roland@frob.com. Public domain. 3.\" Written by roland@frob.com. Public domain.
3.\" 4.\"
4.Dd December 16, 1993 5.Dd $Mdocdate: April 19 2011 $
5.Dt ETHERS 3 6.Dt ETHERS 3
6.Os NetBSD 7.Os
7.Sh NAME 8.Sh NAME
9.Nm ether_aton ,
8.Nm ether_ntoa , 10.Nm ether_ntoa ,
9.Nm ether_addr ,
10.Nm ether_ntohost , 11.Nm ether_ntohost ,
11.Nm ether_hostton , 12.Nm ether_hostton ,
12.Nm ether_line , 13.Nm ether_line
13.Nd get ethers entry 14.Nd get ethers entry
14.Sh SYNOPSIS 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>
15.Fd #include <netinet/if_ether.h> 20.Fd #include <netinet/if_ether.h>
16.Ft char * 21.Ft char *
17.Fn ether_ntoa "struct ether_addr *e" 22.Fn ether_ntoa "struct ether_addr *e"
18.Ft struct ether_addr * 23.Ft struct ether_addr *
19.Fn ether_aton "char *s" 24.Fn ether_aton "const char *s"
25.Ft int
20.Fn ether_ntohost "char *hostname" "struct ether_addr *e" 26.Fn ether_ntohost "char *hostname" "struct ether_addr *e"
21.Fn ether_hostton "char *hostname" "struct ether_addr *e" 27.Ft int
22.Fn ether_line "char *l" "struct ether_addr *e" "char *hostname" 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"
23.Sh DESCRIPTION 31.Sh DESCRIPTION
24Ethernet addresses are represented by the 32Ethernet addresses are represented by the
25following structure: 33following structure:
26.Bd -literal -offset indent 34.Bd -literal -offset indent
27struct ether_addr { 35struct ether_addr {
28 u_char ether_addr_octet[6]; 36 u_int8_t ether_addr_octet[6];
29}; 37};
30.Ed 38.Ed
31.Pp 39.Pp
32The 40The
33.Fn ether_ntoa 41.Fn ether_ntoa
34function converts this structure into an ASCII string of the form 42function converts this structure into an
35``xx:xx:xx:xx:xx:xx'', consisting of 6 hexadecimal numbers separated 43.Tn ASCII
36by colons. It returns a pointer to a static buffer that is reused for 44string of the form
37each call. 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.
38The 49The
39.Fn ether_aton 50.Fn ether_aton
40converts an ASCII string of the same form and to a structure 51converts an
41containing the 6 octets of the address. It returns a pointer to a 52.Tn ASCII
42static structure that is reused for each call. 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.Fn ether_aton
57will return NULL if the string does not represent a valid address.
43.Pp 58.Pp
44The 59The
45.Fn ether_ntohost 60.Fn ether_ntohost
46and 61and
47.Fn ether_hostton 62.Fn ether_hostton
48functions interrogate the data base mapping host names to Ethernet 63functions interrogate the database mapping host names to Ethernet
49addresses, 64addresses,
50.Pa /etc/ethers . 65.Pa /etc/ethers .
51The 66The
52.Fn ether_ntohost 67.Fn ether_ntohost
53function looks up the given Ethernet address and writes the associated 68function looks up the given Ethernet address and writes the associated
54host name into the character buffer passed. 69host name into the character buffer passed.
70This buffer should be
71.Dv MAXHOSTNAMELEN
72characters in size.
55The 73The
56.Fn ether_hostton 74.Fn ether_hostton
57function looks up the given host name and writes the associated 75function looks up the given host name and writes the associated
58Ethernet address into the structure passed. Both functions return 76Ethernet address into the structure passed.
59zero if they find the requested host name or address, and -1 if not. 77Both functions return
78zero if they find the requested host name or address, and \-1 if not.
79.Pp
60Each call reads 80Each call reads
61.Pa /etc/ethers 81.Pa /etc/ethers
62from the beginning; if a + appears alone on a line in the file, then 82from the beginning; if a
83.Ql +
84appears alone on a line in the file, then
63.Fn ether_hostton 85.Fn ether_hostton
64will consult the 86will consult the
65.Pa ethers.byname 87.Pa ethers.byname
@@ -73,9 +95,13 @@ The
73.Fn ether_line 95.Fn ether_line
74function parses a line from the 96function parses a line from the
75.Pa /etc/ethers 97.Pa /etc/ethers
76file and fills in the passed ``struct ether_addr'' and character 98file and fills in the passed
77buffer with the Ethernet address and host name on the line. It 99.Li struct ether_addr
78returns zero if the line was successfully parsed and -1 if not. 100and character buffer with the Ethernet address and host name on the line.
101It returns zero if the line was successfully parsed and \-1 if not.
102The character buffer should be
103.Dv MAXHOSTNAMELEN
104characters in size.
79.Sh FILES 105.Sh FILES
80.Bl -tag -width /etc/ethers -compact 106.Bl -tag -width /etc/ethers -compact
81.It Pa /etc/ethers 107.It Pa /etc/ethers
@@ -91,12 +117,8 @@ The
91and 117and
92.Fn ether_line 118.Fn ether_line
93functions were adopted from SunOS and appeared in 119functions were adopted from SunOS and appeared in
94NetBSD 0.9b. 120.Nx 0.9b .
95.Sh BUGS 121.Sh BUGS
96The data space used by these functions is static; if future use 122The data space used by these functions is static; if future use
97requires the data, it should be copied before any subsequent calls to 123requires the data, it should be copied before any subsequent calls to
98these functions overwrite it. There is no way to restrict how many 124these functions overwrite it.
99character will be written into the host name buffer passed. A very
100long line in
101.Pa /etc/ethers
102could overflow your buffer.
diff --git a/src/lib/libc/net/ethers.c b/src/lib/libc/net/ethers.c
index 0f32b9b71b..d4243ff1da 100644
--- a/src/lib/libc/net/ethers.c
+++ b/src/lib/libc/net/ethers.c
@@ -1,10 +1,25 @@
1/* $NetBSD: ethers.c,v 1.5 1995/02/25 06:20:28 cgd Exp $ */ 1/* $OpenBSD: ethers.c,v 1.20 2005/08/06 20:30:03 espie Exp $ */
2 2
3/* 3/*
4 * ethers(3N) a la Sun. 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.
5 * 9 *
6 * Written by Roland McGrath <roland@frob.com> 10/14/93. 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
7 * Public domain. 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>
8 */ 23 */
9 24
10#include <sys/types.h> 25#include <sys/types.h>
@@ -18,57 +33,77 @@
18#include <stdio.h> 33#include <stdio.h>
19#include <stdlib.h> 34#include <stdlib.h>
20#include <string.h> 35#include <string.h>
36#include <ctype.h>
37#ifdef YP
38#include <rpcsvc/ypclnt.h>
39#endif
21 40
22#ifndef _PATH_ETHERS 41#ifndef _PATH_ETHERS
23#define _PATH_ETHERS "/etc/ethers" 42#define _PATH_ETHERS "/etc/ethers"
24#endif 43#endif
25 44
45static char * _ether_aton(const char *, struct ether_addr *);
46
26char * 47char *
27ether_ntoa(e) 48ether_ntoa(struct ether_addr *e)
28 struct ether_addr *e;
29{ 49{
30 static char a[] = "xx:xx:xx:xx:xx:xx"; 50 static char a[] = "xx:xx:xx:xx:xx:xx";
31 51
32 sprintf(a, "%02x:%02x:%02x:%02x:%02x:%02x", 52 (void)snprintf(a, sizeof a, "%02x:%02x:%02x:%02x:%02x:%02x",
33 e->ether_addr_octet[0], e->ether_addr_octet[1], 53 e->ether_addr_octet[0], e->ether_addr_octet[1],
34 e->ether_addr_octet[2], e->ether_addr_octet[3], 54 e->ether_addr_octet[2], e->ether_addr_octet[3],
35 e->ether_addr_octet[4], e->ether_addr_octet[5]); 55 e->ether_addr_octet[4], e->ether_addr_octet[5]);
36 return a; 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);
37} 83}
38 84
39struct ether_addr * 85struct ether_addr *
40ether_aton(s) 86ether_aton(const char *s)
41 char *s;
42{ 87{
43 static struct ether_addr n; 88 static struct ether_addr n;
44 u_int i[6]; 89
45 90 return (_ether_aton(s, &n) ? &n : NULL);
46 if (sscanf(s, " %x:%x:%x:%x:%x:%x ", &i[0], &i[1],
47 &i[2], &i[3], &i[4], &i[5]) == 6) {
48 n.ether_addr_octet[0] = (u_char)i[0];
49 n.ether_addr_octet[1] = (u_char)i[1];
50 n.ether_addr_octet[2] = (u_char)i[2];
51 n.ether_addr_octet[3] = (u_char)i[3];
52 n.ether_addr_octet[4] = (u_char)i[4];
53 n.ether_addr_octet[5] = (u_char)i[5];
54 return &n;
55 }
56 return NULL;
57} 91}
58 92
59ether_ntohost(hostname, e) 93int
60 char *hostname; 94ether_ntohost(char *hostname, struct ether_addr *e)
61 struct ether_addr *e;
62{ 95{
63 FILE *f; 96 FILE *f;
64 char buf[BUFSIZ]; 97 char buf[BUFSIZ+1], *p;
98 size_t len;
65 struct ether_addr try; 99 struct ether_addr try;
66
67#ifdef YP 100#ifdef YP
68 char trybuf[sizeof "xx:xx:xx:xx:xx:xx"]; 101 char trybuf[sizeof("xx:xx:xx:xx:xx:xx")];
69 int trylen; 102 int trylen;
103#endif
70 104
71 sprintf(trybuf, "%x:%x:%x:%x:%x:%x", 105#ifdef YP
106 snprintf(trybuf, sizeof trybuf, "%x:%x:%x:%x:%x:%x",
72 e->ether_addr_octet[0], e->ether_addr_octet[1], 107 e->ether_addr_octet[0], e->ether_addr_octet[1],
73 e->ether_addr_octet[2], e->ether_addr_octet[3], 108 e->ether_addr_octet[2], e->ether_addr_octet[3],
74 e->ether_addr_octet[4], e->ether_addr_octet[5]); 109 e->ether_addr_octet[4], e->ether_addr_octet[5]);
@@ -76,12 +111,19 @@ ether_ntohost(hostname, e)
76#endif 111#endif
77 112
78 f = fopen(_PATH_ETHERS, "r"); 113 f = fopen(_PATH_ETHERS, "r");
79 if (f==NULL) 114 if (f == NULL)
80 return -1; 115 return (-1);
81 while (fgets(buf, sizeof buf, f)) { 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';
82#ifdef YP 124#ifdef YP
83 /* A + in the file means try YP now. */ 125 /* A + in the file means try YP now. */
84 if (!strncmp(buf, "+\n", sizeof buf)) { 126 if (!strncmp(buf, "+\n", sizeof(buf))) {
85 char *ypbuf, *ypdom; 127 char *ypbuf, *ypdom;
86 int ypbuflen; 128 int ypbuflen;
87 129
@@ -93,42 +135,49 @@ ether_ntohost(hostname, e)
93 if (ether_line(ypbuf, &try, hostname) == 0) { 135 if (ether_line(ypbuf, &try, hostname) == 0) {
94 free(ypbuf); 136 free(ypbuf);
95 (void)fclose(f); 137 (void)fclose(f);
96 return 0; 138 return (0);
97 } 139 }
98 free(ypbuf); 140 free(ypbuf);
99 continue; 141 continue;
100 } 142 }
101#endif 143#endif
102 if (ether_line(buf, &try, hostname) == 0 && 144 if (ether_line(buf, &try, hostname) == 0 &&
103 bcmp((char *)&try, (char *)e, sizeof try) == 0) { 145 memcmp((void *)&try, (void *)e, sizeof(try)) == 0) {
104 (void)fclose(f); 146 (void)fclose(f);
105 return 0; 147 return (0);
106 } 148 }
107 } 149 }
108 (void)fclose(f); 150 (void)fclose(f);
109 errno = ENOENT; 151 errno = ENOENT;
110 return -1; 152 return (-1);
111} 153}
112 154
113ether_hostton(hostname, e) 155int
114 char *hostname; 156ether_hostton(const char *hostname, struct ether_addr *e)
115 struct ether_addr *e;
116{ 157{
117 FILE *f; 158 FILE *f;
118 char buf[BUFSIZ]; 159 char buf[BUFSIZ+1], *p;
119 char try[MAXHOSTNAMELEN]; 160 char try[MAXHOSTNAMELEN];
161 size_t len;
120#ifdef YP 162#ifdef YP
121 int hostlen = strlen(hostname); 163 int hostlen = strlen(hostname);
122#endif 164#endif
123 165
124 f = fopen(_PATH_ETHERS, "r"); 166 f = fopen(_PATH_ETHERS, "r");
125 if (f==NULL) 167 if (f==NULL)
126 return -1; 168 return (-1);
127 169
128 while (fgets(buf, sizeof buf, f)) { 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';
129#ifdef YP 178#ifdef YP
130 /* A + in the file means try YP now. */ 179 /* A + in the file means try YP now. */
131 if (!strncmp(buf, "+\n", sizeof buf)) { 180 if (!strncmp(buf, "+\n", sizeof(buf))) {
132 char *ypbuf, *ypdom; 181 char *ypbuf, *ypdom;
133 int ypbuflen; 182 int ypbuflen;
134 183
@@ -140,7 +189,7 @@ ether_hostton(hostname, e)
140 if (ether_line(ypbuf, e, try) == 0) { 189 if (ether_line(ypbuf, e, try) == 0) {
141 free(ypbuf); 190 free(ypbuf);
142 (void)fclose(f); 191 (void)fclose(f);
143 return 0; 192 return (0);
144 } 193 }
145 free(ypbuf); 194 free(ypbuf);
146 continue; 195 continue;
@@ -148,31 +197,36 @@ ether_hostton(hostname, e)
148#endif 197#endif
149 if (ether_line(buf, e, try) == 0 && strcmp(hostname, try) == 0) { 198 if (ether_line(buf, e, try) == 0 && strcmp(hostname, try) == 0) {
150 (void)fclose(f); 199 (void)fclose(f);
151 return 0; 200 return (0);
152 } 201 }
153 } 202 }
154 (void)fclose(f); 203 (void)fclose(f);
155 errno = ENOENT; 204 errno = ENOENT;
156 return -1; 205 return (-1);
157} 206}
158 207
159ether_line(l, e, hostname) 208int
160 char *l; 209ether_line(const char *line, struct ether_addr *e, char *hostname)
161 struct ether_addr *e;
162 char *hostname;
163{ 210{
164 u_int i[6]; 211 char *p;
165 212 size_t n;
166 if (sscanf(l, " %x:%x:%x:%x:%x:%x %s\n", &i[0], &i[1], 213
167 &i[2], &i[3], &i[4], &i[5], hostname) == 7) { 214 /* Parse "xx:xx:xx:xx:xx:xx" */
168 e->ether_addr_octet[0] = (u_char)i[0]; 215 if ((p = _ether_aton(line, e)) == NULL || (*p != ' ' && *p != '\t'))
169 e->ether_addr_octet[1] = (u_char)i[1]; 216 goto bad;
170 e->ether_addr_octet[2] = (u_char)i[2]; 217
171 e->ether_addr_octet[3] = (u_char)i[3]; 218 /* Now get the hostname */
172 e->ether_addr_octet[4] = (u_char)i[4]; 219 while (isspace(*p))
173 e->ether_addr_octet[5] = (u_char)i[5]; 220 p++;
174 return 0; 221 if (*p == '\0')
175 } 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:
176 errno = EINVAL; 230 errno = EINVAL;
177 return -1; 231 return (-1);
178} 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..6ce94e30a1
--- /dev/null
+++ b/src/lib/libc/net/gai_strerror.3
@@ -0,0 +1,95 @@
1.\" $OpenBSD: gai_strerror.3,v 1.7 2009/06/02 16:47:50 jasper 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 $Mdocdate: June 2 2009 $
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_OVERFLOW
72argument buffer overflow
73.It Dv EAI_PROTOCOL
74resolved protocol is unknown
75.It Dv EAI_SERVICE
76.Fa servname
77not supported for
78.Fa ai_socktype
79.It Dv EAI_SOCKTYPE
80.Fa ai_socktype
81not supported
82.It Dv EAI_SYSTEM
83system error returned in
84.Va errno
85.El
86.Sh RETURN VALUES
87.Fn gai_strerror
88returns a pointer to the error message string corresponding to
89.Fa ecode .
90If
91.Fa ecode
92is out of range, an implementation-specific error message string is returned.
93.Sh SEE ALSO
94.Xr getaddrinfo 3 ,
95.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..f4126413f8
--- /dev/null
+++ b/src/lib/libc/net/gai_strerror.c
@@ -0,0 +1,78 @@
1/* $OpenBSD: gai_strerror.c,v 1.7 2009/06/02 16:47:50 jasper 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 case EAI_OVERFLOW:
74 return "argument buffer overflow";
75 default:
76 return "unknown/invalid error";
77 }
78}
diff --git a/src/lib/libc/net/getaddrinfo.3 b/src/lib/libc/net/getaddrinfo.3
new file mode 100644
index 0000000000..da6e64683f
--- /dev/null
+++ b/src/lib/libc/net/getaddrinfo.3
@@ -0,0 +1,470 @@
1.\" $OpenBSD: getaddrinfo.3,v 1.48 2011/04/05 00:46:06 matthew 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 $Mdocdate: April 5 2011 $
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 host name in the
130.Fa ai_canonname
131element of the first
132.Li addrinfo
133structure returned.
134.It Dv AI_FQDN
135If the
136.Dv AI_FQDN
137bit is set, a successful call to
138.Fn getaddrinfo
139will return a NUL-terminated string containing the fully qualified domain name
140of the specified host name in the
141.Fa ai_canonname
142element of the first
143.Li addrinfo
144structure returned.
145.Pp
146This is different from the
147.Dv AI_CANONNAME
148bit flag that returns the canonical name registered in DNS,
149which may be different from the fully qualified domain name
150that the host name resolved to.
151Only one of the
152.Dv AI_FQDN
153and
154.Dv AI_CANONNAME
155bits can be set.
156.It Dv AI_NUMERICHOST
157If the
158.Dv AI_NUMERICHOST
159bit is set, it indicates that
160.Fa hostname
161should be treated as a numeric string defining an IPv4 or IPv6 address
162and no name resolution should be attempted.
163.It Dv AI_NUMERICSERV
164If the
165.Dv AI_NUMERICSERV
166bit is set, it indicates that
167.Fa servname
168should be treated as a numeric port string
169and no service name resolution should be attempted.
170.It Dv AI_PASSIVE
171If the
172.Dv AI_PASSIVE
173bit is set it indicates that the returned socket address structure
174is intended for use in a call to
175.Xr bind 2 .
176In this case, if the
177.Fa hostname
178argument is the null pointer, then the IP address portion of the
179socket address structure will be set to
180.Dv INADDR_ANY
181for an IPv4 address or
182.Dv IN6ADDR_ANY_INIT
183for an IPv6 address.
184.Pp
185If the
186.Dv AI_PASSIVE
187bit is not set, the returned socket address structure will be ready
188for use in a call to
189.Xr connect 2
190for a connection-oriented protocol or
191.Xr connect 2 ,
192.Xr sendto 2 ,
193or
194.Xr sendmsg 2
195if a connectionless protocol was chosen.
196The
197.Tn IP
198address portion of the socket address structure will be set to the
199loopback address if
200.Fa hostname
201is the null pointer and
202.Dv AI_PASSIVE
203is not set.
204.El
205.El
206.Pp
207All other elements of the
208.Li addrinfo
209structure passed via
210.Fa hints
211must be zero or the null pointer.
212.Pp
213If
214.Fa hints
215is the null pointer,
216.Fn getaddrinfo
217behaves as if the caller provided a
218.Li struct addrinfo
219with
220.Fa ai_family
221set to
222.Dv PF_UNSPEC
223and all other elements set to zero or
224.Dv NULL .
225.Pp
226After a successful call to
227.Fn getaddrinfo ,
228.Fa *res
229is a pointer to a linked list of one or more
230.Li addrinfo
231structures.
232The list can be traversed by following the
233.Fa ai_next
234pointer in each
235.Li addrinfo
236structure until a null pointer is encountered.
237The three members
238.Fa ai_family ,
239.Fa ai_socktype ,
240and
241.Fa ai_protocol
242in each returned
243.Li addrinfo
244structure are suitable for a call to
245.Xr socket 2 .
246For each
247.Li addrinfo
248structure in the list, the
249.Fa ai_addr
250member points to a filled-in socket address structure of length
251.Fa ai_addrlen .
252.Pp
253This implementation of
254.Fn getaddrinfo
255allows numeric IPv6 address notation with scope identifier,
256as documented in chapter 11 of draft-ietf-ipv6-scoping-arch-02.txt.
257By appending the percent character and scope identifier to addresses,
258one can fill the
259.Li sin6_scope_id
260field for addresses.
261This would make management of scoped addresses easier
262and allows cut-and-paste input of scoped addresses.
263.Pp
264At this moment the code supports only link-local addresses with the format.
265The scope identifier is hardcoded to the name of the hardware interface
266associated
267with the link
268.Po
269such as
270.Li ne0
271.Pc .
272An example is
273.Dq Li fe80::1%ne0 ,
274which means
275.Do
276.Li fe80::1
277on the link associated with the
278.Li ne0
279interface
280.Dc .
281.Pp
282The current implementation assumes a one-to-one relationship between
283the interface and link, which is not necessarily true from the specification.
284.Pp
285All of the information returned by
286.Fn getaddrinfo
287is dynamically allocated: the
288.Li addrinfo
289structures themselves as well as the socket address structures and
290the canonical host name strings included in the
291.Li addrinfo
292structures.
293.Pp
294Memory allocated for the dynamically allocated structures created by
295a successful call to
296.Fn getaddrinfo
297is released by the
298.Fn freeaddrinfo
299function.
300The
301.Fa ai
302pointer should be a
303.Li addrinfo
304structure created by a call to
305.Fn getaddrinfo .
306.Sh RETURN VALUES
307.Fn getaddrinfo
308returns zero on success or one of the error codes listed in
309.Xr gai_strerror 3
310if an error occurs.
311If an error occurs, no memory is allocated by
312.Fn getaddrinfo ,
313therefore it is not necessary to release the
314.Li addrinfo
315structure(s).
316.Sh EXAMPLES
317The following code tries to connect to
318.Dq Li www.kame.net
319service
320.Dq Li www
321via a stream socket.
322It loops through all the addresses available, regardless of address family.
323If the destination resolves to an IPv4 address, it will use an
324.Dv AF_INET
325socket.
326Similarly, if it resolves to IPv6, an
327.Dv AF_INET6
328socket is used.
329Observe that there is no hardcoded reference to a particular address family.
330The code works even if
331.Fn getaddrinfo
332returns addresses that are not IPv4/v6.
333.Bd -literal -offset indent
334struct addrinfo hints, *res, *res0;
335int error;
336int save_errno;
337int s;
338const char *cause = NULL;
339
340memset(&hints, 0, sizeof(hints));
341hints.ai_family = PF_UNSPEC;
342hints.ai_socktype = SOCK_STREAM;
343error = getaddrinfo("www.kame.net", "www", &hints, &res0);
344if (error)
345 errx(1, "%s", gai_strerror(error));
346s = -1;
347for (res = res0; res; res = res->ai_next) {
348 s = socket(res->ai_family, res->ai_socktype,
349 res->ai_protocol);
350 if (s == -1) {
351 cause = "socket";
352 continue;
353 }
354
355 if (connect(s, res->ai_addr, res->ai_addrlen) == -1) {
356 cause = "connect";
357 save_errno = errno;
358 close(s);
359 errno = save_errno;
360 s = -1;
361 continue;
362 }
363
364 break; /* okay we got one */
365}
366if (s == -1)
367 err(1, "%s", cause);
368freeaddrinfo(res0);
369.Ed
370.Pp
371The following example tries to open a wildcard listening socket onto service
372.Dq Li www ,
373for all the address families available.
374.Bd -literal -offset indent
375struct addrinfo hints, *res, *res0;
376int error;
377int save_errno;
378int s[MAXSOCK];
379int nsock;
380const char *cause = NULL;
381
382memset(&hints, 0, sizeof(hints));
383hints.ai_family = PF_UNSPEC;
384hints.ai_socktype = SOCK_STREAM;
385hints.ai_flags = AI_PASSIVE;
386error = getaddrinfo(NULL, "www", &hints, &res0);
387if (error)
388 errx(1, "%s", gai_strerror(error));
389nsock = 0;
390for (res = res0; res && nsock < MAXSOCK; res = res->ai_next) {
391 s[nsock] = socket(res->ai_family, res->ai_socktype,
392 res->ai_protocol);
393 if (s[nsock] == -1) {
394 cause = "socket";
395 continue;
396 }
397
398 if (bind(s[nsock], res->ai_addr, res->ai_addrlen) == -1) {
399 cause = "bind";
400 save_errno = errno;
401 close(s[nsock]);
402 errno = save_errno;
403 continue;
404 }
405 (void) listen(s[nsock], 5);
406
407 nsock++;
408}
409if (nsock == 0)
410 err(1, "%s", cause);
411freeaddrinfo(res0);
412.Ed
413.Sh SEE ALSO
414.Xr bind 2 ,
415.Xr connect 2 ,
416.Xr send 2 ,
417.Xr socket 2 ,
418.Xr gai_strerror 3 ,
419.Xr gethostbyname 3 ,
420.Xr getnameinfo 3 ,
421.Xr getservbyname 3 ,
422.Xr resolver 3 ,
423.Xr hosts 5 ,
424.Xr resolv.conf 5 ,
425.Xr services 5 ,
426.Xr hostname 7 ,
427.Xr named 8
428.Rs
429.%A R. Gilligan
430.%A S. Thomson
431.%A J. Bound
432.%A J. McCann
433.%A W. Stevens
434.%T Basic Socket Interface Extensions for IPv6
435.%R RFC 3493
436.%D February 2003
437.Re
438.Rs
439.%A S. Deering
440.%A B. Haberman
441.%A T. Jinmei
442.%A E. Nordmark
443.%A B. Zill
444.%T "IPv6 Scoped Address Architecture"
445.%R internet draft
446.%N draft-ietf-ipv6-scoping-arch-02.txt
447.%O work in progress material
448.Re
449.Rs
450.%A Craig Metz
451.%T Protocol Independence Using the Sockets API
452.%B "Proceedings of the Freenix Track: 2000 USENIX Annual Technical Conference"
453.%D June 2000
454.Re
455.Sh STANDARDS
456The
457.Fn getaddrinfo
458function is defined by the
459.St -p1003.1g-2000
460draft specification and documented in
461.Dv "RFC 3493" ,
462.Dq Basic Socket Interface Extensions for IPv6 .
463.Pp
464The
465.Dv AI_FQDN
466flag bit first appeared in Windows 7.
467.Sh BUGS
468The implementation of
469.Fn getaddrinfo
470is 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..29cc1f463e
--- /dev/null
+++ b/src/lib/libc/net/getaddrinfo.c
@@ -0,0 +1,1755 @@
1/* $OpenBSD: getaddrinfo.c,v 1.72 2011/04/05 00:46:06 matthew 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 (allows
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 struct addrinfo * _gethtent(const char *, const struct addrinfo *,
221 FILE *);
222static struct addrinfo *_files_getaddrinfo(const char *,
223 const struct addrinfo *);
224
225#ifdef YP
226static struct addrinfo *_yphostent(char *, const struct addrinfo *);
227static struct addrinfo *_yp_getaddrinfo(const char *,
228 const struct addrinfo *);
229#endif
230
231static struct addrinfo *getanswer(const querybuf *, int, const char *, int,
232 const struct addrinfo *);
233static int res_queryN(const char *, struct res_target *);
234static int res_searchN(const char *, struct res_target *);
235static int res_querydomainN(const char *, const char *, struct res_target *);
236static struct addrinfo *_dns_getaddrinfo(const char *, const struct addrinfo *,
237 const struct __res_state *);
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) != 0 ||
313 (hints->ai_flags & (AI_CANONNAME | AI_FQDN)) ==
314 (AI_CANONNAME | AI_FQDN))
315 ERR(EAI_BADFLAGS);
316 switch (hints->ai_family) {
317 case PF_UNSPEC:
318 case PF_INET:
319#ifdef INET6
320 case PF_INET6:
321#endif
322 break;
323 default:
324 ERR(EAI_FAMILY);
325 }
326 memcpy(pai, hints, sizeof(*pai));
327
328 /*
329 * if both socktype/protocol are specified, check if they
330 * are meaningful combination.
331 */
332 if (pai->ai_socktype != ANY && pai->ai_protocol != ANY) {
333 for (ex = explore; ex->e_af >= 0; ex++) {
334 if (pai->ai_family != ex->e_af)
335 continue;
336 if (ex->e_socktype == ANY)
337 continue;
338 if (ex->e_protocol == ANY)
339 continue;
340 if (pai->ai_socktype == ex->e_socktype
341 && pai->ai_protocol != ex->e_protocol) {
342 ERR(EAI_BADHINTS);
343 }
344 }
345 }
346 }
347
348 /*
349 * check for special cases. (1) numeric servname is disallowed if
350 * socktype/protocol are left unspecified. (2) servname is disallowed
351 * for raw and other inet{,6} sockets.
352 */
353 if (MATCH_FAMILY(pai->ai_family, PF_INET, 1)
354#ifdef PF_INET6
355 || MATCH_FAMILY(pai->ai_family, PF_INET6, 1)
356#endif
357 ) {
358 ai0 = *pai; /* backup *pai */
359
360 if (pai->ai_family == PF_UNSPEC) {
361#ifdef PF_INET6
362 pai->ai_family = PF_INET6;
363#else
364 pai->ai_family = PF_INET;
365#endif
366 }
367 error = get_portmatch(pai, servname);
368 if (error)
369 ERR(error);
370
371 *pai = ai0;
372 }
373
374 ai0 = *pai;
375
376 /* NULL hostname, or numeric hostname */
377 for (ex = explore; ex->e_af >= 0; ex++) {
378 *pai = ai0;
379
380 /* PF_UNSPEC entries are prepared for DNS queries only */
381 if (ex->e_af == PF_UNSPEC)
382 continue;
383
384 if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex)))
385 continue;
386 if (!MATCH(pai->ai_socktype, ex->e_socktype, WILD_SOCKTYPE(ex)))
387 continue;
388 if (!MATCH(pai->ai_protocol, ex->e_protocol, WILD_PROTOCOL(ex)))
389 continue;
390
391 if (pai->ai_family == PF_UNSPEC)
392 pai->ai_family = ex->e_af;
393 if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
394 pai->ai_socktype = ex->e_socktype;
395 if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
396 pai->ai_protocol = ex->e_protocol;
397
398 if (hostname == NULL)
399 error = explore_null(pai, servname, &cur->ai_next);
400 else
401 error = explore_numeric_scope(pai, hostname, servname,
402 &cur->ai_next);
403
404 if (error)
405 goto free;
406
407 while (cur && cur->ai_next)
408 cur = cur->ai_next;
409 }
410
411 /*
412 * XXX
413 * If numeric representation of AF1 can be interpreted as FQDN
414 * representation of AF2, we need to think again about the code below.
415 */
416 if (sentinel.ai_next)
417 goto good;
418
419 if (hostname == NULL)
420 ERR(EAI_NODATA);
421 if (pai->ai_flags & AI_NUMERICHOST)
422 ERR(EAI_NONAME);
423
424 /*
425 * hostname as alphabetical name.
426 * we would like to prefer AF_INET6 than AF_INET, so we'll make an
427 * outer loop by AFs.
428 */
429 for (ex = explore; ex->e_af >= 0; ex++) {
430 *pai = ai0;
431
432 /* require exact match for family field */
433 if (pai->ai_family != ex->e_af)
434 continue;
435
436 if (!MATCH(pai->ai_socktype, ex->e_socktype,
437 WILD_SOCKTYPE(ex))) {
438 continue;
439 }
440 if (!MATCH(pai->ai_protocol, ex->e_protocol,
441 WILD_PROTOCOL(ex))) {
442 continue;
443 }
444
445 if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
446 pai->ai_socktype = ex->e_socktype;
447 if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
448 pai->ai_protocol = ex->e_protocol;
449
450 error = explore_fqdn(pai, hostname, servname,
451 &cur->ai_next);
452
453 while (cur && cur->ai_next)
454 cur = cur->ai_next;
455 }
456
457 /* XXX */
458 if (sentinel.ai_next)
459 error = 0;
460
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, _resp);
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 } else {
617 GET_AI(cur->ai_next, afd, afd->a_loopback);
618 /* xxx meaningless?
619 * GET_CANONNAME(cur->ai_next, "localhost");
620 */
621 }
622 GET_PORT(cur->ai_next, servname);
623 cur = cur->ai_next;
624
625 *res = sentinel.ai_next;
626 return 0;
627
628free:
629 if (sentinel.ai_next)
630 freeaddrinfo(sentinel.ai_next);
631 return error;
632}
633
634/*
635 * numeric hostname
636 */
637static int
638explore_numeric(const struct addrinfo *pai, const char *hostname,
639 const char *servname, struct addrinfo **res, const char *canonname)
640{
641 const struct afd *afd;
642 struct addrinfo *cur;
643 struct addrinfo sentinel;
644 int error;
645 char pton[PTON_MAX];
646
647 *res = NULL;
648 sentinel.ai_next = NULL;
649 cur = &sentinel;
650
651 /*
652 * if the servname does not match socktype/protocol, ignore it.
653 */
654 if (get_portmatch(pai, servname) != 0)
655 return 0;
656
657 afd = find_afd(pai->ai_family);
658 if (afd == NULL)
659 return 0;
660
661 switch (afd->a_af) {
662#if 0 /*X/Open spec*/
663 case AF_INET:
664 error = inet_aton(hostname, (struct in_addr *)pton);
665 break;
666#endif
667 default:
668 error = inet_pton(afd->a_af, hostname, pton);
669 break;
670 }
671 if (error == 1) {
672 if (pai->ai_family == afd->a_af ||
673 pai->ai_family == PF_UNSPEC /*?*/) {
674 GET_AI(cur->ai_next, afd, pton);
675 GET_PORT(cur->ai_next, servname);
676 /*
677 * Set the numeric address itself as
678 * the canonical name, based on a
679 * clarification in rfc2553bis-03.
680 */
681 GET_CANONNAME(cur->ai_next, canonname);
682
683 while (cur && cur->ai_next)
684 cur = cur->ai_next;
685 } else
686 ERR(EAI_FAMILY); /*xxx*/
687 }
688
689 *res = sentinel.ai_next;
690 return 0;
691
692free:
693bad:
694 if (sentinel.ai_next)
695 freeaddrinfo(sentinel.ai_next);
696 return error;
697}
698
699/*
700 * numeric hostname with scope
701 */
702static int
703explore_numeric_scope(const struct addrinfo *pai, const char *hostname,
704 const char *servname, struct addrinfo **res)
705{
706#if !defined(SCOPE_DELIMITER) || !defined(INET6)
707 return explore_numeric(pai, hostname, servname, res, hostname);
708#else
709 const struct afd *afd;
710 struct addrinfo *cur;
711 int error;
712 char *cp, *hostname2 = NULL, *scope, *addr;
713 struct sockaddr_in6 *sin6;
714
715 /*
716 * if the servname does not match socktype/protocol, ignore it.
717 */
718 if (get_portmatch(pai, servname) != 0)
719 return 0;
720
721 afd = find_afd(pai->ai_family);
722 if (afd == NULL)
723 return 0;
724
725 if (!afd->a_scoped)
726 return explore_numeric(pai, hostname, servname, res, hostname);
727
728 cp = strchr(hostname, SCOPE_DELIMITER);
729 if (cp == NULL)
730 return explore_numeric(pai, hostname, servname, res, hostname);
731
732 /*
733 * Handle special case of <scoped_address><delimiter><scope id>
734 */
735 hostname2 = strdup(hostname);
736 if (hostname2 == NULL)
737 return EAI_MEMORY;
738 /* terminate at the delimiter */
739 hostname2[cp - hostname] = '\0';
740 addr = hostname2;
741 scope = cp + 1;
742
743 error = explore_numeric(pai, addr, servname, res, hostname);
744 if (error == 0) {
745 u_int32_t scopeid;
746
747 for (cur = *res; cur; cur = cur->ai_next) {
748 if (cur->ai_family != AF_INET6)
749 continue;
750 sin6 = (struct sockaddr_in6 *)(void *)cur->ai_addr;
751 if (ip6_str2scopeid(scope, sin6, &scopeid) == -1) {
752 free(hostname2);
753 return(EAI_NODATA); /* XXX: is return OK? */
754 }
755 sin6->sin6_scope_id = scopeid;
756 }
757 }
758
759 free(hostname2);
760
761 return error;
762#endif
763}
764
765static int
766get_canonname(const struct addrinfo *pai, struct addrinfo *ai, const char *str)
767{
768 if ((pai->ai_flags & (AI_CANONNAME | AI_FQDN)) != 0) {
769 ai->ai_canonname = strdup(str);
770 if (ai->ai_canonname == NULL)
771 return EAI_MEMORY;
772 }
773 return 0;
774}
775
776static struct addrinfo *
777get_ai(const struct addrinfo *pai, const struct afd *afd, const char *addr)
778{
779 char *p;
780 struct addrinfo *ai;
781
782 ai = (struct addrinfo *)malloc(sizeof(struct addrinfo)
783 + (afd->a_socklen));
784 if (ai == NULL)
785 return NULL;
786
787 memcpy(ai, pai, sizeof(struct addrinfo));
788 ai->ai_addr = (struct sockaddr *)(void *)(ai + 1);
789 memset(ai->ai_addr, 0, (size_t)afd->a_socklen);
790 ai->ai_addr->sa_len = afd->a_socklen;
791 ai->ai_addrlen = afd->a_socklen;
792 ai->ai_addr->sa_family = ai->ai_family = afd->a_af;
793 p = (char *)(void *)(ai->ai_addr);
794 memcpy(p + afd->a_off, addr, (size_t)afd->a_addrlen);
795 return ai;
796}
797
798static int
799get_portmatch(const struct addrinfo *ai, const char *servname)
800{
801
802 /* get_port does not touch first argument. when matchonly == 1. */
803 /* LINTED const cast */
804 return get_port((struct addrinfo *)ai, servname, 1);
805}
806
807static int
808get_port(struct addrinfo *ai, const char *servname, int matchonly)
809{
810 const char *errstr, *proto;
811 int port;
812 int allownumeric;
813
814 if (servname == NULL)
815 return 0;
816 switch (ai->ai_family) {
817 case AF_INET:
818#ifdef AF_INET6
819 case AF_INET6:
820#endif
821 break;
822 default:
823 return 0;
824 }
825
826 switch (ai->ai_socktype) {
827 case SOCK_RAW:
828 return EAI_SERVICE;
829 case SOCK_DGRAM:
830 case SOCK_STREAM:
831 case ANY:
832 allownumeric = 1;
833 break;
834 default:
835 return EAI_SOCKTYPE;
836 }
837
838 port = (int)strtonum(servname, 0, USHRT_MAX, &errstr);
839 if (!errstr) {
840 if (!allownumeric)
841 return EAI_SERVICE;
842 port = htons(port);
843 } else {
844 struct servent sp;
845 struct servent_data sd;
846
847 if (errno == ERANGE)
848 return EAI_SERVICE;
849 if (ai->ai_flags & AI_NUMERICSERV)
850 return EAI_NONAME;
851
852 switch (ai->ai_socktype) {
853 case SOCK_DGRAM:
854 proto = "udp";
855 break;
856 case SOCK_STREAM:
857 proto = "tcp";
858 break;
859 default:
860 proto = NULL;
861 break;
862 }
863
864 (void)memset(&sd, 0, sizeof(sd));
865 if (getservbyname_r(servname, proto, &sp, &sd) == -1)
866 return EAI_SERVICE;
867 port = sp.s_port;
868 endservent_r(&sd);
869 }
870
871 if (!matchonly) {
872 switch (ai->ai_family) {
873 case AF_INET:
874 ((struct sockaddr_in *)(void *)
875 ai->ai_addr)->sin_port = port;
876 break;
877#ifdef INET6
878 case AF_INET6:
879 ((struct sockaddr_in6 *)(void *)
880 ai->ai_addr)->sin6_port = port;
881 break;
882#endif
883 }
884 }
885
886 return 0;
887}
888
889static const struct afd *
890find_afd(int af)
891{
892 const struct afd *afd;
893
894 if (af == PF_UNSPEC)
895 return NULL;
896 for (afd = afdl; afd->a_af; afd++) {
897 if (afd->a_af == af)
898 return afd;
899 }
900 return NULL;
901}
902
903#ifdef INET6
904/* convert a string to a scope identifier. XXX: IPv6 specific */
905static int
906ip6_str2scopeid(char *scope, struct sockaddr_in6 *sin6, u_int32_t *scopeid)
907{
908 struct in6_addr *a6 = &sin6->sin6_addr;
909 const char *errstr;
910
911 /* empty scopeid portion is invalid */
912 if (*scope == '\0')
913 return -1;
914
915 if (IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6) ||
916 IN6_IS_ADDR_MC_INTFACELOCAL(a6)) {
917 /*
918 * We currently assume a one-to-one mapping between links
919 * and interfaces, so we simply use interface indices for
920 * like-local scopes.
921 */
922 *scopeid = if_nametoindex(scope);
923 if (*scopeid == 0)
924 goto trynumeric;
925 return 0;
926 }
927
928 /* still unclear about literal, allow numeric only - placeholder */
929 if (IN6_IS_ADDR_SITELOCAL(a6) || IN6_IS_ADDR_MC_SITELOCAL(a6))
930 goto trynumeric;
931 if (IN6_IS_ADDR_MC_ORGLOCAL(a6))
932 goto trynumeric;
933 else
934 goto trynumeric; /* global */
935
936 /* try to convert to a numeric id as a last resort */
937 trynumeric:
938 *scopeid = (u_int32_t)strtonum(scope, 0, UINT32_MAX, &errstr);
939 if (errstr)
940 return (-1);
941 return (0);
942}
943#endif
944
945/* code duplicate with gethnamaddr.c */
946
947static const char AskedForGot[] =
948 "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
949
950static struct addrinfo *
951getanswer(const querybuf *answer, int anslen, const char *qname, int qtype,
952 const struct addrinfo *pai)
953{
954 struct addrinfo sentinel, *cur;
955 struct addrinfo ai;
956 const struct afd *afd;
957 char *canonname;
958 const HEADER *hp;
959 const u_char *cp;
960 int n;
961 const u_char *eom;
962 char *bp, *ep;
963 int type, class, ancount, qdcount;
964 int haveanswer, had_error;
965 char tbuf[MAXDNAME];
966 int (*name_ok)(const char *);
967 char hostbuf[8*1024];
968
969 memset(&sentinel, 0, sizeof(sentinel));
970 cur = &sentinel;
971
972 canonname = NULL;
973 eom = answer->buf + anslen;
974 switch (qtype) {
975 case T_A:
976 case T_AAAA:
977 case T_ANY: /*use T_ANY only for T_A/T_AAAA lookup*/
978 name_ok = res_hnok;
979 break;
980 default:
981 return (NULL); /* XXX should be abort() -- but that is illegal */
982 }
983 /*
984 * find first satisfactory answer
985 */
986 hp = &answer->hdr;
987 ancount = ntohs(hp->ancount);
988 qdcount = ntohs(hp->qdcount);
989 bp = hostbuf;
990 ep = hostbuf + sizeof hostbuf;
991 cp = answer->buf + HFIXEDSZ;
992 if (qdcount != 1) {
993 h_errno = NO_RECOVERY;
994 return (NULL);
995 }
996 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
997 if ((n < 0) || !(*name_ok)(bp)) {
998 h_errno = NO_RECOVERY;
999 return (NULL);
1000 }
1001 cp += n + QFIXEDSZ;
1002 if (qtype == T_A || qtype == T_AAAA || qtype == T_ANY) {
1003 size_t len;
1004
1005 /* res_send() has already verified that the query name is the
1006 * same as the one we sent; this just gets the expanded name
1007 * (i.e., with the succeeding search-domain tacked on).
1008 */
1009 len = strlen(bp) + 1; /* for the \0 */
1010 if (len >= MAXHOSTNAMELEN) {
1011 h_errno = NO_RECOVERY;
1012 return (NULL);
1013 }
1014 canonname = bp;
1015 bp += len;
1016 /* The qname can be abbreviated, but h_name is now absolute. */
1017 qname = canonname;
1018 }
1019 haveanswer = 0;
1020 had_error = 0;
1021 while (ancount-- > 0 && cp < eom && !had_error) {
1022 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
1023 if ((n < 0) || !(*name_ok)(bp)) {
1024 had_error++;
1025 continue;
1026 }
1027 cp += n; /* name */
1028 type = _getshort(cp);
1029 cp += INT16SZ; /* type */
1030 class = _getshort(cp);
1031 cp += INT16SZ + INT32SZ; /* class, TTL */
1032 n = _getshort(cp);
1033 cp += INT16SZ; /* len */
1034 if (class != C_IN) {
1035 /* XXX - debug? syslog? */
1036 cp += n;
1037 continue; /* XXX - had_error++ ? */
1038 }
1039 if ((qtype == T_A || qtype == T_AAAA || qtype == T_ANY) &&
1040 type == T_CNAME) {
1041 size_t len;
1042
1043 n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
1044 if ((n < 0) || !(*name_ok)(tbuf)) {
1045 had_error++;
1046 continue;
1047 }
1048 cp += n;
1049 /* Get canonical name. */
1050 len = strlen(tbuf) + 1; /* for the \0 */
1051 if (len > ep - bp || len >= MAXHOSTNAMELEN) {
1052 had_error++;
1053 continue;
1054 }
1055 strlcpy(bp, tbuf, ep - bp);
1056 canonname = bp;
1057 bp += len;
1058 continue;
1059 }
1060 if (qtype == T_ANY) {
1061 if (!(type == T_A || type == T_AAAA)) {
1062 cp += n;
1063 continue;
1064 }
1065 } else if (type != qtype) {
1066#ifndef NO_LOG_BAD_DNS_RESPONSES
1067 if (type != T_KEY && type != T_SIG) {
1068 struct syslog_data sdata = SYSLOG_DATA_INIT;
1069
1070 syslog_r(LOG_NOTICE|LOG_AUTH, &sdata,
1071 "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
1072 qname, p_class(C_IN), p_type(qtype),
1073 p_type(type));
1074 }
1075#endif /* NO_LOG_BAD_DNS_RESPONSES */
1076 cp += n;
1077 continue; /* XXX - had_error++ ? */
1078 }
1079 switch (type) {
1080 case T_A:
1081 case T_AAAA:
1082 if (strcasecmp(canonname, bp) != 0) {
1083 struct syslog_data sdata = SYSLOG_DATA_INIT;
1084
1085 syslog_r(LOG_NOTICE|LOG_AUTH, &sdata,
1086 AskedForGot, canonname, bp);
1087 cp += n;
1088 continue; /* XXX - had_error++ ? */
1089 }
1090 if (type == T_A && n != INADDRSZ) {
1091 cp += n;
1092 continue;
1093 }
1094 if (type == T_AAAA && n != IN6ADDRSZ) {
1095 cp += n;
1096 continue;
1097 }
1098 if (type == T_AAAA) {
1099 struct in6_addr in6;
1100 memcpy(&in6, cp, IN6ADDRSZ);
1101 if (IN6_IS_ADDR_V4MAPPED(&in6)) {
1102 cp += n;
1103 continue;
1104 }
1105 }
1106 if (!haveanswer) {
1107 canonname = bp;
1108 bp += strlen(bp) + 1; /* for the \0 */
1109 }
1110
1111 /* don't overwrite pai */
1112 ai = *pai;
1113 ai.ai_family = (type == T_A) ? AF_INET : AF_INET6;
1114 afd = find_afd(ai.ai_family);
1115 if (afd == NULL) {
1116 cp += n;
1117 continue;
1118 }
1119 cur->ai_next = get_ai(&ai, afd, (const char *)cp);
1120 if (cur->ai_next == NULL)
1121 had_error++;
1122 while (cur && cur->ai_next)
1123 cur = cur->ai_next;
1124 cp += n;
1125 break;
1126 default:
1127 abort(); /* XXX abort illegal in library */
1128 }
1129 if (!had_error)
1130 haveanswer++;
1131 }
1132 if (haveanswer) {
1133 if (!canonname || (pai->ai_flags & AI_FQDN) != 0)
1134 (void)get_canonname(pai, sentinel.ai_next, qname);
1135 else
1136 (void)get_canonname(pai, sentinel.ai_next, canonname);
1137 h_errno = NETDB_SUCCESS;
1138 return sentinel.ai_next;
1139 }
1140
1141 h_errno = NO_RECOVERY;
1142 return NULL;
1143}
1144
1145/*ARGSUSED*/
1146static struct addrinfo *
1147_dns_getaddrinfo(const char *name, const struct addrinfo *pai,
1148 const struct __res_state *_resp)
1149{
1150 struct addrinfo *ai;
1151 querybuf *buf, *buf2;
1152 struct addrinfo sentinel, *cur;
1153 struct res_target q, q2;
1154
1155 memset(&q, 0, sizeof(q));
1156 memset(&q2, 0, sizeof(q2));
1157 memset(&sentinel, 0, sizeof(sentinel));
1158 cur = &sentinel;
1159
1160 buf = malloc(sizeof(*buf));
1161 if (buf == NULL) {
1162 h_errno = NETDB_INTERNAL;
1163 return NULL;
1164 }
1165 buf2 = malloc(sizeof(*buf2));
1166 if (buf2 == NULL) {
1167 free(buf);
1168 h_errno = NETDB_INTERNAL;
1169 return NULL;
1170 }
1171
1172 switch (pai->ai_family) {
1173 case AF_UNSPEC:
1174 /* respect user supplied order */
1175 q.qclass = C_IN;
1176 q.qtype = (_resp->family[0] == AF_INET6) ? T_AAAA : T_A;
1177 q.answer = buf->buf;
1178 q.anslen = sizeof(buf->buf);
1179 q.next = &q2;
1180
1181 if (_resp->family[1] == -1) {
1182 /* stop here if only one family was given */
1183 q.next = NULL;
1184 break;
1185 }
1186
1187 q2.qclass = C_IN;
1188 q2.qtype = (_resp->family[1] == AF_INET6) ? T_AAAA : T_A;
1189 q2.answer = buf2->buf;
1190 q2.anslen = sizeof(buf2->buf);
1191 break;
1192 case AF_INET:
1193 q.qclass = C_IN;
1194 q.qtype = T_A;
1195 q.answer = buf->buf;
1196 q.anslen = sizeof(buf->buf);
1197 break;
1198 case AF_INET6:
1199 q.qclass = C_IN;
1200 q.qtype = T_AAAA;
1201 q.answer = buf->buf;
1202 q.anslen = sizeof(buf->buf);
1203 break;
1204 default:
1205 free(buf);
1206 free(buf2);
1207 return NULL;
1208 }
1209 if (res_searchN(name, &q) < 0) {
1210 free(buf);
1211 free(buf2);
1212 return NULL;
1213 }
1214 ai = getanswer(buf, q.n, q.name, q.qtype, pai);
1215 if (ai) {
1216 cur->ai_next = ai;
1217 while (cur && cur->ai_next)
1218 cur = cur->ai_next;
1219 }
1220 if (q.next) {
1221 ai = getanswer(buf2, q2.n, q2.name, q2.qtype, pai);
1222 if (ai)
1223 cur->ai_next = ai;
1224 }
1225 free(buf);
1226 free(buf2);
1227 return sentinel.ai_next;
1228}
1229
1230static struct addrinfo *
1231_gethtent(const char *name, const struct addrinfo *pai, FILE *hostf)
1232{
1233 char *p;
1234 char *cp, *tname, *cname;
1235 struct addrinfo hints, *res0, *res;
1236 int error;
1237 const char *addr;
1238 char hostbuf[8*1024];
1239
1240 again:
1241 if (!(p = fgets(hostbuf, sizeof hostbuf, hostf)))
1242 return (NULL);
1243 if (*p == '#')
1244 goto again;
1245 if (!(cp = strpbrk(p, "#\n")))
1246 goto again;
1247 *cp = '\0';
1248 if (!(cp = strpbrk(p, " \t")))
1249 goto again;
1250 *cp++ = '\0';
1251 addr = p;
1252 /* if this is not something we're looking for, skip it. */
1253 cname = NULL;
1254 while (cp && *cp) {
1255 if (*cp == ' ' || *cp == '\t') {
1256 cp++;
1257 continue;
1258 }
1259 if (!cname)
1260 cname = cp;
1261 tname = cp;
1262 if ((cp = strpbrk(cp, " \t")) != NULL)
1263 *cp++ = '\0';
1264 if (strcasecmp(name, tname) == 0)
1265 goto found;
1266 }
1267 goto again;
1268
1269found:
1270 hints = *pai;
1271 hints.ai_flags = AI_NUMERICHOST;
1272 error = getaddrinfo(addr, NULL, &hints, &res0);
1273 if (error)
1274 goto again;
1275 for (res = res0; res; res = res->ai_next) {
1276 /* cover it up */
1277 res->ai_flags = pai->ai_flags;
1278
1279 if (get_canonname(pai, res, cname) != 0) {
1280 freeaddrinfo(res0);
1281 goto again;
1282 }
1283 }
1284 return res0;
1285}
1286
1287/*ARGSUSED*/
1288static struct addrinfo *
1289_files_getaddrinfo(const char *name, const struct addrinfo *pai)
1290{
1291 struct addrinfo sentinel, *cur;
1292 struct addrinfo *p;
1293 FILE *hostf;
1294
1295 hostf = fopen(_PATH_HOSTS, "r");
1296 if (hostf == NULL)
1297 return NULL;
1298
1299 memset(&sentinel, 0, sizeof(sentinel));
1300 cur = &sentinel;
1301
1302 while ((p = _gethtent(name, pai, hostf)) != NULL) {
1303 cur->ai_next = p;
1304 while (cur && cur->ai_next)
1305 cur = cur->ai_next;
1306 }
1307 fclose(hostf);
1308
1309 return sentinel.ai_next;
1310}
1311
1312#ifdef YP
1313static char *__ypdomain;
1314
1315/*ARGSUSED*/
1316static struct addrinfo *
1317_yphostent(char *line, const struct addrinfo *pai)
1318{
1319 struct addrinfo sentinel, *cur;
1320 struct addrinfo hints, *res, *res0;
1321 int error;
1322 char *p = line;
1323 const char *addr, *canonname;
1324 char *nextline;
1325 char *cp;
1326
1327 addr = canonname = NULL;
1328
1329 memset(&sentinel, 0, sizeof(sentinel));
1330 cur = &sentinel;
1331
1332nextline:
1333 /* terminate line */
1334 cp = strchr(p, '\n');
1335 if (cp) {
1336 *cp++ = '\0';
1337 nextline = cp;
1338 } else
1339 nextline = NULL;
1340
1341 cp = strpbrk(p, " \t");
1342 if (cp == NULL) {
1343 if (canonname == NULL)
1344 return (NULL);
1345 else
1346 goto done;
1347 }
1348 *cp++ = '\0';
1349
1350 addr = p;
1351
1352 while (cp && *cp) {
1353 if (*cp == ' ' || *cp == '\t') {
1354 cp++;
1355 continue;
1356 }
1357 if (!canonname)
1358 canonname = cp;
1359 if ((cp = strpbrk(cp, " \t")) != NULL)
1360 *cp++ = '\0';
1361 }
1362
1363 hints = *pai;
1364 hints.ai_flags = AI_NUMERICHOST;
1365 error = getaddrinfo(addr, NULL, &hints, &res0);
1366 if (error == 0) {
1367 for (res = res0; res; res = res->ai_next) {
1368 /* cover it up */
1369 res->ai_flags = pai->ai_flags;
1370
1371 (void)get_canonname(pai, res, canonname);
1372 }
1373 } else
1374 res0 = NULL;
1375 if (res0) {
1376 cur->ai_next = res0;
1377 while (cur && cur->ai_next)
1378 cur = cur->ai_next;
1379 }
1380
1381 if (nextline) {
1382 p = nextline;
1383 goto nextline;
1384 }
1385
1386done:
1387 return sentinel.ai_next;
1388}
1389
1390/*ARGSUSED*/
1391static struct addrinfo *
1392_yp_getaddrinfo(const char *name, const struct addrinfo *pai)
1393{
1394 struct addrinfo sentinel, *cur;
1395 struct addrinfo *ai = NULL;
1396 static char *__ypcurrent;
1397 int __ypcurrentlen, r;
1398
1399 memset(&sentinel, 0, sizeof(sentinel));
1400 cur = &sentinel;
1401
1402 if (!__ypdomain) {
1403 if (_yp_check(&__ypdomain) == 0)
1404 return NULL;
1405 }
1406 if (__ypcurrent)
1407 free(__ypcurrent);
1408 __ypcurrent = NULL;
1409
1410 /* hosts.byname is only for IPv4 (Solaris8) */
1411 if (pai->ai_family == PF_UNSPEC || pai->ai_family == PF_INET) {
1412 r = yp_match(__ypdomain, "hosts.byname", name,
1413 (int)strlen(name), &__ypcurrent, &__ypcurrentlen);
1414 if (r == 0) {
1415 struct addrinfo ai4;
1416
1417 ai4 = *pai;
1418 ai4.ai_family = AF_INET;
1419 ai = _yphostent(__ypcurrent, &ai4);
1420 if (ai) {
1421 cur->ai_next = ai;
1422 while (cur && cur->ai_next)
1423 cur = cur->ai_next;
1424 }
1425 }
1426 }
1427
1428 /* ipnodes.byname can hold both IPv4/v6 */
1429 r = yp_match(__ypdomain, "ipnodes.byname", name,
1430 (int)strlen(name), &__ypcurrent, &__ypcurrentlen);
1431 if (r == 0) {
1432 ai = _yphostent(__ypcurrent, pai);
1433 if (ai) {
1434 cur->ai_next = ai;
1435 while (cur && cur->ai_next)
1436 cur = cur->ai_next;
1437 }
1438 }
1439
1440 return sentinel.ai_next;
1441}
1442#endif
1443
1444
1445/* resolver logic */
1446
1447extern const char *__hostalias(const char *);
1448extern int h_errno;
1449extern int res_opt(int, u_char *, int, int);
1450
1451/*
1452 * Formulate a normal query, send, and await answer.
1453 * Returned answer is placed in supplied buffer "answer".
1454 * Perform preliminary check of answer, returning success only
1455 * if no error is indicated and the answer count is nonzero.
1456 * Return the size of the response on success, -1 on error.
1457 * Error number is left in h_errno.
1458 *
1459 * Caller must parse answer and determine whether it answers the question.
1460 */
1461static int
1462res_queryN(const char *name, struct res_target *target)
1463{
1464 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
1465 u_char *buf;
1466 HEADER *hp;
1467 int n;
1468 struct res_target *t;
1469 int rcode;
1470 int ancount;
1471
1472 buf = malloc(MAXPACKET);
1473 if (buf == NULL) {
1474 h_errno = NETDB_INTERNAL;
1475 return (-1);
1476 }
1477
1478 rcode = NOERROR;
1479 ancount = 0;
1480
1481 if (_res_init(0) == -1) {
1482 h_errno = NETDB_INTERNAL;
1483 free(buf);
1484 return (-1);
1485 }
1486
1487 for (t = target; t; t = t->next) {
1488 int class, type;
1489 u_char *answer;
1490 int anslen;
1491
1492 hp = (HEADER *)(void *)t->answer;
1493 hp->rcode = NOERROR; /* default */
1494
1495 /* make it easier... */
1496 class = t->qclass;
1497 type = t->qtype;
1498 answer = t->answer;
1499 anslen = t->anslen;
1500#ifdef DEBUG
1501 if (_resp->options & RES_DEBUG)
1502 printf(";; res_query(%s, %d, %d)\n", name, class, type);
1503#endif
1504
1505 n = res_mkquery(QUERY, name, class, type, NULL, 0, NULL,
1506 buf, MAXPACKET);
1507 if (n > 0 && (_resp->options & RES_USE_EDNS0) != 0)
1508 n = res_opt(n, buf, MAXPACKET, anslen);
1509 if (n <= 0) {
1510#ifdef DEBUG
1511 if (_resp->options & RES_DEBUG)
1512 printf(";; res_query: mkquery failed\n");
1513#endif
1514 h_errno = NO_RECOVERY;
1515 free(buf);
1516 return (n);
1517 }
1518 n = res_send(buf, n, answer, anslen);
1519#if 0
1520 if (n < 0) {
1521#ifdef DEBUG
1522 if (_resp->options & RES_DEBUG)
1523 printf(";; res_query: send error\n");
1524#endif
1525 h_errno = TRY_AGAIN;
1526 free(buf);
1527 return (n);
1528 }
1529#endif
1530
1531 if (n < 0 || hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
1532 rcode = hp->rcode; /* record most recent error */
1533#ifdef DEBUG
1534 if (_resp->options & RES_DEBUG)
1535 printf(";; rcode = %u, ancount=%u\n", hp->rcode,
1536 ntohs(hp->ancount));
1537#endif
1538 continue;
1539 }
1540
1541 ancount += ntohs(hp->ancount);
1542
1543 t->n = n;
1544 }
1545
1546 if (ancount == 0) {
1547 switch (rcode) {
1548 case NXDOMAIN:
1549 h_errno = HOST_NOT_FOUND;
1550 break;
1551 case SERVFAIL:
1552 h_errno = TRY_AGAIN;
1553 break;
1554 case NOERROR:
1555 h_errno = NO_DATA;
1556 break;
1557 case FORMERR:
1558 case NOTIMP:
1559 case REFUSED:
1560 default:
1561 h_errno = NO_RECOVERY;
1562 break;
1563 }
1564 free(buf);
1565 return (-1);
1566 }
1567 free(buf);
1568 return (ancount);
1569}
1570
1571/*
1572 * Formulate a normal query, send, and retrieve answer in supplied buffer.
1573 * Return the size of the response on success, -1 on error.
1574 * If enabled, implement search rules until answer or unrecoverable failure
1575 * is detected. Error code, if any, is left in h_errno.
1576 */
1577static int
1578res_searchN(const char *name, struct res_target *target)
1579{
1580 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
1581 const char *cp, * const *domain;
1582 HEADER *hp = (HEADER *)(void *)target->answer; /*XXX*/
1583 u_int dots;
1584 int trailing_dot, ret, saved_herrno;
1585 int got_nodata = 0, got_servfail = 0, tried_as_is = 0;
1586
1587 if (_res_init(0) == -1) {
1588 h_errno = NETDB_INTERNAL;
1589 return (-1);
1590 }
1591
1592 errno = 0;
1593 h_errno = HOST_NOT_FOUND; /* default, if we never query */
1594 dots = 0;
1595 for (cp = name; *cp; cp++)
1596 dots += (*cp == '.');
1597 trailing_dot = 0;
1598 if (cp > name && *--cp == '.')
1599 trailing_dot++;
1600
1601 /*
1602 * if there aren't any dots, it could be a user-level alias
1603 */
1604 if (!dots && (cp = __hostalias(name)) != NULL)
1605 return (res_queryN(cp, target));
1606
1607 /*
1608 * If there are dots in the name already, let's just give it a try
1609 * 'as is'. The threshold can be set with the "ndots" option.
1610 */
1611 saved_herrno = -1;
1612 if (dots >= _resp->ndots) {
1613 ret = res_querydomainN(name, NULL, target);
1614 if (ret > 0)
1615 return (ret);
1616 saved_herrno = h_errno;
1617 tried_as_is++;
1618 }
1619
1620 /*
1621 * We do at least one level of search if
1622 * - there is no dot and RES_DEFNAME is set, or
1623 * - there is at least one dot, there is no trailing dot,
1624 * and RES_DNSRCH is set.
1625 */
1626 if ((!dots && (_resp->options & RES_DEFNAMES)) ||
1627 (dots && !trailing_dot && (_resp->options & RES_DNSRCH))) {
1628 int done = 0;
1629
1630 for (domain = (const char * const *)_resp->dnsrch;
1631 *domain && !done;
1632 domain++) {
1633
1634 ret = res_querydomainN(name, *domain, target);
1635 if (ret > 0)
1636 return (ret);
1637
1638 /*
1639 * If no server present, give up.
1640 * If name isn't found in this domain,
1641 * keep trying higher domains in the search list
1642 * (if that's enabled).
1643 * On a NO_DATA error, keep trying, otherwise
1644 * a wildcard entry of another type could keep us
1645 * from finding this entry higher in the domain.
1646 * If we get some other error (negative answer or
1647 * server failure), then stop searching up,
1648 * but try the input name below in case it's
1649 * fully-qualified.
1650 */
1651 if (errno == ECONNREFUSED) {
1652 h_errno = TRY_AGAIN;
1653 return (-1);
1654 }
1655
1656 switch (h_errno) {
1657 case NO_DATA:
1658 got_nodata++;
1659 /* FALLTHROUGH */
1660 case HOST_NOT_FOUND:
1661 /* keep trying */
1662 break;
1663 case TRY_AGAIN:
1664 if (hp->rcode == SERVFAIL) {
1665 /* try next search element, if any */
1666 got_servfail++;
1667 break;
1668 }
1669 /* FALLTHROUGH */
1670 default:
1671 /* anything else implies that we're done */
1672 done++;
1673 }
1674 /*
1675 * if we got here for some reason other than DNSRCH,
1676 * we only wanted one iteration of the loop, so stop.
1677 */
1678 if (!(_resp->options & RES_DNSRCH))
1679 done++;
1680 }
1681 }
1682
1683 /*
1684 * if we have not already tried the name "as is", do that now.
1685 * note that we do this regardless of how many dots were in the
1686 * name or whether it ends with a dot.
1687 */
1688 if (!tried_as_is) {
1689 ret = res_querydomainN(name, NULL, target);
1690 if (ret > 0)
1691 return (ret);
1692 }
1693
1694 /*
1695 * if we got here, we didn't satisfy the search.
1696 * if we did an initial full query, return that query's h_errno
1697 * (note that we wouldn't be here if that query had succeeded).
1698 * else if we ever got a nodata, send that back as the reason.
1699 * else send back meaningless h_errno, that being the one from
1700 * the last DNSRCH we did.
1701 */
1702 if (saved_herrno != -1)
1703 h_errno = saved_herrno;
1704 else if (got_nodata)
1705 h_errno = NO_DATA;
1706 else if (got_servfail)
1707 h_errno = TRY_AGAIN;
1708 return (-1);
1709}
1710
1711/*
1712 * Perform a call on res_query on the concatenation of name and domain,
1713 * removing a trailing dot from name if domain is NULL.
1714 */
1715static int
1716res_querydomainN(const char *name, const char *domain,
1717 struct res_target *target)
1718{
1719 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
1720 char nbuf[MAXDNAME];
1721 const char *longname = nbuf;
1722 size_t len;
1723
1724 if (_res_init(0) == -1) {
1725 h_errno = NETDB_INTERNAL;
1726 return (-1);
1727 }
1728#ifdef DEBUG
1729 if (_resp->options & RES_DEBUG)
1730 printf(";; res_querydomain(%s, %s)\n",
1731 name, domain?domain:"<Nil>");
1732#endif
1733 if (domain == NULL) {
1734 /*
1735 * Check for trailing '.';
1736 * copy without '.' if present.
1737 */
1738 len = strlcpy(nbuf, name, sizeof(nbuf));
1739 if (len >= sizeof(nbuf)) {
1740 h_errno = NO_RECOVERY;
1741 return (-1);
1742 }
1743 if (len > 0 && nbuf[len - 1] == '.')
1744 nbuf[len - 1] = '\0';
1745 } else {
1746 int i;
1747
1748 i = snprintf(nbuf, sizeof(nbuf), "%s.%s", name, domain);
1749 if (i < 0 || i >= sizeof(nbuf)) {
1750 h_errno = NO_RECOVERY;
1751 return (-1);
1752 }
1753 }
1754 return (res_queryN(longname, target));
1755}
diff --git a/src/lib/libc/net/gethostbyname.3 b/src/lib/libc/net/gethostbyname.3
index bac0368296..1a05460da4 100644
--- a/src/lib/libc/net/gethostbyname.3
+++ b/src/lib/libc/net/gethostbyname.3
@@ -1,4 +1,4 @@
1.\" $NetBSD: gethostbyname.3,v 1.6 1995/02/25 06:20:28 cgd Exp $ 1.\" $OpenBSD: gethostbyname.3,v 1.25 2007/05/31 19:19:30 jmc Exp $
2.\" 2.\"
3.\" Copyright (c) 1983, 1987, 1991, 1993 3.\" Copyright (c) 1983, 1987, 1991, 1993
4.\" The Regents of the University of California. All rights reserved. 4.\" The Regents of the University of California. All rights reserved.
@@ -11,11 +11,7 @@
11.\" 2. Redistributions in binary form must reproduce the above copyright 11.\" 2. Redistributions in binary form must reproduce the above copyright
12.\" notice, this list of conditions and the following disclaimer in the 12.\" notice, this list of conditions and the following disclaimer in the
13.\" documentation and/or other materials provided with the distribution. 13.\" documentation and/or other materials provided with the distribution.
14.\" 3. All advertising materials mentioning features or use of this software 14.\" 3. Neither the name of the University nor the names of its contributors
15.\" must display the following acknowledgement:
16.\" This product includes software developed by the University of
17.\" California, Berkeley and its contributors.
18.\" 4. Neither the name of the University nor the names of its contributors
19.\" may be used to endorse or promote products derived from this software 15.\" may be used to endorse or promote products derived from this software
20.\" without specific prior written permission. 16.\" without specific prior written permission.
21.\" 17.\"
@@ -31,58 +27,66 @@
31.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32.\" SUCH DAMAGE. 28.\" SUCH DAMAGE.
33.\" 29.\"
34.\" @(#)gethostbyname.3 8.2 (Berkeley) 4/19/94 30.Dd $Mdocdate: May 31 2007 $
35.\"
36.Dd April 19, 1994
37.Dt GETHOSTBYNAME 3 31.Dt GETHOSTBYNAME 3
38.Os BSD 4.2 32.Os
39.Sh NAME 33.Sh NAME
40.Nm gethostbyname , 34.Nm gethostbyname ,
35.Nm gethostbyname2 ,
41.Nm gethostbyaddr , 36.Nm gethostbyaddr ,
42.Nm gethostent , 37.Nm gethostent ,
43.Nm sethostent , 38.Nm sethostent ,
44.Nm endhostent , 39.Nm endhostent ,
40.Nm hstrerror ,
45.Nm herror 41.Nm herror
46.Nd get network host entry 42.Nd get network host entry
47.Sh SYNOPSIS 43.Sh SYNOPSIS
48.Fd #include <netdb.h> 44.Fd #include <netdb.h>
49.Fd extern int h_errno; 45.Vt extern int h_errno ;
50.Ft struct hostent * 46.Ft struct hostent *
51.Fn gethostbyname "const char *name" 47.Fn gethostbyname "const char *name"
52.Ft struct hostent * 48.Ft struct hostent *
53.Fn gethostbyaddr "const char *addr" "int len" "int type" 49.Fn gethostbyname2 "const char *name" "int af"
50.Ft struct hostent *
51.Fn gethostbyaddr "const void *addr" "socklen_t len" "int af"
54.Ft struct hostent * 52.Ft struct hostent *
55.Fn gethostent void 53.Fn gethostent void
54.Ft void
56.Fn sethostent "int stayopen" 55.Fn sethostent "int stayopen"
56.Ft void
57.Fn endhostent void 57.Fn endhostent void
58.Fn herror "char *string" 58.Ft void
59.Fn herror "const char *string"
60.Ft const char *
61.Fn hstrerror "int err"
59.Sh DESCRIPTION 62.Sh DESCRIPTION
60The 63The
61.Fn gethostbyname 64.Fn gethostbyname ,
65.Fn gethostbyname2 ,
62and 66and
63.Fn gethostbyaddr 67.Fn gethostbyaddr
64functions 68functions each return a pointer to an object with the following structure
65each return a pointer to an object with the 69describing an Internet host referenced by name or by address, respectively.
66following structure describing an internet host 70This structure contains either information obtained from the name server (i.e.,
67referenced by name or by address, respectively. 71.Xr resolver 3
68This structure contains either the information obtained from the name server, 72and
69.Xr named 8 , 73.Xr named 8 ) ,
70broken-out fields from a line in 74broken-out fields from a line in
71.Pa /etc/hosts , 75.Pa /etc/hosts ,
72or database entries supplied by the 76or database entries supplied by the
73.Xr yp 8 77.Xr yp 8
74system . 78system.
75If the local name server is not running these routines do a lookup in 79.Xr resolv.conf 5
76.Pa /etc/hosts . 80describes how the particular database is chosen.
77.Bd -literal 81.Bd -literal -offset indent
78struct hostent { 82struct hostent {
79 char *h_name; /* official name of host */ 83 char *h_name; /* official name of host */
80 char **h_aliases; /* alias list */ 84 char **h_aliases; /* alias list */
81 int h_addrtype; /* host address type */ 85 int h_addrtype; /* host address type */
82 int h_length; /* length of address */ 86 int h_length; /* length of address */
83 char **h_addr_list; /* list of addresses from name server */ 87 char **h_addr_list; /* list of returned addresses */
84}; 88};
85#define h_addr h_addr_list[0] /* address, for backward compatibility */ 89#define h_addr h_addr_list[0] /* address, for backward compat */
86.Ed 90.Ed
87.Pp 91.Pp
88The members of this structure are: 92The members of this structure are:
@@ -90,36 +94,50 @@ The members of this structure are:
90.It Fa h_name 94.It Fa h_name
91Official name of the host. 95Official name of the host.
92.It Fa h_aliases 96.It Fa h_aliases
93A zero terminated array of alternate names for the host. 97A null-terminated array of alternate names for the host.
94.It Fa h_addrtype 98.It Fa h_addrtype
95The type of address being returned; currently always 99The type of address being returned.
96.Dv AF_INET .
97.It Fa h_length 100.It Fa h_length
98The length, in bytes, of the address. 101The length, in bytes, of the address.
99.It Fa h_addr_list 102.It Fa h_addr_list
100A zero terminated array of network addresses for the host. 103A null-terminated array of network addresses for the host.
101Host addresses are returned in network byte order. 104Host addresses are returned in network byte order.
102.It Fa h_addr 105.It Fa h_addr
103The first address in 106The first address in
104.Fa h_addr_list ; 107.Fa h_addr_list ;
105this is for backward compatibility. 108this is for backward compatibility.
109.El
106.Pp 110.Pp
107When using the nameserver, 111The function
108.Fn gethostbyname 112.Fn gethostbyname
109will search for the named host in the current domain and its parents 113will search for the named host in the current domain and its parents
110unless the name ends in a dot. 114using the search lookup semantics detailed in
111If the name contains no dot, and if the environment variable 115.Xr resolv.conf 5
112.Dq Ev HOSTALIASES 116and
113contains the name of an alias file, the alias file will first be searched 117.Xr hostname 7 .
114for an alias matching the input name. 118.Pp
115See 119.Fn gethostbyname2
116.Xr hostname 7 120is an advanced form of
117for the domain search procedure and the alias file format. 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 .
118.Pp 137.Pp
119The 138The
120.Fn sethostent 139.Fn sethostent
121function 140function may be used to request the use of a connected
122may be used to request the use of a connected
123.Tn TCP 141.Tn TCP
124socket for queries. 142socket for queries.
125If the 143If the
@@ -127,7 +145,7 @@ If the
127flag is non-zero, 145flag is non-zero,
128this sets the option to send all queries to the name server using 146this sets the option to send all queries to the name server using
129.Tn TCP 147.Tn TCP
130and to retain the connection after each call to 148and to retain the connection after each call to
131.Fn gethostbyname 149.Fn gethostbyname
132or 150or
133.Fn gethostbyaddr . 151.Fn gethostbyaddr .
@@ -137,17 +155,46 @@ datagrams.
137.Pp 155.Pp
138The 156The
139.Fn endhostent 157.Fn endhostent
140function 158function closes the
141closes the
142.Tn TCP 159.Tn TCP
143connection. 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
144.Sh FILES 189.Sh FILES
145.Bl -tag -width /etc/hosts -compact 190.Bl -tag -width /etc/resolv.conf -compact
146.It Pa /etc/hosts 191.It Pa /etc/hosts
192.It Pa /etc/resolv.conf
147.El 193.El
148.Sh DIAGNOSTICS 194.Sh DIAGNOSTICS
149Error return status from 195Error return status from
150.Fn gethostbyname 196.Fn gethostbyname ,
197.Fn gethostbyname2 ,
151and 198and
152.Fn gethostbyaddr 199.Fn gethostbyaddr
153is indicated by return of a null pointer. 200is indicated by return of a null pointer.
@@ -155,15 +202,6 @@ The external integer
155.Va h_errno 202.Va h_errno
156may then be checked to see whether this is a temporary failure 203may then be checked to see whether this is a temporary failure
157or an invalid or unknown host. 204or an invalid or unknown host.
158The routine
159.Fn herror
160can be used to print an error message describing the failure.
161If its argument
162.Fa string
163is
164.Pf non Dv -NULL ,
165it is printed, followed by a colon and a space.
166The error message is printed with a trailing newline.
167.Pp 205.Pp
168The variable 206The variable
169.Va h_errno 207.Va h_errno
@@ -180,75 +218,80 @@ A retry at some later time may succeed.
180Some unexpected server failure was encountered. 218Some unexpected server failure was encountered.
181This is a non-recoverable error. 219This is a non-recoverable error.
182.It Dv NO_DATA 220.It Dv NO_DATA
183The requested name is valid but does not have an IP address; 221The requested name is valid but does not have an IP address;
184this is not a temporary error. 222this is not a temporary error.
185This means that the name is known to the name server but there is no address 223This means that the name is known to the name server but there is no address
186associated with this name. 224associated with this name.
187Another type of request to the name server using this domain name 225Another type of request to the name server using this domain name
188will result in an answer; 226will result in an answer;
189for example, a mail-forwarder may be registered for this domain. 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.
190.El 237.El
191.Sh SEE ALSO 238.Sh SEE ALSO
239.Xr getaddrinfo 3 ,
240.Xr getnameinfo 3 ,
192.Xr resolver 3 , 241.Xr resolver 3 ,
193.Xr hosts 5 , 242.Xr hosts 5 ,
243.Xr resolv.conf 5 ,
194.Xr hostname 7 , 244.Xr hostname 7 ,
195.Xr named 8 245.Xr named 8
196.Sh CAVEAT 246.Sh HISTORY
197The 247The
198.Fn gethostent 248.Fn herror
199function 249function appeared in
200is defined, and 250.Bx 4.3 .
201.Fn sethostent 251The
252.Fn endhostent ,
253.Fn gethostbyaddr ,
254.Fn gethostbyname ,
255.Fn gethostent ,
202and 256and
203.Fn endhostent 257.Fn sethostent
204are redefined, 258functions appeared in
205when 259.Bx 4.2 .
206.Xr libc 3 260.Sh CAVEATS
207is built to use only the routines to lookup in 261If the search routines in
262.Xr resolv.conf 5
263decide to read the
208.Pa /etc/hosts 264.Pa /etc/hosts
209and not the name server. 265file,
210.Pp
211The
212.Fn gethostent 266.Fn gethostent
213function 267and other functions will
214reads the next line of 268read the next line of the file,
215.Pa /etc/hosts , 269re-opening the file if necessary.
216opening the file if necessary.
217.Pp 270.Pp
218The 271The
219.Fn sethostent 272.Fn sethostent
220function 273function opens and/or rewinds the file
221opens and/or rewinds the file
222.Pa /etc/hosts . 274.Pa /etc/hosts .
223If the 275If the
224.Fa stayopen 276.Fa stayopen
225argument is non-zero, 277argument is non-zero, the file will not be closed after each call to
226the file will not be closed after each call to 278.Fn gethostbyname ,
227.Fn gethostbyname 279.Fn gethostbyname2 ,
228or 280or
229.Fn gethostbyaddr . 281.Fn gethostbyaddr .
230.Pp 282.Pp
231The 283The
232.Fn endhostent 284.Fn endhostent
233function 285function closes the file.
234closes the file.
235.Sh HISTORY
236The
237.Fn herror
238function appeared in
239.Bx 4.3 .
240The
241.Fn endhostent ,
242.Fn gethostbyaddr ,
243.Fn gethostbyname ,
244.Fn gethostent ,
245and
246.Fn sethostent
247functions appeared in
248.Bx 4.2 .
249.Sh BUGS 286.Sh BUGS
250These functions use static data storage; 287These functions use static data storage;
251if the data is needed for future use, it should be 288if the data is needed for future use, it should be
252copied before any subsequent calls overwrite it. 289copied before any subsequent calls overwrite it.
290.Pp
253Only the Internet 291Only the Internet
254address format is currently understood. 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
index ec3f14a900..f4e655eeaf 100644
--- a/src/lib/libc/net/gethostnamadr.c
+++ b/src/lib/libc/net/gethostnamadr.c
@@ -1,5 +1,4 @@
1/* $NetBSD: gethostnamadr.c,v 1.13 1995/05/21 16:21:14 mycroft Exp $ */ 1/* $OpenBSD: gethostnamadr.c,v 1.73 2009/11/18 07:43:22 guenther Exp $ */
2
3/*- 2/*-
4 * Copyright (c) 1985, 1988, 1993 3 * Copyright (c) 1985, 1988, 1993
5 * The Regents of the University of California. All rights reserved. 4 * The Regents of the University of California. All rights reserved.
@@ -12,11 +11,7 @@
12 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software 14 * 3. Neither the name of the University nor the names of its contributors
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software 15 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission. 16 * without specific prior written permission.
22 * 17 *
@@ -53,15 +48,6 @@
53 * --Copyright-- 48 * --Copyright--
54 */ 49 */
55 50
56#if defined(LIBC_SCCS) && !defined(lint)
57#if 0
58static char sccsid[] = "@(#)gethostnamadr.c 8.1 (Berkeley) 6/4/93";
59static char rcsid[] = "$Id: gethnamaddr.c,v 4.9.1.1 1993/05/02 22:43:03 vixie Rel ";
60#else
61static char rcsid[] = "$NetBSD: gethostnamadr.c,v 1.13 1995/05/21 16:21:14 mycroft Exp $";
62#endif
63#endif /* LIBC_SCCS and not lint */
64
65#include <sys/param.h> 51#include <sys/param.h>
66#include <sys/socket.h> 52#include <sys/socket.h>
67#include <netinet/in.h> 53#include <netinet/in.h>
@@ -73,11 +59,17 @@ static char rcsid[] = "$NetBSD: gethostnamadr.c,v 1.13 1995/05/21 16:21:14 mycro
73#include <ctype.h> 59#include <ctype.h>
74#include <errno.h> 60#include <errno.h>
75#include <string.h> 61#include <string.h>
62#include <syslog.h>
63#include <stdlib.h>
76#ifdef YP 64#ifdef YP
77#include <rpc/rpc.h> 65#include <rpc/rpc.h>
78#include <rpcsvc/yp_prot.h> 66#include <rpcsvc/yp.h>
79#include <rpcsvc/ypclnt.h> 67#include <rpcsvc/ypclnt.h>
68#include "ypinternal.h"
80#endif 69#endif
70#include "thread_private.h"
71
72#define MULTI_PTRS_ARE_ALIASES 1 /* XXX - experimental */
81 73
82#define MAXALIASES 35 74#define MAXALIASES 35
83#define MAXADDRS 35 75#define MAXADDRS 35
@@ -91,47 +83,101 @@ static char *__ypdomain;
91static struct hostent host; 83static struct hostent host;
92static char *host_aliases[MAXALIASES]; 84static char *host_aliases[MAXALIASES];
93static char hostbuf[BUFSIZ+1]; 85static char hostbuf[BUFSIZ+1];
94static struct in_addr host_addr; 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
95static FILE *hostf = NULL; 91static FILE *hostf = NULL;
96static int stayopen = 0; 92static int stayopen = 0;
97 93
98#if PACKETSZ > 1024 94static void map_v4v6_address(const char *src, char *dst);
99#define MAXPACKET PACKETSZ 95static void map_v4v6_hostent(struct hostent *hp, char **bp, char *);
100#else 96
101#define MAXPACKET 1024 97#ifdef RESOLVSORT
98static void addrsort(char **, int);
102#endif 99#endif
103 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
104typedef union { 108typedef union {
105 HEADER hdr; 109 HEADER hdr;
106 u_char buf[MAXPACKET]; 110 u_char buf[MAXPACKET];
107} querybuf; 111} querybuf;
108 112
109typedef union { 113typedef union {
110 int32_t al; 114 int32_t al;
111 char ac; 115 char ac;
112} align; 116} align;
113 117
114static int qcomp __P((struct in_addr **, struct in_addr **)); 118static struct hostent *getanswer(const querybuf *, int, const char *, int);
115static struct hostent *getanswer __P((querybuf *, int, int));
116 119
117extern int h_errno; 120extern int h_errno;
118 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
119static struct hostent * 148static struct hostent *
120getanswer(answer, anslen, iquery) 149getanswer(const querybuf *answer, int anslen, const char *qname, int qtype)
121 querybuf *answer;
122 int anslen;
123 int iquery;
124{ 150{
125 register HEADER *hp; 151 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
126 register u_char *cp; 152 const HEADER *hp;
127 register int n; 153 const u_char *cp, *eom;
128 u_char *eom; 154 char tbuf[MAXDNAME];
129 char *bp, **ap; 155 char *bp, **ap, **hap, *ep;
130 int type, class, buflen, ancount, qdcount; 156 int type, class, ancount, qdcount, n;
131 int haveanswer, getclass = C_ANY; 157 int haveanswer, had_error, toobig = 0;
132 char **hap; 158 const char *tname;
159 int (*name_ok)(const char *);
133 160
161 tname = qname;
162 host.h_name = NULL;
134 eom = answer->buf + anslen; 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 }
135 /* 181 /*
136 * find first satisfactory answer 182 * find first satisfactory answer
137 */ 183 */
@@ -139,31 +185,27 @@ getanswer(answer, anslen, iquery)
139 ancount = ntohs(hp->ancount); 185 ancount = ntohs(hp->ancount);
140 qdcount = ntohs(hp->qdcount); 186 qdcount = ntohs(hp->qdcount);
141 bp = hostbuf; 187 bp = hostbuf;
142 buflen = sizeof(hostbuf); 188 ep = hostbuf + sizeof hostbuf;
143 cp = answer->buf + sizeof(HEADER); 189 cp = answer->buf + HFIXEDSZ;
144 if (qdcount) { 190 if (qdcount != 1) {
145 if (iquery) { 191 h_errno = NO_RECOVERY;
146 if ((n = dn_expand((u_char *)answer->buf, 192 return (NULL);
147 (u_char *)eom, (u_char *)cp, (u_char *)bp, 193 }
148 buflen)) < 0) { 194 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
149 h_errno = NO_RECOVERY; 195 if ((n < 0) || !(*name_ok)(bp)) {
150 return ((struct hostent *) NULL); 196 h_errno = NO_RECOVERY;
151 } 197 return (NULL);
152 cp += n + QFIXEDSZ; 198 }
153 host.h_name = bp; 199 cp += n + QFIXEDSZ;
154 n = strlen(bp) + 1; 200 if (qtype == T_A || qtype == T_AAAA) {
155 bp += n; 201 /* res_send() has already verified that the query name is the
156 buflen -= n; 202 * same as the one we sent; this just gets the expanded name
157 } else 203 * (i.e., with the succeeding search-domain tacked on).
158 cp += __dn_skipname(cp, eom) + QFIXEDSZ; 204 */
159 while (--qdcount > 0) 205 host.h_name = bp;
160 cp += __dn_skipname(cp, eom) + QFIXEDSZ; 206 bp += strlen(bp) + 1; /* for the \0 */
161 } else if (iquery) { 207 /* The qname can be abbreviated, but h_name is now absolute. */
162 if (hp->aa) 208 qname = host.h_name;
163 h_errno = HOST_NOT_FOUND;
164 else
165 h_errno = TRY_AGAIN;
166 return ((struct hostent *) NULL);
167 } 209 }
168 ap = host_aliases; 210 ap = host_aliases;
169 *ap = NULL; 211 *ap = NULL;
@@ -172,103 +214,325 @@ getanswer(answer, anslen, iquery)
172 *hap = NULL; 214 *hap = NULL;
173 host.h_addr_list = h_addr_ptrs; 215 host.h_addr_list = h_addr_ptrs;
174 haveanswer = 0; 216 haveanswer = 0;
175 while (--ancount >= 0 && cp < eom) { 217 had_error = 0;
176 if ((n = dn_expand((u_char *)answer->buf, (u_char *)eom, 218 while (ancount-- > 0 && cp < eom && !had_error) {
177 (u_char *)cp, (u_char *)bp, buflen)) < 0) 219 size_t len;
220
221 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
222 if ((n < 0) || !(*name_ok)(bp)) {
223 had_error++;
224 continue;
225 }
226 cp += n; /* name */
227 if (cp >= eom)
178 break; 228 break;
179 cp += n;
180 type = _getshort(cp); 229 type = _getshort(cp);
181 cp += sizeof(u_int16_t); 230 cp += INT16SZ; /* type */
231 if (cp >= eom)
232 break;
182 class = _getshort(cp); 233 class = _getshort(cp);
183 cp += sizeof(u_int16_t) + sizeof(u_int32_t); 234 cp += INT16SZ + INT32SZ; /* class, TTL */
235 if (cp >= eom)
236 break;
184 n = _getshort(cp); 237 n = _getshort(cp);
185 cp += sizeof(u_int16_t); 238 cp += INT16SZ; /* len */
186 if (type == T_CNAME) { 239 if (cp >= eom)
240 break;
241 if (type == T_SIG || type == T_RRSIG) {
242 /* XXX - ignore signatures as we don't use them yet */
187 cp += n; 243 cp += n;
188 if (ap >= &host_aliases[MAXALIASES-1])
189 continue;
190 *ap++ = bp;
191 n = strlen(bp) + 1;
192 bp += n;
193 buflen -= n;
194 continue; 244 continue;
195 } 245 }
196 if (iquery && type == T_PTR) { 246 if (class != C_IN) {
197 if ((n = dn_expand((u_char *)answer->buf, 247 /* XXX - debug? syslog? */
198 (u_char *)eom, (u_char *)cp, (u_char *)bp,
199 buflen)) < 0)
200 break;
201 cp += n; 248 cp += n;
249 continue; /* XXX - had_error++ ? */
250 }
251 if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) {
252 if (ap >= &host_aliases[MAXALIASES-1])
253 continue;
254 n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
255 if ((n < 0) || !(*name_ok)(tbuf)) {
256 had_error++;
257 continue;
258 }
259 cp += n;
260 /* Store alias. */
261 *ap++ = bp;
262 bp += strlen(bp) + 1; /* for the \0 */
263 /* Get canonical name. */
264 len = strlen(tbuf) + 1; /* for the \0 */
265 if (len > ep - bp) {
266 had_error++;
267 continue;
268 }
269 strlcpy(bp, tbuf, ep - bp);
202 host.h_name = bp; 270 host.h_name = bp;
203 return(&host); 271 bp += len;
272 continue;
204 } 273 }
205 if (iquery || type != T_A) { 274 if (qtype == T_PTR && type == T_CNAME) {
206#ifdef DEBUG 275 n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
207 if (_res.options & RES_DEBUG) 276#ifdef USE_RESOLV_NAME_OK
208 printf("unexpected answer type %d, size %d\n", 277 if ((n < 0) || !res_hnok(tbuf)) {
209 type, n); 278#else
279 if ((n < 0) || !_hokchar(tbuf)) {
210#endif 280#endif
281 had_error++;
282 continue;
283 }
211 cp += n; 284 cp += n;
285 /* Get canonical name. */
286 len = strlen(tbuf) + 1; /* for the \0 */
287 if (len > ep - bp) {
288 had_error++;
289 continue;
290 }
291 strlcpy(bp, tbuf, ep - bp);
292 tname = bp;
293 bp += len;
212 continue; 294 continue;
213 } 295 }
214 if (haveanswer) { 296 if (type != qtype) {
215 if (n != host.h_length) { 297#ifndef NO_LOG_BAD_DNS_RESPONSES
298 syslog(LOG_NOTICE|LOG_AUTH,
299 "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
300 qname, p_class(C_IN), p_type(qtype),
301 p_type(type));
302#endif /* NO_LOG_BAD_DNS_RESPONSES */
303 cp += n;
304 continue; /* XXX - had_error++ ? */
305 }
306 switch (type) {
307 case T_PTR:
308 if (strcasecmp(tname, bp) != 0) {
309 syslog(LOG_NOTICE|LOG_AUTH,
310 AskedForGot, qname, bp);
216 cp += n; 311 cp += n;
217 continue; 312 continue; /* XXX - had_error++ ? */
313 }
314 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
315#ifdef USE_RESOLV_NAME_OK
316 if ((n < 0) || !res_hnok(bp)) {
317#else
318 if ((n < 0) || !_hokchar(bp)) {
319#endif
320 had_error++;
321 break;
322 }
323#if MULTI_PTRS_ARE_ALIASES
324 cp += n;
325 if (!haveanswer)
326 host.h_name = bp;
327 else if (ap < &host_aliases[MAXALIASES-1])
328 *ap++ = bp;
329 else
330 n = -1;
331 if (n != -1) {
332 n = strlen(bp) + 1; /* for the \0 */
333 bp += n;
334 }
335 break;
336#else
337 host.h_name = bp;
338 if (_resp->options & RES_USE_INET6) {
339 n = strlen(bp) + 1; /* for the \0 */
340 bp += n;
341 map_v4v6_hostent(&host, &bp, ep);
342 }
343 h_errno = NETDB_SUCCESS;
344 return (&host);
345#endif
346 case T_A:
347 case T_AAAA:
348 if (strcasecmp(host.h_name, bp) != 0) {
349 syslog(LOG_NOTICE|LOG_AUTH,
350 AskedForGot, host.h_name, bp);
351 cp += n;
352 continue; /* XXX - had_error++ ? */
218 } 353 }
219 if (class != getclass) { 354 if (n != host.h_length) {
220 cp += n; 355 cp += n;
221 continue; 356 continue;
222 } 357 }
223 } else { 358 if (type == T_AAAA) {
224 host.h_length = n; 359 struct in6_addr in6;
225 getclass = class; 360 memcpy(&in6, cp, IN6ADDRSZ);
226 host.h_addrtype = (class == C_IN) ? AF_INET : AF_UNSPEC; 361 if (IN6_IS_ADDR_V4MAPPED(&in6)) {
227 if (!iquery) { 362 cp += n;
363 continue;
364 }
365 }
366 if (!haveanswer) {
228 host.h_name = bp; 367 host.h_name = bp;
229 bp += strlen(bp) + 1; 368 bp += strlen(bp) + 1; /* for the \0 */
230 } 369 }
231 }
232 370
233 bp += sizeof(align) - ((u_long)bp % sizeof(align)); 371 bp += sizeof(align) - ((u_long)bp % sizeof(align));
234 372
235 if (bp + n >= &hostbuf[sizeof(hostbuf)]) { 373 if (bp + n >= &hostbuf[sizeof hostbuf]) {
236#ifdef DEBUG 374#ifdef DEBUG
237 if (_res.options & RES_DEBUG) 375 if (_resp->options & RES_DEBUG)
238 printf("size (%d) too big\n", n); 376 printf("size (%d) too big\n", n);
239#endif 377#endif
378 had_error++;
379 continue;
380 }
381 if (hap >= &h_addr_ptrs[MAXADDRS-1]) {
382 if (!toobig++)
383#ifdef DEBUG
384 if (_resp->options & RES_DEBUG)
385 printf("Too many addresses (%d)\n", MAXADDRS);
386#endif
387 cp += n;
388 continue;
389 }
390 bcopy(cp, *hap++ = bp, n);
391 bp += n;
392 cp += n;
240 break; 393 break;
241 } 394 }
242 bcopy(cp, *hap++ = bp, n); 395 if (!had_error)
243 bp +=n; 396 haveanswer++;
244 cp += n;
245 haveanswer++;
246 } 397 }
247 if (haveanswer) { 398 if (haveanswer) {
248 *ap = NULL; 399 *ap = NULL;
249 *hap = NULL; 400 *hap = NULL;
250 if (_res.nsort) { 401# if defined(RESOLVSORT)
251 qsort(host.h_addr_list, haveanswer, 402 /*
252 sizeof(struct in_addr), 403 * Note: we sort even if host can take only one address
253 (int (*)__P((const void *, const void *)))qcomp); 404 * in its return structures - should give it the "best"
405 * address in that case, not some random one
406 */
407 if (_resp->nsort && haveanswer > 1 && qtype == T_A)
408 addrsort(h_addr_ptrs, haveanswer);
409# endif /*RESOLVSORT*/
410 if (!host.h_name) {
411 size_t len;
412
413 len = strlen(qname) + 1;
414 if (len > ep - bp) /* for the \0 */
415 goto try_again;
416 strlcpy(bp, qname, ep - bp);
417 host.h_name = bp;
418 bp += len;
254 } 419 }
420 if (_resp->options & RES_USE_INET6)
421 map_v4v6_hostent(&host, &bp, ep);
422 h_errno = NETDB_SUCCESS;
255 return (&host); 423 return (&host);
256 } else {
257 h_errno = TRY_AGAIN;
258 return ((struct hostent *) NULL);
259 } 424 }
425 try_again:
426 h_errno = TRY_AGAIN;
427 return (NULL);
260} 428}
261 429
430#ifdef notyet
431/*
432 * XXX This is an extremely bogus implementation.
433 *
434 * FreeBSD has this interface:
435 * int gethostbyaddr_r(const char *addr, int len, int type,
436 * struct hostent *result, struct hostent_data *buffer)
437 */
438
439struct hostent *
440gethostbyname_r(const char *name, struct hostent *hp, char *buf, int buflen,
441 int *errorp)
442{
443 struct hostent *res;
444
445 res = gethostbyname(name);
446 *errorp = h_errno;
447 if (res == NULL)
448 return NULL;
449 memcpy(hp, res, sizeof *hp); /* XXX not sufficient */
450 return hp;
451}
452
453/*
454 * XXX This is an extremely bogus implementation.
455 */
262struct hostent * 456struct hostent *
263gethostbyname(name) 457gethostbyaddr_r(const char *addr, int len, int af, struct hostent *he,
264 const char *name; 458 char *buf, int buflen, int *errorp)
265{ 459{
266 querybuf buf; 460 struct hostent * res;
267 register const char *cp; 461
268 int n, i; 462 res = gethostbyaddr(addr, len, af);
269 extern struct hostent *_gethtbyname(), *_yp_gethtbyname(); 463 *errorp = h_errno;
270 register struct hostent *hp; 464 if (res == NULL)
465 return NULL;
466 memcpy(he, res, sizeof *he); /* XXX not sufficient */
467 return he;
468}
469
470/* XXX RFC2133 expects a gethostbyname2_r() -- unimplemented */
471#endif
472
473struct hostent *
474gethostbyname(const char *name)
475{
476 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
477 struct hostent *hp;
478 extern struct hostent *_gethtbyname2(const char *, int);
479
480 if (_res_init(0) == -1)
481 hp = _gethtbyname2(name, AF_INET);
482
483 else if (_resp->options & RES_USE_INET6) {
484 hp = gethostbyname2(name, AF_INET6);
485 if (hp == NULL)
486 hp = gethostbyname2(name, AF_INET);
487 }
488 else
489 hp = gethostbyname2(name, AF_INET);
490 return hp;
491}
492
493struct hostent *
494gethostbyname2(const char *name, int af)
495{
496 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
497 querybuf *buf;
498 const char *cp;
499 char *bp, *ep;
500 int n, size, type, i;
501 struct hostent *hp;
271 char lookups[MAXDNSLUS]; 502 char lookups[MAXDNSLUS];
503 extern struct hostent *_gethtbyname2(const char *, int);
504#ifdef YP
505 extern struct hostent *_yp_gethtbyname(const char *);
506#endif
507
508 if (_res_init(0) == -1)
509 return (_gethtbyname2(name, af));
510
511 switch (af) {
512 case AF_INET:
513 size = INADDRSZ;
514 type = T_A;
515 break;
516 case AF_INET6:
517 size = IN6ADDRSZ;
518 type = T_AAAA;
519 break;
520 default:
521 h_errno = NETDB_INTERNAL;
522 errno = EAFNOSUPPORT;
523 return (NULL);
524 }
525
526 host.h_addrtype = af;
527 host.h_length = size;
528
529 /*
530 * if there aren't any dots, it could be a user-level alias.
531 * this is also done in res_query() since we are not the only
532 * function that looks up host names.
533 */
534 if (!strchr(name, '.') && (cp = __hostalias(name)))
535 name = cp;
272 536
273 /* 537 /*
274 * disallow names consisting only of digits/dots, unless 538 * disallow names consisting only of digits/dots, unless
@@ -284,122 +548,229 @@ gethostbyname(name)
284 * Fake up a hostent as if we'd actually 548 * Fake up a hostent as if we'd actually
285 * done a lookup. 549 * done a lookup.
286 */ 550 */
287 if (!inet_aton(name, &host_addr)) { 551 if (inet_pton(af, name, host_addr) <= 0) {
288 h_errno = HOST_NOT_FOUND; 552 h_errno = HOST_NOT_FOUND;
289 return((struct hostent *) NULL); 553 return (NULL);
290 } 554 }
291 host.h_name = (char *)name; 555 strlcpy(hostbuf, name, MAXHOSTNAMELEN);
556 bp = hostbuf + MAXHOSTNAMELEN;
557 ep = hostbuf + sizeof(hostbuf);
558 host.h_name = hostbuf;
292 host.h_aliases = host_aliases; 559 host.h_aliases = host_aliases;
293 host_aliases[0] = NULL; 560 host_aliases[0] = NULL;
294 host.h_addrtype = AF_INET; 561 h_addr_ptrs[0] = (char *)host_addr;
295 host.h_length = sizeof(u_int32_t);
296 h_addr_ptrs[0] = (char *)&host_addr;
297 h_addr_ptrs[1] = NULL; 562 h_addr_ptrs[1] = NULL;
298 host.h_addr_list = h_addr_ptrs; 563 host.h_addr_list = h_addr_ptrs;
564 if (_resp->options & RES_USE_INET6)
565 map_v4v6_hostent(&host, &bp, ep);
566 h_errno = NETDB_SUCCESS;
299 return (&host); 567 return (&host);
300 } 568 }
301 if (!isdigit(*cp) && *cp != '.') 569 if (!isdigit(*cp) && *cp != '.')
302 break; 570 break;
303 } 571 }
572 if ((isxdigit(name[0]) && strchr(name, ':') != NULL) ||
573 name[0] == ':')
574 for (cp = name;; ++cp) {
575 if (!*cp) {
576 if (*--cp == '.')
577 break;
578 /*
579 * All-IPv6-legal, no dot at the end.
580 * Fake up a hostent as if we'd actually
581 * done a lookup.
582 */
583 if (inet_pton(af, name, host_addr) <= 0) {
584 h_errno = HOST_NOT_FOUND;
585 return (NULL);
586 }
587 strlcpy(hostbuf, name, MAXHOSTNAMELEN);
588 bp = hostbuf + MAXHOSTNAMELEN;
589 ep = hostbuf + sizeof(hostbuf);
590 host.h_name = hostbuf;
591 host.h_aliases = host_aliases;
592 host_aliases[0] = NULL;
593 h_addr_ptrs[0] = (char *)host_addr;
594 h_addr_ptrs[1] = NULL;
595 host.h_addr_list = h_addr_ptrs;
596 h_errno = NETDB_SUCCESS;
597 return (&host);
598 }
599 if (!isxdigit(*cp) && *cp != ':' && *cp != '.')
600 break;
601 }
304 602
305 if ((_res.options & RES_INIT) == 0 && res_init() == -1) 603 bcopy(_resp->lookups, lookups, sizeof lookups);
306 return (_gethtbyname(name));
307
308 bcopy(_res.lookups, lookups, sizeof lookups);
309 if (lookups[0] == '\0') 604 if (lookups[0] == '\0')
310 strncpy(lookups, "bf", sizeof lookups); 605 strlcpy(lookups, "bf", sizeof lookups);
311 606
312 hp = (struct hostent *)NULL; 607 hp = (struct hostent *)NULL;
313 for (i = 0; i < MAXDNSLUS && hp == NULL && lookups[i]; i++) { 608 for (i = 0; i < MAXDNSLUS && hp == NULL && lookups[i]; i++) {
314 switch (lookups[i]) { 609 switch (lookups[i]) {
315#ifdef YP 610#ifdef YP
316 case 'y': 611 case 'y':
317 hp = _yp_gethtbyname(name); 612 /* YP only supports AF_INET. */
613 if (af == AF_INET)
614 hp = _yp_gethtbyname(name);
318 break; 615 break;
319#endif 616#endif
320 case 'b': 617 case 'b':
321 if ((n = res_search(name, C_IN, T_A, buf.buf, 618 buf = malloc(sizeof(*buf));
322 sizeof(buf))) < 0) { 619 if (buf == NULL)
620 break;
621 if ((n = res_search(name, C_IN, type, buf->buf,
622 sizeof(buf->buf))) < 0) {
623 free(buf);
323#ifdef DEBUG 624#ifdef DEBUG
324 if (_res.options & RES_DEBUG) 625 if (_resp->options & RES_DEBUG)
325 printf("res_search failed\n"); 626 printf("res_search failed\n");
326#endif 627#endif
327 break; 628 break;
328 } 629 }
329 hp = getanswer(&buf, n, 0); 630 hp = getanswer(buf, n, name, type);
631 free(buf);
330 break; 632 break;
331 case 'f': 633 case 'f':
332 hp = _gethtbyname(name); 634 hp = _gethtbyname2(name, af);
333 break; 635 break;
334 } 636 }
335 } 637 }
638 /* XXX h_errno not correct in all cases... */
336 return (hp); 639 return (hp);
337} 640}
338 641
339struct hostent * 642struct hostent *
340gethostbyaddr(addr, len, type) 643gethostbyaddr(const void *addr, socklen_t len, int af)
341 const char *addr;
342 int len, type;
343{ 644{
344 int n, i; 645 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
345 querybuf buf; 646 const u_char *uaddr = (const u_char *)addr;
346 register struct hostent *hp; 647 int n, size, i;
347 char qbuf[MAXDNAME]; 648 querybuf *buf;
348 extern struct hostent *_gethtbyaddr(), *_yp_gethtbyaddr(); 649 struct hostent *hp;
650 char qbuf[MAXDNAME+1], *qp, *ep;
349 char lookups[MAXDNSLUS]; 651 char lookups[MAXDNSLUS];
652 struct hostent *res;
653 extern struct hostent *_gethtbyaddr(const void *, socklen_t, int);
654#ifdef YP
655 extern struct hostent *_yp_gethtbyaddr(const void *);
656#endif
350 657
351 if (type != AF_INET) 658 if (_res_init(0) == -1) {
352 return ((struct hostent *) NULL); 659 res = _gethtbyaddr(addr, len, af);
353 (void)sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa", 660 return (res);
354 ((unsigned)addr[3] & 0xff), 661 }
355 ((unsigned)addr[2] & 0xff), 662
356 ((unsigned)addr[1] & 0xff), 663 if (af == AF_INET6 && len == IN6ADDRSZ &&
357 ((unsigned)addr[0] & 0xff)); 664 (IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)uaddr) ||
358 665 IN6_IS_ADDR_SITELOCAL((struct in6_addr *)uaddr))) {
359 if ((_res.options & RES_INIT) == 0 && res_init() == -1) 666 h_errno = HOST_NOT_FOUND;
360 return (_gethtbyaddr(addr, len, type)); 667 return (NULL);
361 668 }
362 bcopy(_res.lookups, lookups, sizeof lookups); 669 if (af == AF_INET6 && len == IN6ADDRSZ &&
670 (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)uaddr) ||
671 IN6_IS_ADDR_V4COMPAT((struct in6_addr *)uaddr))) {
672 /* Unmap. */
673 uaddr += IN6ADDRSZ - INADDRSZ;
674 af = AF_INET;
675 len = INADDRSZ;
676 }
677 switch (af) {
678 case AF_INET:
679 size = INADDRSZ;
680 break;
681 case AF_INET6:
682 size = IN6ADDRSZ;
683 break;
684 default:
685 errno = EAFNOSUPPORT;
686 h_errno = NETDB_INTERNAL;
687 return (NULL);
688 }
689 if (size != len) {
690 errno = EINVAL;
691 h_errno = NETDB_INTERNAL;
692 return (NULL);
693 }
694 ep = qbuf + sizeof(qbuf);
695 switch (af) {
696 case AF_INET:
697 (void) snprintf(qbuf, sizeof qbuf, "%u.%u.%u.%u.in-addr.arpa",
698 (uaddr[3] & 0xff), (uaddr[2] & 0xff),
699 (uaddr[1] & 0xff), (uaddr[0] & 0xff));
700 break;
701 case AF_INET6:
702 qp = qbuf;
703 for (n = IN6ADDRSZ - 1; n >= 0; n--) {
704 i = snprintf(qp, ep - qp, "%x.%x.",
705 uaddr[n] & 0xf, (uaddr[n] >> 4) & 0xf);
706 if (i <= 0 || i >= ep - qp) {
707 errno = EINVAL;
708 h_errno = NETDB_INTERNAL;
709 return (NULL);
710 }
711 qp += i;
712 }
713 strlcpy(qp, "ip6.arpa", ep - qp);
714 break;
715 }
716
717 bcopy(_resp->lookups, lookups, sizeof lookups);
363 if (lookups[0] == '\0') 718 if (lookups[0] == '\0')
364 strncpy(lookups, "bf", sizeof lookups); 719 strlcpy(lookups, "bf", sizeof lookups);
365 720
366 hp = (struct hostent *)NULL; 721 hp = (struct hostent *)NULL;
367 for (i = 0; i < MAXDNSLUS && hp == NULL && lookups[i]; i++) { 722 for (i = 0; i < MAXDNSLUS && hp == NULL && lookups[i]; i++) {
368 switch (lookups[i]) { 723 switch (lookups[i]) {
369#ifdef YP 724#ifdef YP
370 case 'y': 725 case 'y':
371 hp = _yp_gethtbyaddr(addr, len, type); 726 /* YP only supports AF_INET. */
727 if (af == AF_INET)
728 hp = _yp_gethtbyaddr(uaddr);
372 break; 729 break;
373#endif 730#endif
374 case 'b': 731 case 'b':
375 n = res_query(qbuf, C_IN, T_PTR, (char *)&buf, sizeof(buf)); 732 buf = malloc(sizeof(*buf));
733 if (!buf)
734 break;
735 n = res_query(qbuf, C_IN, T_PTR, buf->buf,
736 sizeof(buf->buf));
376 if (n < 0) { 737 if (n < 0) {
738 free(buf);
377#ifdef DEBUG 739#ifdef DEBUG
378 if (_res.options & RES_DEBUG) 740 if (_resp->options & RES_DEBUG)
379 printf("res_query failed\n"); 741 printf("res_query failed\n");
380#endif 742#endif
381 break; 743 break;
382 } 744 }
383 hp = getanswer(&buf, n, 1); 745 if (!(hp = getanswer(buf, n, qbuf, T_PTR))) {
384 if (hp == NULL) 746 free(buf);
385 break; 747 break;
386 hp->h_addrtype = type; 748 }
749 free(buf);
750 hp->h_addrtype = af;
387 hp->h_length = len; 751 hp->h_length = len;
388 h_addr_ptrs[0] = (char *)&host_addr; 752 bcopy(uaddr, host_addr, len);
389 h_addr_ptrs[1] = (char *)0; 753 h_addr_ptrs[0] = (char *)host_addr;
390 host_addr = *(struct in_addr *)addr; 754 h_addr_ptrs[1] = NULL;
755 if (af == AF_INET && (_resp->options & RES_USE_INET6)) {
756 map_v4v6_address((char*)host_addr,
757 (char*)host_addr);
758 hp->h_addrtype = AF_INET6;
759 hp->h_length = IN6ADDRSZ;
760 }
761 h_errno = NETDB_SUCCESS;
391 break; 762 break;
392 case 'f': 763 case 'f':
393 hp = _gethtbyaddr(addr, len, type); 764 hp = _gethtbyaddr(uaddr, len, af);
394 break; 765 break;
395 } 766 }
396 } 767 }
768 /* XXX h_errno not correct in all cases... */
397 return (hp); 769 return (hp);
398} 770}
399 771
400void 772void
401_sethtent(f) 773_sethtent(int f)
402 int f;
403{ 774{
404 if (hostf == NULL) 775 if (hostf == NULL)
405 hostf = fopen(_PATH_HOSTS, "r" ); 776 hostf = fopen(_PATH_HOSTS, "r" );
@@ -409,7 +780,7 @@ _sethtent(f)
409} 780}
410 781
411void 782void
412_endhtent() 783_endhtent(void)
413{ 784{
414 if (hostf && !stayopen) { 785 if (hostf && !stayopen) {
415 (void) fclose(hostf); 786 (void) fclose(hostf);
@@ -417,40 +788,66 @@ _endhtent()
417 } 788 }
418} 789}
419 790
420struct hostent * 791static struct hostent *
421_gethtent() 792_gethtent(void)
422{ 793{
423 char *p; 794 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
424 register char *cp, **q; 795 char *p, *cp, **q;
796 int af;
797 size_t len;
425 798
426 if (hostf == NULL && (hostf = fopen(_PATH_HOSTS, "r" )) == NULL) 799 if (!hostf && !(hostf = fopen(_PATH_HOSTS, "r" ))) {
800 h_errno = NETDB_INTERNAL;
427 return (NULL); 801 return (NULL);
428again: 802 }
429 if ((p = fgets(hostbuf, BUFSIZ, hostf)) == NULL) 803 again:
804 if ((p = fgetln(hostf, &len)) == NULL) {
805 h_errno = HOST_NOT_FOUND;
430 return (NULL); 806 return (NULL);
431 if (*p == '#') 807 }
808 if (p[len-1] == '\n')
809 len--;
810 if (len >= sizeof(hostbuf) || len == 0)
432 goto again; 811 goto again;
433 cp = strpbrk(p, "#\n"); 812 p = memcpy(hostbuf, p, len);
434 if (cp == NULL) 813 hostbuf[len] = '\0';
814 if (*p == '#')
435 goto again; 815 goto again;
436 *cp = '\0'; 816 if ((cp = strchr(p, '#')))
437 cp = strpbrk(p, " \t"); 817 *cp = '\0';
438 if (cp == NULL) 818 if (!(cp = strpbrk(p, " \t")))
439 goto again; 819 goto again;
440 *cp++ = '\0'; 820 *cp++ = '\0';
441 /* THIS STUFF IS INTERNET SPECIFIC */ 821 if (inet_pton(AF_INET6, p, host_addr) > 0) {
442 h_addr_ptrs[0] = (char *)&host_addr; 822 af = AF_INET6;
823 len = IN6ADDRSZ;
824 } else if (inet_pton(AF_INET, p, host_addr) > 0) {
825 if (_resp->options & RES_USE_INET6) {
826 map_v4v6_address((char*)host_addr, (char*)host_addr);
827 af = AF_INET6;
828 len = IN6ADDRSZ;
829 } else {
830 af = AF_INET;
831 len = INADDRSZ;
832 }
833 } else {
834 goto again;
835 }
836 /* if this is not something we're looking for, skip it. */
837 if (host.h_addrtype != AF_UNSPEC && host.h_addrtype != af)
838 goto again;
839 if (host.h_length != 0 && host.h_length != len)
840 goto again;
841 h_addr_ptrs[0] = (char *)host_addr;
443 h_addr_ptrs[1] = NULL; 842 h_addr_ptrs[1] = NULL;
444 (void) inet_aton(p, &host_addr);
445 host.h_addr_list = h_addr_ptrs; 843 host.h_addr_list = h_addr_ptrs;
446 host.h_length = sizeof(u_int32_t); 844 host.h_length = len;
447 host.h_addrtype = AF_INET; 845 host.h_addrtype = af;
448 while (*cp == ' ' || *cp == '\t') 846 while (*cp == ' ' || *cp == '\t')
449 cp++; 847 cp++;
450 host.h_name = cp; 848 host.h_name = cp;
451 q = host.h_aliases = host_aliases; 849 q = host.h_aliases = host_aliases;
452 cp = strpbrk(cp, " \t"); 850 if ((cp = strpbrk(cp, " \t")))
453 if (cp != NULL)
454 *cp++ = '\0'; 851 *cp++ = '\0';
455 while (cp && *cp) { 852 while (cp && *cp) {
456 if (*cp == ' ' || *cp == '\t') { 853 if (*cp == ' ' || *cp == '\t') {
@@ -459,74 +856,61 @@ again:
459 } 856 }
460 if (q < &host_aliases[MAXALIASES - 1]) 857 if (q < &host_aliases[MAXALIASES - 1])
461 *q++ = cp; 858 *q++ = cp;
462 cp = strpbrk(cp, " \t"); 859 if ((cp = strpbrk(cp, " \t")))
463 if (cp != NULL)
464 *cp++ = '\0'; 860 *cp++ = '\0';
465 } 861 }
466 *q = NULL; 862 *q = NULL;
863 if (_resp->options & RES_USE_INET6) {
864 char *bp = hostbuf;
865 char *ep = hostbuf + sizeof hostbuf;
866
867 map_v4v6_hostent(&host, &bp, ep);
868 }
869 h_errno = NETDB_SUCCESS;
467 return (&host); 870 return (&host);
468} 871}
469 872
470struct hostent * 873struct hostent *
471_gethtbyname(name) 874_gethtbyname2(const char *name, int af)
472 char *name;
473{ 875{
474 register struct hostent *p; 876 struct hostent *p;
475 register char **cp; 877 char **cp;
476 878
477 _sethtent(0); 879 _sethtent(0);
478 while (p = _gethtent()) { 880 while ((p = _gethtent())) {
881 if (p->h_addrtype != af)
882 continue;
479 if (strcasecmp(p->h_name, name) == 0) 883 if (strcasecmp(p->h_name, name) == 0)
480 break; 884 break;
481 for (cp = p->h_aliases; *cp != 0; cp++) 885 for (cp = p->h_aliases; *cp != 0; cp++)
482 if (strcasecmp(*cp, name) == 0) 886 if (strcasecmp(*cp, name) == 0)
483 goto found; 887 goto found;
484 } 888 }
485found: 889 found:
486 _endhtent(); 890 _endhtent();
487 if (p==NULL)
488 h_errno = HOST_NOT_FOUND;
489 return (p); 891 return (p);
490} 892}
491 893
492struct hostent * 894struct hostent *
493_gethtbyaddr(addr, len, type) 895_gethtbyaddr(const void *addr, socklen_t len, int af)
494 const char *addr;
495 int len, type;
496{ 896{
497 register struct hostent *p; 897 struct hostent *p;
898
899 host.h_length = len;
900 host.h_addrtype = af;
498 901
499 _sethtent(0); 902 _sethtent(0);
500 while (p = _gethtent()) 903 while ((p = _gethtent()))
501 if (p->h_addrtype == type && !bcmp(p->h_addr, addr, len)) 904 if (p->h_addrtype == af && p->h_length == len &&
905 !bcmp(p->h_addr, addr, len))
502 break; 906 break;
503 _endhtent(); 907 _endhtent();
504 if (p==NULL)
505 h_errno = HOST_NOT_FOUND;
506 return (p); 908 return (p);
507} 909}
508 910
509static int
510qcomp(a1, a2)
511 struct in_addr **a1, **a2;
512{
513 int pos1, pos2;
514
515 for (pos1 = 0; pos1 < _res.nsort; pos1++)
516 if (_res.sort_list[pos1].addr.s_addr ==
517 ((*a1)->s_addr & _res.sort_list[pos1].mask))
518 break;
519 for (pos2 = 0; pos2 < _res.nsort; pos2++)
520 if (_res.sort_list[pos2].addr.s_addr ==
521 ((*a2)->s_addr & _res.sort_list[pos2].mask))
522 break;
523 return pos1 - pos2;
524}
525
526#ifdef YP 911#ifdef YP
527struct hostent * 912struct hostent *
528_yphostent(line) 913_yphostent(char *line)
529 char *line;
530{ 914{
531 static struct in_addr host_addrs[MAXADDRS]; 915 static struct in_addr host_addrs[MAXADDRS];
532 char *p = line; 916 char *p = line;
@@ -537,21 +921,21 @@ _yphostent(line)
537 921
538 host.h_name = NULL; 922 host.h_name = NULL;
539 host.h_addr_list = h_addr_ptrs; 923 host.h_addr_list = h_addr_ptrs;
540 host.h_length = sizeof(u_int32_t); 924 host.h_length = INADDRSZ;
541 host.h_addrtype = AF_INET; 925 host.h_addrtype = AF_INET;
542 hap = h_addr_ptrs; 926 hap = h_addr_ptrs;
543 buf = host_addrs; 927 buf = host_addrs;
544 q = host.h_aliases = host_aliases; 928 q = host.h_aliases = host_aliases;
545 929
546nextline: 930nextline:
931 /* check for host_addrs overflow */
932 if (buf >= &host_addrs[sizeof(host_addrs) / sizeof(host_addrs[0])])
933 goto done;
934
547 more = 0; 935 more = 0;
548 cp = strpbrk(p, " \t"); 936 cp = strpbrk(p, " \t");
549 if (cp == NULL) { 937 if (cp == NULL)
550 if (host.h_name == NULL) 938 goto done;
551 return (NULL);
552 else
553 goto done;
554 }
555 *cp++ = '\0'; 939 *cp++ = '\0';
556 940
557 *hap++ = (char *)buf; 941 *hap++ = (char *)buf;
@@ -592,30 +976,28 @@ nextline:
592 *cp++ = '\0'; 976 *cp++ = '\0';
593 } 977 }
594done: 978done:
979 if (host.h_name == NULL)
980 return (NULL);
595 *q = NULL; 981 *q = NULL;
596 *hap = NULL; 982 *hap = NULL;
597 return (&host); 983 return (&host);
598} 984}
599 985
600struct hostent * 986struct hostent *
601_yp_gethtbyaddr(addr, len, type) 987_yp_gethtbyaddr(const void *addr)
602 const char *addr;
603 int len, type;
604{ 988{
605 struct hostent *hp = (struct hostent *)NULL; 989 struct hostent *hp = NULL;
990 const u_char *uaddr = (const u_char *)addr;
606 static char *__ypcurrent; 991 static char *__ypcurrent;
607 int __ypcurrentlen, r; 992 int __ypcurrentlen, r;
608 char name[sizeof("xxx.xxx.xxx.xxx") + 1]; 993 char name[sizeof("xxx.xxx.xxx.xxx")];
609 994
610 if (!__ypdomain) { 995 if (!__ypdomain) {
611 if (_yp_check(&__ypdomain) == 0) 996 if (_yp_check(&__ypdomain) == 0)
612 return (hp); 997 return (hp);
613 } 998 }
614 sprintf(name, "%u.%u.%u.%u", 999 snprintf(name, sizeof name, "%u.%u.%u.%u", (uaddr[0] & 0xff),
615 ((unsigned)addr[0] & 0xff), 1000 (uaddr[1] & 0xff), (uaddr[2] & 0xff), (uaddr[3] & 0xff));
616 ((unsigned)addr[1] & 0xff),
617 ((unsigned)addr[2] & 0xff),
618 ((unsigned)addr[3] & 0xff));
619 if (__ypcurrent) 1001 if (__ypcurrent)
620 free(__ypcurrent); 1002 free(__ypcurrent);
621 __ypcurrent = NULL; 1003 __ypcurrent = NULL;
@@ -629,13 +1011,14 @@ _yp_gethtbyaddr(addr, len, type)
629} 1011}
630 1012
631struct hostent * 1013struct hostent *
632_yp_gethtbyname(name) 1014_yp_gethtbyname(const char *name)
633 const char *name;
634{ 1015{
635 struct hostent *hp = (struct hostent *)NULL; 1016 struct hostent *hp = (struct hostent *)NULL;
636 static char *__ypcurrent; 1017 static char *__ypcurrent;
637 int __ypcurrentlen, r; 1018 int __ypcurrentlen, r;
638 1019
1020 if (strlen(name) >= MAXHOSTNAMELEN)
1021 return (NULL);
639 if (!__ypdomain) { 1022 if (!__ypdomain) {
640 if (_yp_check(&__ypdomain) == 0) 1023 if (_yp_check(&__ypdomain) == 0)
641 return (hp); 1024 return (hp);
@@ -645,10 +1028,104 @@ _yp_gethtbyname(name)
645 __ypcurrent = NULL; 1028 __ypcurrent = NULL;
646 r = yp_match(__ypdomain, "hosts.byname", name, 1029 r = yp_match(__ypdomain, "hosts.byname", name,
647 strlen(name), &__ypcurrent, &__ypcurrentlen); 1030 strlen(name), &__ypcurrent, &__ypcurrentlen);
648 if (r==0) 1031 if (r == 0)
649 hp = _yphostent(__ypcurrent); 1032 hp = _yphostent(__ypcurrent);
650 if (hp==NULL) 1033 if (hp == NULL)
651 h_errno = HOST_NOT_FOUND; 1034 h_errno = HOST_NOT_FOUND;
652 return (hp); 1035 return (hp);
653} 1036}
654#endif 1037#endif
1038
1039static void
1040map_v4v6_address(const char *src, char *dst)
1041{
1042 u_char *p = (u_char *)dst;
1043 char tmp[INADDRSZ];
1044 int i;
1045
1046 /* Stash a temporary copy so our caller can update in place. */
1047 bcopy(src, tmp, INADDRSZ);
1048 /* Mark this ipv6 addr as a mapped ipv4. */
1049 for (i = 0; i < 10; i++)
1050 *p++ = 0x00;
1051 *p++ = 0xff;
1052 *p++ = 0xff;
1053 /* Retrieve the saved copy and we're done. */
1054 bcopy(tmp, (void*)p, INADDRSZ);
1055}
1056
1057static void
1058map_v4v6_hostent(struct hostent *hp, char **bpp, char *ep)
1059{
1060 char **ap;
1061
1062 if (hp->h_addrtype != AF_INET || hp->h_length != INADDRSZ)
1063 return;
1064 hp->h_addrtype = AF_INET6;
1065 hp->h_length = IN6ADDRSZ;
1066 for (ap = hp->h_addr_list; *ap; ap++) {
1067 int i = sizeof(align) - ((u_long)*bpp % sizeof(align));
1068
1069 if (ep - *bpp < (i + IN6ADDRSZ)) {
1070 /* Out of memory. Truncate address list here. XXX */
1071 *ap = NULL;
1072 return;
1073 }
1074 *bpp += i;
1075 map_v4v6_address(*ap, *bpp);
1076 *ap = *bpp;
1077 *bpp += IN6ADDRSZ;
1078 }
1079}
1080
1081struct hostent *
1082gethostent(void)
1083{
1084 host.h_addrtype = AF_UNSPEC;
1085 host.h_length = 0;
1086 return (_gethtent());
1087}
1088
1089#ifdef RESOLVSORT
1090static void
1091addrsort(char **ap, int num)
1092{
1093 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
1094 int i, j;
1095 char **p;
1096 short aval[MAXADDRS];
1097 int needsort = 0;
1098
1099 p = ap;
1100 for (i = 0; i < num; i++, p++) {
1101 for (j = 0 ; (unsigned)j < _resp->nsort; j++)
1102 if (_resp->sort_list[j].addr.s_addr ==
1103 (((struct in_addr *)(*p))->s_addr &
1104 _resp->sort_list[j].mask))
1105 break;
1106 aval[i] = j;
1107 if (needsort == 0 && i > 0 && j < aval[i-1])
1108 needsort = i;
1109 }
1110 if (!needsort)
1111 return;
1112
1113 while (needsort < num) {
1114 for (j = needsort - 1; j >= 0; j--) {
1115 if (aval[j] > aval[j+1]) {
1116 char *hp;
1117
1118 i = aval[j];
1119 aval[j] = aval[j+1];
1120 aval[j+1] = i;
1121
1122 hp = ap[j];
1123 ap[j] = ap[j+1];
1124 ap[j+1] = hp;
1125 } else
1126 break;
1127 }
1128 needsort++;
1129 }
1130}
1131#endif
diff --git a/src/lib/libc/net/getifaddrs.3 b/src/lib/libc/net/getifaddrs.3
new file mode 100644
index 0000000000..f282e26960
--- /dev/null
+++ b/src/lib/libc/net/getifaddrs.3
@@ -0,0 +1,157 @@
1.\" $OpenBSD: getifaddrs.3,v 1.14 2007/05/31 19:19:30 jmc Exp $
2.\" BSDI getifaddrs.3,v 2.5 2000/02/23 14:51:59 dab Exp
3.\"
4.\" Copyright (c) 1995, 1999
5.\" Berkeley Software Design, Inc. All rights reserved.
6.\"
7.\" Redistribution and use in source and binary forms, with or without
8.\" modification, are permitted provided that the following conditions
9.\" are met:
10.\" 1. Redistributions of source code must retain the above copyright
11.\" notice, this list of conditions and the following disclaimer.
12.\"
13.\" THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
14.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16.\" ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
17.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23.\" SUCH DAMAGE.
24.Dd $Mdocdate: May 31 2007 $
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,
108.Fa ifa_data
109is
110.Dv NULL .
111.El
112.Pp
113The data returned by
114.Fn getifaddrs
115is dynamically allocated and should be freed using
116.Fn freeifaddrs
117when no longer needed.
118.Sh RETURN VALUES
119Upon successful completion, a value of 0 is returned.
120Otherwise, a value of \-1 is returned and
121.Va errno
122is set to indicate the error.
123.Sh ERRORS
124The
125.Fn getifaddrs
126may fail and set
127.Va errno
128for any of the errors specified for the library routines
129.Xr ioctl 2 ,
130.Xr socket 2 ,
131.Xr malloc 3 ,
132or
133.Xr sysctl 3 .
134.Sh SEE ALSO
135.Xr ioctl 2 ,
136.Xr socket 2 ,
137.Xr sysctl 3 ,
138.Xr networking 4 ,
139.Xr ifconfig 8
140.Sh HISTORY
141The
142.Fn getifaddrs
143function first appeared in BSDI BSD/OS.
144The function has been available on
145.Ox
146since
147.Ox 2.7 .
148.Sh BUGS
149If both
150.Aq Pa net/if.h
151and
152.Aq Pa ifaddrs.h
153are being included,
154.Aq Pa net/if.h
155.Em must
156be included before
157.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..6f7ea15721
--- /dev/null
+++ b/src/lib/libc/net/getifaddrs.c
@@ -0,0 +1,284 @@
1/* $OpenBSD: getifaddrs.c,v 1.10 2008/11/24 20:08:49 claudio 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 <stddef.h>
40#include <stdlib.h>
41#include <string.h>
42#include <unistd.h>
43
44#define SALIGN (sizeof(long) - 1)
45#define SA_RLEN(sa) ((sa)->sa_len ? (((sa)->sa_len + SALIGN) & ~SALIGN) : (SALIGN + 1))
46
47int
48getifaddrs(struct ifaddrs **pif)
49{
50 int icnt = 1;
51 int dcnt = 0;
52 int ncnt = 0;
53 int mib[6];
54 size_t needed;
55 char *buf;
56 char *next;
57 struct ifaddrs *cif = 0;
58 char *p, *p0;
59 struct rt_msghdr *rtm;
60 struct if_msghdr *ifm;
61 struct ifa_msghdr *ifam;
62 struct sockaddr_dl *dl;
63 struct sockaddr *sa;
64 u_short index = 0;
65 size_t len, alen, dlen;
66 struct ifaddrs *ifa, *ift;
67 int i;
68 char *data;
69 char *names;
70
71 mib[0] = CTL_NET;
72 mib[1] = PF_ROUTE;
73 mib[2] = 0; /* protocol */
74 mib[3] = 0; /* wildcard address family */
75 mib[4] = NET_RT_IFLIST;
76 mib[5] = 0; /* no flags */
77 if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
78 return (-1);
79 if ((buf = malloc(needed)) == NULL)
80 return (-1);
81 if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
82 free(buf);
83 return (-1);
84 }
85
86 for (next = buf; next < buf + needed; next += rtm->rtm_msglen) {
87 rtm = (struct rt_msghdr *)next;
88 if (rtm->rtm_version != RTM_VERSION)
89 continue;
90 switch (rtm->rtm_type) {
91 case RTM_IFINFO:
92 ifm = (struct if_msghdr *)rtm;
93 if (ifm->ifm_addrs & RTA_IFP) {
94 index = ifm->ifm_index;
95 ++icnt;
96 dl = (struct sockaddr_dl *)(next +
97 rtm->rtm_hdrlen);
98 dcnt += SA_RLEN((struct sockaddr *)dl) +
99 ALIGNBYTES;
100 dcnt += sizeof(ifm->ifm_data);
101 ncnt += dl->sdl_nlen + 1;
102 } else
103 index = 0;
104 break;
105
106 case RTM_NEWADDR:
107 ifam = (struct ifa_msghdr *)rtm;
108 if (index && ifam->ifam_index != index)
109 abort(); /* XXX abort illegal in library */
110
111#define RTA_MASKS (RTA_NETMASK | RTA_IFA | RTA_BRD)
112 if (index == 0 || (ifam->ifam_addrs & RTA_MASKS) == 0)
113 break;
114 p = next + rtm->rtm_hdrlen;
115 ++icnt;
116 /* Scan to look for length of address */
117 alen = 0;
118 for (p0 = p, i = 0; i < RTAX_MAX; i++) {
119 if ((RTA_MASKS & ifam->ifam_addrs & (1 << i))
120 == 0)
121 continue;
122 sa = (struct sockaddr *)p;
123 len = SA_RLEN(sa);
124 if (i == RTAX_IFA) {
125 alen = len;
126 break;
127 }
128 p += len;
129 }
130 for (p = p0, i = 0; i < RTAX_MAX; i++) {
131 if ((RTA_MASKS & ifam->ifam_addrs & (1 << i))
132 == 0)
133 continue;
134 sa = (struct sockaddr *)p;
135 len = SA_RLEN(sa);
136 if (i == RTAX_NETMASK && sa->sa_len == 0)
137 dcnt += alen;
138 else
139 dcnt += len;
140 p += len;
141 }
142 break;
143 }
144 }
145
146 if (icnt + dcnt + ncnt == 1) {
147 *pif = NULL;
148 free(buf);
149 return (0);
150 }
151 data = malloc(sizeof(struct ifaddrs) * icnt + dcnt + ncnt);
152 if (data == NULL) {
153 free(buf);
154 return(-1);
155 }
156
157 ifa = (struct ifaddrs *)data;
158 data += sizeof(struct ifaddrs) * icnt;
159 names = data + dcnt;
160
161 memset(ifa, 0, sizeof(struct ifaddrs) * icnt);
162 ift = ifa;
163
164 index = 0;
165 for (next = buf; next < buf + needed; next += rtm->rtm_msglen) {
166 rtm = (struct rt_msghdr *)next;
167 if (rtm->rtm_version != RTM_VERSION)
168 continue;
169 switch (rtm->rtm_type) {
170 case RTM_IFINFO:
171 ifm = (struct if_msghdr *)rtm;
172 if (ifm->ifm_addrs & RTA_IFP) {
173 index = ifm->ifm_index;
174 dl = (struct sockaddr_dl *)(next +
175 rtm->rtm_hdrlen);
176
177 cif = ift;
178 ift->ifa_name = names;
179 ift->ifa_flags = (int)ifm->ifm_flags;
180 memcpy(names, dl->sdl_data, dl->sdl_nlen);
181 names[dl->sdl_nlen] = 0;
182 names += dl->sdl_nlen + 1;
183
184 ift->ifa_addr = (struct sockaddr *)data;
185 memcpy(data, dl,
186 ((struct sockaddr *)dl)->sa_len);
187 data += SA_RLEN((struct sockaddr *)dl);
188
189 /* ifm_data needs to be aligned */
190 ift->ifa_data = data = (void *)ALIGN(data);
191 dlen = rtm->rtm_hdrlen -
192 offsetof(struct if_msghdr, ifm_data);
193 if (dlen > sizeof(ifm->ifm_data))
194 dlen = sizeof(ifm->ifm_data);
195 memcpy(data, &ifm->ifm_data, dlen);
196 data += sizeof(ifm->ifm_data);
197
198 ift = (ift->ifa_next = ift + 1);
199 } else
200 index = 0;
201 break;
202
203 case RTM_NEWADDR:
204 ifam = (struct ifa_msghdr *)rtm;
205 if (index && ifam->ifam_index != index)
206 abort(); /* XXX abort illegal in library */
207
208 if (index == 0 || (ifam->ifam_addrs & RTA_MASKS) == 0)
209 break;
210 ift->ifa_name = cif->ifa_name;
211 ift->ifa_flags = cif->ifa_flags;
212 ift->ifa_data = NULL;
213 p = next + rtm->rtm_hdrlen;
214 /* Scan to look for length of address */
215 alen = 0;
216 for (p0 = p, i = 0; i < RTAX_MAX; i++) {
217 if ((RTA_MASKS & ifam->ifam_addrs & (1 << i))
218 == 0)
219 continue;
220 sa = (struct sockaddr *)p;
221 len = SA_RLEN(sa);
222 if (i == RTAX_IFA) {
223 alen = len;
224 break;
225 }
226 p += len;
227 }
228 for (p = p0, i = 0; i < RTAX_MAX; i++) {
229 if ((RTA_MASKS & ifam->ifam_addrs & (1 << i))
230 == 0)
231 continue;
232 sa = (struct sockaddr *)p;
233 len = SA_RLEN(sa);
234 switch (i) {
235 case RTAX_IFA:
236 ift->ifa_addr = (struct sockaddr *)data;
237 memcpy(data, p, len);
238 data += len;
239 break;
240
241 case RTAX_NETMASK:
242 ift->ifa_netmask =
243 (struct sockaddr *)data;
244 if (sa->sa_len == 0) {
245 memset(data, 0, alen);
246 data += alen;
247 break;
248 }
249 memcpy(data, p, len);
250 data += len;
251 break;
252
253 case RTAX_BRD:
254 ift->ifa_broadaddr =
255 (struct sockaddr *)data;
256 memcpy(data, p, len);
257 data += len;
258 break;
259 }
260 p += len;
261 }
262
263
264 ift = (ift->ifa_next = ift + 1);
265 break;
266 }
267 }
268
269 free(buf);
270 if (--ift >= ifa) {
271 ift->ifa_next = NULL;
272 *pif = ifa;
273 } else {
274 *pif = NULL;
275 free(ifa);
276 }
277 return (0);
278}
279
280void
281freeifaddrs(struct ifaddrs *ifp)
282{
283 free(ifp);
284}
diff --git a/src/lib/libc/net/getnameinfo.3 b/src/lib/libc/net/getnameinfo.3
new file mode 100644
index 0000000000..a91e8896b6
--- /dev/null
+++ b/src/lib/libc/net/getnameinfo.3
@@ -0,0 +1,265 @@
1.\" $OpenBSD: getnameinfo.3,v 1.41 2008/12/22 12:18:56 jacekm 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 $Mdocdate: December 22 2008 $
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");
142printf("host=%s, serv=%s\en", hbuf, sbuf);
143.Ed
144.Pp
145The following version checks if the socket address has a reverse address mapping:
146.Bd -literal -offset indent
147struct sockaddr *sa; /* input */
148char hbuf[NI_MAXHOST];
149
150if (getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf), NULL, 0,
151 NI_NAMEREQD))
152 errx(1, "could not resolve hostname");
153printf("host=%s\en", hbuf);
154.Ed
155.Sh SEE ALSO
156.Xr gai_strerror 3 ,
157.Xr getaddrinfo 3 ,
158.Xr gethostbyaddr 3 ,
159.Xr getservbyport 3 ,
160.Xr inet_ntop 3 ,
161.Xr resolver 3 ,
162.Xr hosts 5 ,
163.Xr resolv.conf 5 ,
164.Xr services 5 ,
165.Xr hostname 7 ,
166.Xr named 8
167.Rs
168.%A R. Gilligan
169.%A S. Thomson
170.%A J. Bound
171.%A W. Stevens
172.%T Basic Socket Interface Extensions for IPv6
173.%R RFC 2553
174.%D March 1999
175.Re
176.Rs
177.%A S. Deering
178.%A B. Haberman
179.%A T. Jinmei
180.%A E. Nordmark
181.%A B. Zill
182.%T "IPv6 Scoped Address Architecture"
183.%R internet draft
184.%N draft-ietf-ipv6-scoping-arch-02.txt
185.%O work in progress material
186.Re
187.Rs
188.%A Craig Metz
189.%T Protocol Independence Using the Sockets API
190.%B "Proceedings of the Freenix Track: 2000 USENIX Annual Technical Conference"
191.%D June 2000
192.Re
193.Sh STANDARDS
194The
195.Fn getnameinfo
196function is defined by the
197.St -p1003.1g-2000
198draft specification and documented in
199.Tn "RFC 2553" ,
200.Dq Basic Socket Interface Extensions for IPv6 .
201.Sh CAVEATS
202.Fn getnameinfo
203can return both numeric and FQDN forms of the address specified in
204.Fa sa .
205There is no return value that indicates whether the string returned in
206.Fa host
207is a result of binary to numeric-text translation (like
208.Xr inet_ntop 3 ) ,
209or is the result of a DNS reverse lookup.
210Because of this, malicious parties could set up a PTR record as follows:
211.Bd -literal -offset indent
2121.0.0.127.in-addr.arpa. IN PTR 10.1.1.1
213.Ed
214.Pp
215and trick the caller of
216.Fn getnameinfo
217into believing that
218.Fa sa
219is
220.Li 10.1.1.1
221when it is actually
222.Li 127.0.0.1 .
223.Pp
224To prevent such attacks, the use of
225.Dv NI_NAMEREQD
226is recommended when the result of
227.Fn getnameinfo
228is used
229for access control purposes:
230.Bd -literal -offset indent
231struct sockaddr *sa;
232char addr[NI_MAXHOST];
233struct addrinfo hints, *res;
234int error;
235
236error = getnameinfo(sa, sa->sa_len, addr, sizeof(addr),
237 NULL, 0, NI_NAMEREQD);
238if (error == 0) {
239 memset(&hints, 0, sizeof(hints));
240 hints.ai_socktype = SOCK_DGRAM; /*dummy*/
241 hints.ai_flags = AI_NUMERICHOST;
242 if (getaddrinfo(addr, "0", &hints, &res) == 0) {
243 /* malicious PTR record */
244 freeaddrinfo(res);
245 printf("bogus PTR record\en");
246 return -1;
247 }
248 /* addr is FQDN as a result of PTR lookup */
249} else {
250 /* addr is numeric string */
251 error = getnameinfo(sa, sa->sa_len, addr, sizeof(addr),
252 NULL, 0, NI_NUMERICHOST);
253}
254.Ed
255.Sh BUGS
256The implementation of
257.Fn getnameinfo
258is not thread-safe.
259.Pp
260.Ox
261intentionally uses a different
262.Dv NI_MAXHOST
263value from what
264.Tn "RFC 2553"
265suggests, 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..7041a4ee48
--- /dev/null
+++ b/src/lib/libc/net/getnameinfo.c
@@ -0,0 +1,351 @@
1/* $OpenBSD: getnameinfo.c,v 1.33 2007/02/15 04:25:35 ray 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
91void *__THREAD_NAME(serv_mutex);
92
93int
94getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host,
95 size_t hostlen, char *serv, size_t servlen, int flags)
96{
97 const struct afd *afd;
98 struct hostent *hp;
99 u_short port;
100 int family, i;
101 const char *addr;
102 u_int32_t v4a;
103 char numserv[512];
104 char numaddr[512];
105
106 if (sa == NULL)
107 return EAI_FAIL;
108
109 family = sa->sa_family;
110 for (i = 0; afdl[i].a_af; i++)
111 if (afdl[i].a_af == family) {
112 afd = &afdl[i];
113 goto found;
114 }
115 return EAI_FAMILY;
116
117 found:
118 if (salen != afd->a_socklen)
119 return EAI_FAIL;
120
121 /* network byte order */
122 port = ((const struct sockinet *)sa)->si_port;
123 addr = (const char *)sa + afd->a_off;
124
125 if (serv == NULL || servlen == 0) {
126 /*
127 * do nothing in this case.
128 * in case you are wondering if "&&" is more correct than
129 * "||" here: rfc2553bis-03 says that serv == NULL OR
130 * servlen == 0 means that the caller does not want the result.
131 */
132 } else if (!(flags & NI_NUMERICSERV)) {
133 struct servent sp;
134 struct servent_data sd;
135
136 (void)memset(&sd, 0, sizeof(sd));
137 if (getservbyport_r(port,
138 (flags & NI_DGRAM) ? "udp" : "tcp", &sp, &sd) == -1)
139 goto numeric;
140
141 if (strlen(sp.s_name) + 1 > servlen) {
142 endservent_r(&sd);
143 return EAI_MEMORY;
144 }
145 strlcpy(serv, sp.s_name, servlen);
146 endservent_r(&sd);
147 } else {
148 numeric:
149 i = snprintf(numserv, sizeof(numserv), "%u", ntohs(port));
150 if (i < 0 || i >= servlen || i >= sizeof(numserv))
151 return EAI_MEMORY;
152 strlcpy(serv, numserv, servlen);
153 }
154
155 switch (sa->sa_family) {
156 case AF_INET:
157 v4a = (u_int32_t)
158 ntohl(((const struct sockaddr_in *)sa)->sin_addr.s_addr);
159 if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))
160 flags |= NI_NUMERICHOST;
161 v4a >>= IN_CLASSA_NSHIFT;
162 if (v4a == 0)
163 flags |= NI_NUMERICHOST;
164 break;
165#ifdef INET6
166 case AF_INET6:
167 {
168 const struct sockaddr_in6 *sin6;
169 sin6 = (const struct sockaddr_in6 *)sa;
170 switch (sin6->sin6_addr.s6_addr[0]) {
171 case 0x00:
172 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr))
173 ;
174 else if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr))
175 ;
176 else
177 flags |= NI_NUMERICHOST;
178 break;
179 default:
180 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
181 flags |= NI_NUMERICHOST;
182 }
183 else if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
184 flags |= NI_NUMERICHOST;
185 break;
186 }
187 }
188 break;
189#endif
190 }
191 if (host == NULL || hostlen == 0) {
192 /*
193 * do nothing in this case.
194 * in case you are wondering if "&&" is more correct than
195 * "||" here: rfc2553bis-03 says that host == NULL or
196 * hostlen == 0 means that the caller does not want the result.
197 */
198 } else if (flags & NI_NUMERICHOST) {
199 int numaddrlen;
200
201 /* NUMERICHOST and NAMEREQD conflicts with each other */
202 if (flags & NI_NAMEREQD)
203 return EAI_NONAME;
204
205 switch(afd->a_af) {
206#ifdef INET6
207 case AF_INET6:
208 {
209 int error;
210
211 if ((error = ip6_parsenumeric(sa, addr, host,
212 hostlen, flags)) != 0)
213 return(error);
214 break;
215 }
216#endif
217 default:
218 if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr))
219 == NULL)
220 return EAI_SYSTEM;
221 numaddrlen = strlen(numaddr);
222 if (numaddrlen + 1 > hostlen) /* don't forget terminator */
223 return EAI_MEMORY;
224 strlcpy(host, numaddr, hostlen);
225 break;
226 }
227 } else {
228 _THREAD_PRIVATE_MUTEX_LOCK(serv_mutex);
229 hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af);
230 _THREAD_PRIVATE_MUTEX_UNLOCK(serv_mutex);
231
232 if (hp) {
233#if 0
234 /*
235 * commented out, since "for local host" is not
236 * implemented here - see RFC2553 p30
237 */
238 if (flags & NI_NOFQDN) {
239 char *p;
240 p = strchr(hp->h_name, '.');
241 if (p)
242 *p = '\0';
243 }
244#endif
245 if (strlen(hp->h_name) + 1 > hostlen) {
246 return EAI_MEMORY;
247 }
248 strlcpy(host, hp->h_name, hostlen);
249 } else {
250 if (flags & NI_NAMEREQD)
251 return EAI_NONAME;
252 switch(afd->a_af) {
253#ifdef INET6
254 case AF_INET6:
255 {
256 int error;
257
258 if ((error = ip6_parsenumeric(sa, addr, host,
259 hostlen,
260 flags)) != 0)
261 return(error);
262 break;
263 }
264#endif
265 default:
266 if (inet_ntop(afd->a_af, addr, host,
267 hostlen) == NULL)
268 return EAI_SYSTEM;
269 break;
270 }
271 }
272 }
273 return(0);
274}
275
276#ifdef INET6
277static int
278ip6_parsenumeric(const struct sockaddr *sa, const char *addr, char *host,
279 size_t hostlen, int flags)
280{
281 int numaddrlen;
282 char numaddr[512];
283
284 if (inet_ntop(AF_INET6, addr, numaddr, sizeof(numaddr)) == NULL)
285 return EAI_SYSTEM;
286
287 numaddrlen = strlen(numaddr);
288 if (numaddrlen + 1 > hostlen) /* don't forget terminator */
289 return EAI_MEMORY;
290 strlcpy(host, numaddr, hostlen);
291
292 if (((const struct sockaddr_in6 *)sa)->sin6_scope_id) {
293 char zonebuf[MAXHOSTNAMELEN];
294 int zonelen;
295
296 zonelen = ip6_sa2str(
297 (const struct sockaddr_in6 *)(const void *)sa,
298 zonebuf, sizeof(zonebuf), flags);
299 if (zonelen < 0)
300 return EAI_MEMORY;
301 if (zonelen + 1 + numaddrlen + 1 > hostlen)
302 return EAI_MEMORY;
303
304 /* construct <numeric-addr><delim><zoneid> */
305 memcpy(host + numaddrlen + 1, zonebuf,
306 (size_t)zonelen);
307 host[numaddrlen] = SCOPE_DELIMITER;
308 host[numaddrlen + 1 + zonelen] = '\0';
309 }
310
311 return 0;
312}
313
314/* ARGSUSED */
315static int
316ip6_sa2str(const struct sockaddr_in6 *sa6, char *buf, size_t bufsiz, int flags)
317{
318 unsigned int ifindex;
319 const struct in6_addr *a6;
320 int n;
321
322 ifindex = (unsigned int)sa6->sin6_scope_id;
323 a6 = &sa6->sin6_addr;
324
325#ifdef notdef
326 if ((flags & NI_NUMERICSCOPE) != 0) {
327 n = snprintf(buf, bufsiz, "%u", sa6->sin6_scope_id);
328 if (n < 0 || n >= bufsiz)
329 return -1;
330 else
331 return n;
332 }
333#endif
334
335 /* if_indextoname() does not take buffer size. not a good api... */
336 if ((IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6) ||
337 IN6_IS_ADDR_MC_INTFACELOCAL(a6)) && bufsiz >= IF_NAMESIZE) {
338 char *p = if_indextoname(ifindex, buf);
339 if (p) {
340 return(strlen(p));
341 }
342 }
343
344 /* last resort */
345 n = snprintf(buf, bufsiz, "%u", sa6->sin6_scope_id);
346 if (n < 0 || n >= bufsiz)
347 return -1;
348 else
349 return n;
350}
351#endif /* INET6 */
diff --git a/src/lib/libc/net/getnetbyaddr.c b/src/lib/libc/net/getnetbyaddr.c
index c193860e36..a85106630c 100644
--- a/src/lib/libc/net/getnetbyaddr.c
+++ b/src/lib/libc/net/getnetbyaddr.c
@@ -1,5 +1,4 @@
1/* $NetBSD: getnetbyaddr.c,v 1.4 1995/02/25 06:20:30 cgd Exp $ */ 1/* $OpenBSD: getnetbyaddr.c,v 1.8 2005/08/06 20:30:03 espie Exp $ */
2
3/* 2/*
4 * Copyright (c) 1983, 1993 3 * Copyright (c) 1983, 1993
5 * The Regents of the University of California. All rights reserved. 4 * The Regents of the University of California. All rights reserved.
@@ -12,11 +11,7 @@
12 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software 14 * 3. Neither the name of the University nor the names of its contributors
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software 15 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission. 16 * without specific prior written permission.
22 * 17 *
@@ -33,27 +28,17 @@
33 * SUCH DAMAGE. 28 * SUCH DAMAGE.
34 */ 29 */
35 30
36#if defined(LIBC_SCCS) && !defined(lint)
37#if 0
38static char sccsid[] = "@(#)getnetbyaddr.c 8.1 (Berkeley) 6/4/93";
39#else
40static char rcsid[] = "$NetBSD: getnetbyaddr.c,v 1.4 1995/02/25 06:20:30 cgd Exp $";
41#endif
42#endif /* LIBC_SCCS and not lint */
43
44#include <netdb.h> 31#include <netdb.h>
45 32
46extern int _net_stayopen; 33extern int _net_stayopen;
47 34
48struct netent * 35struct netent *
49getnetbyaddr(net, type) 36_getnetbyaddr(in_addr_t net, int type)
50 register long net;
51 register int type;
52{ 37{
53 register struct netent *p; 38 struct netent *p;
54 39
55 setnetent(_net_stayopen); 40 setnetent(_net_stayopen);
56 while (p = getnetent()) 41 while ((p = getnetent()))
57 if (p->n_addrtype == type && p->n_net == net) 42 if (p->n_addrtype == type && p->n_net == net)
58 break; 43 break;
59 if (!_net_stayopen) 44 if (!_net_stayopen)
diff --git a/src/lib/libc/net/getnetbyname.c b/src/lib/libc/net/getnetbyname.c
index 93a2e1256c..e6540cf12c 100644
--- a/src/lib/libc/net/getnetbyname.c
+++ b/src/lib/libc/net/getnetbyname.c
@@ -1,5 +1,4 @@
1/* $NetBSD: getnetbyname.c,v 1.4 1995/02/25 06:20:31 cgd Exp $ */ 1/* $OpenBSD: getnetbyname.c,v 1.8 2005/08/06 20:30:03 espie Exp $ */
2
3/* 2/*
4 * Copyright (c) 1983, 1993 3 * Copyright (c) 1983, 1993
5 * The Regents of the University of California. All rights reserved. 4 * The Regents of the University of California. All rights reserved.
@@ -12,11 +11,7 @@
12 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software 14 * 3. Neither the name of the University nor the names of its contributors
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software 15 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission. 16 * without specific prior written permission.
22 * 17 *
@@ -33,32 +28,23 @@
33 * SUCH DAMAGE. 28 * SUCH DAMAGE.
34 */ 29 */
35 30
36#if defined(LIBC_SCCS) && !defined(lint)
37#if 0
38static char sccsid[] = "@(#)getnetbyname.c 8.1 (Berkeley) 6/4/93";
39#else
40static char rcsid[] = "$NetBSD: getnetbyname.c,v 1.4 1995/02/25 06:20:31 cgd Exp $";
41#endif
42#endif /* LIBC_SCCS and not lint */
43
44#include <netdb.h> 31#include <netdb.h>
45#include <string.h> 32#include <string.h>
46 33
47extern int _net_stayopen; 34extern int _net_stayopen;
48 35
49struct netent * 36struct netent *
50getnetbyname(name) 37_getnetbyname(const char *name)
51 register const char *name;
52{ 38{
53 register struct netent *p; 39 struct netent *p;
54 register char **cp; 40 char **cp;
55 41
56 setnetent(_net_stayopen); 42 setnetent(_net_stayopen);
57 while (p = getnetent()) { 43 while ((p = getnetent())) {
58 if (strcmp(p->n_name, name) == 0) 44 if (strcasecmp(p->n_name, name) == 0)
59 break; 45 break;
60 for (cp = p->n_aliases; *cp != 0; cp++) 46 for (cp = p->n_aliases; *cp != 0; cp++)
61 if (strcmp(*cp, name) == 0) 47 if (strcasecmp(*cp, name) == 0)
62 goto found; 48 goto found;
63 } 49 }
64found: 50found:
diff --git a/src/lib/libc/net/getnetent.3 b/src/lib/libc/net/getnetent.3
index d4f0bedbf9..00fd543ec4 100644
--- a/src/lib/libc/net/getnetent.3
+++ b/src/lib/libc/net/getnetent.3
@@ -1,4 +1,4 @@
1.\" $NetBSD: getnetent.3,v 1.3 1995/02/25 06:20:32 cgd Exp $ 1.\" $OpenBSD: getnetent.3,v 1.15 2007/05/31 19:19:30 jmc Exp $
2.\" 2.\"
3.\" Copyright (c) 1983, 1991, 1993 3.\" Copyright (c) 1983, 1991, 1993
4.\" The Regents of the University of California. All rights reserved. 4.\" The Regents of the University of California. All rights reserved.
@@ -11,11 +11,7 @@
11.\" 2. Redistributions in binary form must reproduce the above copyright 11.\" 2. Redistributions in binary form must reproduce the above copyright
12.\" notice, this list of conditions and the following disclaimer in the 12.\" notice, this list of conditions and the following disclaimer in the
13.\" documentation and/or other materials provided with the distribution. 13.\" documentation and/or other materials provided with the distribution.
14.\" 3. All advertising materials mentioning features or use of this software 14.\" 3. Neither the name of the University nor the names of its contributors
15.\" must display the following acknowledgement:
16.\" This product includes software developed by the University of
17.\" California, Berkeley and its contributors.
18.\" 4. Neither the name of the University nor the names of its contributors
19.\" may be used to endorse or promote products derived from this software 15.\" may be used to endorse or promote products derived from this software
20.\" without specific prior written permission. 16.\" without specific prior written permission.
21.\" 17.\"
@@ -31,11 +27,9 @@
31.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32.\" SUCH DAMAGE. 28.\" SUCH DAMAGE.
33.\" 29.\"
34.\" @(#)getnetent.3 8.1 (Berkeley) 6/4/93 30.Dd $Mdocdate: May 31 2007 $
35.\"
36.Dd June 4, 1993
37.Dt GETNETENT 3 31.Dt GETNETENT 3
38.Os BSD 4.2 32.Os
39.Sh NAME 33.Sh NAME
40.Nm getnetent , 34.Nm getnetent ,
41.Nm getnetbyaddr , 35.Nm getnetbyaddr ,
@@ -46,31 +40,30 @@
46.Sh SYNOPSIS 40.Sh SYNOPSIS
47.Fd #include <netdb.h> 41.Fd #include <netdb.h>
48.Ft struct netent * 42.Ft struct netent *
49.Fn getnetent 43.Fn getnetent "void"
50.Ft struct netent * 44.Ft struct netent *
51.Fn getnetbyname "char *name" 45.Fn getnetbyname "const char *name"
52.Ft struct netent * 46.Ft struct netent *
53.Fn getnetbyaddr "long net" "int type" 47.Fn getnetbyaddr "in_addr_t net" "int type"
48.Ft void
54.Fn setnetent "int stayopen" 49.Fn setnetent "int stayopen"
55.Fn endnetent 50.Ft void
51.Fn endnetent "void"
56.Sh DESCRIPTION 52.Sh DESCRIPTION
57The 53The
58.Fn getnetent , 54.Fn getnetent ,
59.Fn getnetbyname , 55.Fn getnetbyname ,
60and 56and
61.Fn getnetbyaddr 57.Fn getnetbyaddr
62functions 58functions each return a pointer to an object with the following structure
63each return a pointer to an object with the 59containing the broken-out fields of a line in the network database,
64following structure
65containing the broken-out
66fields of a line in the network data base,
67.Pa /etc/networks . 60.Pa /etc/networks .
68.Bd -literal -offset indent 61.Bd -literal -offset indent
69struct netent { 62struct netent {
70 char *n_name; /* official name of net */ 63 char *n_name; /* official name of net */
71 char **n_aliases; /* alias list */ 64 char **n_aliases; /* alias list */
72 int n_addrtype; /* net number type */ 65 int n_addrtype; /* net number type */
73 unsigned long n_net; /* net number */ 66 in_addr_t n_net; /* net number */
74}; 67};
75.Ed 68.Ed
76.Pp 69.Pp
@@ -79,45 +72,42 @@ The members of this structure are:
79.It Fa n_name 72.It Fa n_name
80The official name of the network. 73The official name of the network.
81.It Fa n_aliases 74.It Fa n_aliases
82A zero terminated list of alternate names for the network. 75A null-terminated list of alternate names for the network.
83.It Fa n_addrtype 76.It Fa n_addrtype
84The type of the network number returned; currently only AF_INET. 77The type of the network number returned; currently only
78.Dv AF_INET .
85.It Fa n_net 79.It Fa n_net
86The network number. Network numbers are returned in machine byte 80The network number.
87order. 81Network numbers are returned in machine byte order.
88.El 82.El
89.Pp 83.Pp
90The 84The
91.Fn getnetent 85.Fn getnetent
92function 86function reads the next line of the file, opening the file if necessary.
93reads the next line of the file, opening the file if necessary.
94.Pp 87.Pp
95The 88The
96.Fn setnetent 89.Fn setnetent
97function 90function opens and rewinds the file.
98opens and rewinds the file. If the 91If the
99.Fa stayopen 92.Fa stayopen
100flag is non-zero, 93flag is non-zero,
101the net data base will not be closed after each call to 94the net database will not be closed after each call to
102.Fn getnetbyname 95.Fn getnetbyname
103or 96or
104.Fn getnetbyaddr . 97.Fn getnetbyaddr .
105.Pp 98.Pp
106The 99The
107.Fn endnetent 100.Fn endnetent
108function 101function closes the file.
109closes the file.
110.Pp 102.Pp
111The 103The
112.Fn getnetbyname 104.Fn getnetbyname
113function
114and 105and
115.Fn getnetbyaddr 106.Fn getnetbyaddr
116sequentially search from the beginning 107functions search the domain name server if the system is configured to use one.
117of the file until a matching 108If the search fails, or no name server is configured, they sequentially
118net name or 109search from the beginning of the file until a matching net name or
119net address and type is found, 110net address and type is found, or until
120or until
121.Dv EOF 111.Dv EOF
122is encountered. 112is encountered.
123Network numbers are supplied in host order. 113Network numbers are supplied in host order.
@@ -126,11 +116,11 @@ Network numbers are supplied in host order.
126.It Pa /etc/networks 116.It Pa /etc/networks
127.El 117.El
128.Sh DIAGNOSTICS 118.Sh DIAGNOSTICS
129Null pointer 119Null pointer (0) returned on
130(0) returned on
131.Dv EOF 120.Dv EOF
132or error. 121or error.
133.Sh SEE ALSO 122.Sh SEE ALSO
123.Xr resolver 3 ,
134.Xr networks 5 124.Xr networks 5
135.Sh HISTORY 125.Sh HISTORY
136The 126The
@@ -140,14 +130,11 @@ The
140.Fn setnetent , 130.Fn setnetent ,
141and 131and
142.Fn endnetent 132.Fn endnetent
143functions appeared in 133functions appeared in
144.Bx 4.2 . 134.Bx 4.2 .
145.Sh BUGS 135.Sh BUGS
146The data space used by 136The data space used by these functions is static; if future use
147these functions is static; if future use requires the data, it should be 137requires the data, it should be copied before any subsequent calls
148copied before any subsequent calls to these functions overwrite it. 138to these functions overwrite it.
149Only Internet network 139Only Internet network numbers are currently understood.
150numbers are currently understood. 140Expecting network numbers to fit in no more than 32 bits is naive.
151Expecting network numbers to fit
152in no more than 32 bits is probably
153naive.
diff --git a/src/lib/libc/net/getnetent.c b/src/lib/libc/net/getnetent.c
index b4e16b8f5d..1bec6fb98c 100644
--- a/src/lib/libc/net/getnetent.c
+++ b/src/lib/libc/net/getnetent.c
@@ -1,5 +1,4 @@
1/* $NetBSD: getnetent.c,v 1.4 1995/02/25 06:20:33 cgd Exp $ */ 1/* $OpenBSD: getnetent.c,v 1.12 2006/01/17 15:37:58 millert Exp $ */
2
3/* 2/*
4 * Copyright (c) 1983, 1993 3 * Copyright (c) 1983, 1993
5 * The Regents of the University of California. All rights reserved. 4 * The Regents of the University of California. All rights reserved.
@@ -12,11 +11,7 @@
12 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software 14 * 3. Neither the name of the University nor the names of its contributors
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software 15 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission. 16 * without specific prior written permission.
22 * 17 *
@@ -33,15 +28,7 @@
33 * SUCH DAMAGE. 28 * SUCH DAMAGE.
34 */ 29 */
35 30
36#if defined(LIBC_SCCS) && !defined(lint) 31#include <sys/param.h>
37#if 0
38static char sccsid[] = "@(#)getnetent.c 8.1 (Berkeley) 6/4/93";
39#else
40static char rcsid[] = "$NetBSD: getnetent.c,v 1.4 1995/02/25 06:20:33 cgd Exp $";
41#endif
42#endif /* LIBC_SCCS and not lint */
43
44#include <sys/types.h>
45#include <sys/socket.h> 32#include <sys/socket.h>
46#include <netinet/in.h> 33#include <netinet/in.h>
47#include <arpa/inet.h> 34#include <arpa/inet.h>
@@ -58,8 +45,7 @@ static char *net_aliases[MAXALIASES];
58int _net_stayopen; 45int _net_stayopen;
59 46
60void 47void
61setnetent(f) 48setnetent(int f)
62 int f;
63{ 49{
64 if (netf == NULL) 50 if (netf == NULL)
65 netf = fopen(_PATH_NETWORKS, "r" ); 51 netf = fopen(_PATH_NETWORKS, "r" );
@@ -69,7 +55,7 @@ setnetent(f)
69} 55}
70 56
71void 57void
72endnetent() 58endnetent(void)
73{ 59{
74 if (netf) { 60 if (netf) {
75 fclose(netf); 61 fclose(netf);
@@ -79,24 +65,29 @@ endnetent()
79} 65}
80 66
81struct netent * 67struct netent *
82getnetent() 68getnetent(void)
83{ 69{
84 char *p; 70 char *p, *cp, **q;
85 register char *cp, **q; 71 size_t len;
86 72
87 if (netf == NULL && (netf = fopen(_PATH_NETWORKS, "r" )) == NULL) 73 if (netf == NULL && (netf = fopen(_PATH_NETWORKS, "r" )) == NULL)
88 return (NULL); 74 return (NULL);
89again: 75again:
90 p = fgets(line, BUFSIZ, netf); 76 if ((p = fgetln(netf, &len)) == NULL)
91 if (p == NULL)
92 return (NULL); 77 return (NULL);
93 if (*p == '#') 78 if (p[len-1] == '\n')
79 len--;
80 if (len >= sizeof(line) || len == 0)
94 goto again; 81 goto again;
95 cp = strpbrk(p, "#\n"); 82 p = memcpy(line, p, len);
96 if (cp == NULL) 83 line[len] = '\0';
84 if (*p == '#')
97 goto again; 85 goto again;
98 *cp = '\0'; 86 if ((cp = strchr(p, '#')) != NULL)
87 *cp = '\0';
99 net.n_name = p; 88 net.n_name = p;
89 if (strlen(net.n_name) >= MAXHOSTNAMELEN-1)
90 net.n_name[MAXHOSTNAMELEN-1] = '\0';
100 cp = strpbrk(p, " \t"); 91 cp = strpbrk(p, " \t");
101 if (cp == NULL) 92 if (cp == NULL)
102 goto again; 93 goto again;
@@ -116,8 +107,11 @@ again:
116 cp++; 107 cp++;
117 continue; 108 continue;
118 } 109 }
119 if (q < &net_aliases[MAXALIASES - 1]) 110 if (q < &net_aliases[MAXALIASES - 1]) {
120 *q++ = cp; 111 *q++ = cp;
112 if (strlen(cp) >= MAXHOSTNAMELEN-1)
113 cp[MAXHOSTNAMELEN-1] = '\0';
114 }
121 cp = strpbrk(cp, " \t"); 115 cp = strpbrk(cp, " \t");
122 if (cp != NULL) 116 if (cp != NULL)
123 *cp++ = '\0'; 117 *cp++ = '\0';
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/getpeereid.3 b/src/lib/libc/net/getpeereid.3
new file mode 100644
index 0000000000..c1671a7516
--- /dev/null
+++ b/src/lib/libc/net/getpeereid.3
@@ -0,0 +1,119 @@
1.\" $OpenBSD: getpeereid.3,v 1.1 2010/07/01 19:15:30 deraadt 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.Dd $Mdocdate: July 1 2010 $
30.Dt GETPEEREID 3
31.Os
32.Sh NAME
33.Nm getpeereid
34.Nd get effective user and group identification of locally-connected peer
35.Sh SYNOPSIS
36.Fd #include <sys/types.h>
37.Fd #include <sys/socket.h>
38.Ft int
39.Fn getpeereid "int s" "uid_t *euid" "gid_t *egid"
40.Sh DESCRIPTION
41.Fn getpeereid
42returns the effective user ID and group ID of the peer connected to
43a
44.Ux Ns -domain
45socket (see
46.Xr unix 4 ) .
47The argument
48.Fa s
49must be of type
50.Dv SOCK_STREAM .
51.Pp
52One common use is for
53.Ux Ns -domain
54servers to determine the credentials of clients that have connected to it.
55.Pp
56.Fn getpeereid
57takes three parameters:
58.Bl -bullet
59.It
60.Fa s
61contains the file descriptor of the socket whose peer credentials
62should be looked up.
63.It
64.Fa euid
65points to a
66.Li uid_t
67variable into which the effective user ID for the connected peer will
68be stored.
69.It
70.Fa egid
71points to a
72.Li gid_t
73variable into which the effective group ID for the connected peer will
74be stored.
75.El
76.Sh RETURN VALUES
77If the call succeeds, a 0 is returned and
78.Fa euid
79and
80.Fa egid
81are set to the effective user ID and group ID of the connected peer.
82Otherwise,
83.Va errno
84is set and a value of \-1 is returned.
85.Sh ERRORS
86On failure,
87.Va errno
88is set to one of the following:
89.Bl -tag -width Er
90.It Bq Er EBADF
91The argument
92.Fa s
93is not a valid descriptor.
94.It Bq Er ENOTSOCK
95The argument
96.Fa s
97is a file, not a socket.
98.It Bq Er EOPNOTSUPP
99The socket is not in the
100.Ux Ns -domain .
101.It Bq Er ENOTCONN
102The socket is not connected.
103.It Bq Er ENOBUFS
104Insufficient resources were available in the system
105to perform the operation.
106.El
107.Sh SEE ALSO
108.Xr accept 2 ,
109.Xr bind 2 ,
110.Xr getpeername 2 ,
111.Xr getsockname 2 ,
112.Xr getsockopt 2 ,
113.Xr socket 2 ,
114.Xr unix 4
115.Sh HISTORY
116The
117.Fn getpeereid
118function call appeared in
119.Ox 3.0 .
diff --git a/src/lib/libc/net/getpeereid.c b/src/lib/libc/net/getpeereid.c
new file mode 100644
index 0000000000..208e541f17
--- /dev/null
+++ b/src/lib/libc/net/getpeereid.c
@@ -0,0 +1,36 @@
1/* $OpenBSD: getpeereid.c,v 1.1 2010/07/01 19:15:30 deraadt Exp $ */
2
3/*
4 * Copyright (c) 2010 Theo de Raadt <deraadt@openbsd.org>
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#include <sys/types.h>
20#include <sys/socket.h>
21
22int
23getpeereid(int s, uid_t *euid, gid_t *egid)
24{
25 struct sockpeercred creds;
26 socklen_t credslen = sizeof(creds);
27 int error;
28
29 error = getsockopt(s, SOL_SOCKET, SO_PEERCRED,
30 &creds, &credslen);
31 if (error)
32 return (error);
33 *euid = creds.uid;
34 *egid = creds.gid;
35 return (0);
36}
diff --git a/src/lib/libc/net/getproto.c b/src/lib/libc/net/getproto.c
index 49c09b0806..07fa33288d 100644
--- a/src/lib/libc/net/getproto.c
+++ b/src/lib/libc/net/getproto.c
@@ -1,5 +1,4 @@
1/* $NetBSD: getproto.c,v 1.4 1995/02/25 06:20:33 cgd Exp $ */ 1/* $OpenBSD: getproto.c,v 1.7 2005/08/06 20:30:03 espie Exp $ */
2
3/* 2/*
4 * Copyright (c) 1983, 1993 3 * Copyright (c) 1983, 1993
5 * The Regents of the University of California. All rights reserved. 4 * The Regents of the University of California. All rights reserved.
@@ -12,11 +11,7 @@
12 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software 14 * 3. Neither the name of the University nor the names of its contributors
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software 15 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission. 16 * without specific prior written permission.
22 * 17 *
@@ -33,29 +28,32 @@
33 * SUCH DAMAGE. 28 * SUCH DAMAGE.
34 */ 29 */
35 30
36#if defined(LIBC_SCCS) && !defined(lint)
37#if 0
38static char sccsid[] = "@(#)getproto.c 8.1 (Berkeley) 6/4/93";
39#else
40static char rcsid[] = "$NetBSD: getproto.c,v 1.4 1995/02/25 06:20:33 cgd Exp $";
41#endif
42#endif /* LIBC_SCCS and not lint */
43
44#include <netdb.h> 31#include <netdb.h>
32#include <stdio.h>
45 33
46extern int _proto_stayopen; 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}
47 49
48struct protoent * 50struct protoent *
49getprotobynumber(proto) 51getprotobynumber(int num)
50 register int proto;
51{ 52{
52 register struct protoent *p; 53 extern struct protoent_data _protoent_data;
54 static struct protoent proto;
53 55
54 setprotoent(_proto_stayopen); 56 if (getprotobynumber_r(num, &proto, &_protoent_data) != 0)
55 while (p = getprotoent()) 57 return (NULL);
56 if (p->p_proto == proto) 58 return (&proto);
57 break;
58 if (!_proto_stayopen)
59 endprotoent();
60 return (p);
61} 59}
diff --git a/src/lib/libc/net/getprotoent.3 b/src/lib/libc/net/getprotoent.3
index 8d607199ef..df4cd0c323 100644
--- a/src/lib/libc/net/getprotoent.3
+++ b/src/lib/libc/net/getprotoent.3
@@ -1,4 +1,4 @@
1.\" $NetBSD: getprotoent.3,v 1.3 1995/02/25 06:20:34 cgd Exp $ 1.\" $OpenBSD: getprotoent.3,v 1.17 2007/05/31 19:19:30 jmc Exp $
2.\" 2.\"
3.\" Copyright (c) 1983, 1991, 1993 3.\" Copyright (c) 1983, 1991, 1993
4.\" The Regents of the University of California. All rights reserved. 4.\" The Regents of the University of California. All rights reserved.
@@ -11,11 +11,7 @@
11.\" 2. Redistributions in binary form must reproduce the above copyright 11.\" 2. Redistributions in binary form must reproduce the above copyright
12.\" notice, this list of conditions and the following disclaimer in the 12.\" notice, this list of conditions and the following disclaimer in the
13.\" documentation and/or other materials provided with the distribution. 13.\" documentation and/or other materials provided with the distribution.
14.\" 3. All advertising materials mentioning features or use of this software 14.\" 3. Neither the name of the University nor the names of its contributors
15.\" must display the following acknowledgement:
16.\" This product includes software developed by the University of
17.\" California, Berkeley and its contributors.
18.\" 4. Neither the name of the University nor the names of its contributors
19.\" may be used to endorse or promote products derived from this software 15.\" may be used to endorse or promote products derived from this software
20.\" without specific prior written permission. 16.\" without specific prior written permission.
21.\" 17.\"
@@ -31,39 +27,51 @@
31.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32.\" SUCH DAMAGE. 28.\" SUCH DAMAGE.
33.\" 29.\"
34.\" @(#)getprotoent.3 8.1 (Berkeley) 6/4/93 30.Dd $Mdocdate: May 31 2007 $
35.\"
36.Dd June 4, 1993
37.Dt GETPROTOENT 3 31.Dt GETPROTOENT 3
38.Os BSD 4.2 32.Os
39.Sh NAME 33.Sh NAME
40.Nm getprotoent , 34.Nm getprotoent ,
35.Nm getprotoent_r ,
41.Nm getprotobynumber , 36.Nm getprotobynumber ,
37.Nm getprotobynumber_r ,
42.Nm getprotobyname , 38.Nm getprotobyname ,
39.Nm getprotobyname_r ,
43.Nm setprotoent , 40.Nm setprotoent ,
44.Nm endprotoent 41.Nm setprotoent_r ,
42.Nm endprotoent ,
43.Nm endprotoent_r
45.Nd get protocol entry 44.Nd get protocol entry
46.Sh SYNOPSIS 45.Sh SYNOPSIS
47.Fd #include <netdb.h> 46.Fd #include <netdb.h>
48.Ft struct protoent * 47.Ft struct protoent *
49.Fn getprotoent 48.Fn getprotoent "void"
49.Ft int
50.Fn getprotoent_r "struct protoent *protoent" "struct protoent_data *protoent_data"
50.Ft struct protoent * 51.Ft struct protoent *
51.Fn getprotobyname "char *name" 52.Fn getprotobyname "const char *name"
53.Ft int
54.Fn getprotobyname_r "const char *name" "struct protoent *protoent" "struct protoent_data *protoent_data"
52.Ft struct protoent * 55.Ft struct protoent *
53.Fn getprotobynumber "int proto" 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
54.Fn setprotoent "int stayopen" 60.Fn setprotoent "int stayopen"
55.Fn endprotoent 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"
56.Sh DESCRIPTION 67.Sh DESCRIPTION
57The 68The
58.Fn getprotoent , 69.Fn getprotoent ,
59.Fn getprotobyname , 70.Fn getprotobyname ,
60and 71and
61.Fn getprotobynumber 72.Fn getprotobynumber
62functions 73functions each return a pointer to an object with the following structure
63each return a pointer to an object with the 74containing the broken-out fields of a line in the network protocol database,
64following structure
65containing the broken-out
66fields of a line in the network protocol data base,
67.Pa /etc/protocols . 75.Pa /etc/protocols .
68.Bd -literal -offset indent 76.Bd -literal -offset indent
69.Pp 77.Pp
@@ -79,55 +87,106 @@ The members of this structure are:
79.It Fa p_name 87.It Fa p_name
80The official name of the protocol. 88The official name of the protocol.
81.It Fa p_aliases 89.It Fa p_aliases
82A zero terminated list of alternate names for the protocol. 90A null-terminated list of alternate names for the protocol.
83.It Fa p_proto 91.It Fa p_proto
84The protocol number. 92The protocol number.
85.El 93.El
86.Pp 94.Pp
87The 95The
88.Fn getprotoent 96.Fn getprotoent
89function 97function reads the next line of the file, opening the file if necessary.
90reads the next line of the file, opening the file if necessary.
91.Pp 98.Pp
92The 99The
93.Fn setprotoent 100.Fn setprotoent
94function 101function opens and rewinds the file.
95opens and rewinds the file. If the 102If the
96.Fa stayopen 103.Fa stayopen
97flag is non-zero, 104flag is non-zero,
98the net data base will not be closed after each call to 105the protocol database will not be closed after each call to
99.Fn getprotobyname 106.Fn getprotobyname
100or 107or
101.Fn getprotobynumber . 108.Fn getprotobynumber .
102.Pp 109.Pp
103The 110The
104.Fn endprotoent 111.Fn endprotoent
105function 112function closes the file.
106closes the file.
107.Pp 113.Pp
108The 114The
109.Fn getprotobyname 115.Fn getprotobyname
110function
111and 116and
112.Fn getprotobynumber 117.Fn getprotobynumber
113sequentially search from the beginning 118functions sequentially search from the beginning of the file until a
114of the file until a matching 119matching protocol name or protocol number is found, or until
115protocol name or
116protocol number is found,
117or until
118.Dv EOF 120.Dv EOF
119is encountered. 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.
120.Sh RETURN VALUES 146.Sh RETURN VALUES
121Null pointer 147The
122(0) returned on 148.Fn getprotoent ,
123.Dv EOF 149.Fn getprotobyport ,
124or error. 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.
125.Sh FILES 164.Sh FILES
126.Bl -tag -width /etc/protocols -compact 165.Bl -tag -width /etc/protocols -compact
127.It Pa /etc/protocols 166.It Pa /etc/protocols
128.El 167.El
129.Sh SEE ALSO 168.Sh SEE ALSO
130.Xr protocols 5 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.
131.Sh HISTORY 190.Sh HISTORY
132The 191The
133.Fn getprotoent , 192.Fn getprotoent ,
@@ -136,11 +195,19 @@ The
136.Fn setprotoent , 195.Fn setprotoent ,
137and 196and
138.Fn endprotoent 197.Fn endprotoent
139functions appeared in 198functions appeared in
140.Bx 4.2 . 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 .
141.Sh BUGS 210.Sh BUGS
142These functions use a static data space; 211The non-reentrant functions use a static data space; if the data is needed
143if the data is needed for future use, it should be 212for future use, it should be copied before any subsequent calls overwrite it.
144copied before any subsequent calls overwrite it. 213Only the Internet protocols are currently understood.
145Only the Internet
146protocols are currently understood.
diff --git a/src/lib/libc/net/getprotoent.c b/src/lib/libc/net/getprotoent.c
index 1179b9029b..f0705e0765 100644
--- a/src/lib/libc/net/getprotoent.c
+++ b/src/lib/libc/net/getprotoent.c
@@ -1,5 +1,4 @@
1/* $NetBSD: getprotoent.c,v 1.4 1995/02/25 06:20:35 cgd Exp $ */ 1/* $OpenBSD: getprotoent.c,v 1.10 2007/09/02 15:19:17 deraadt Exp $ */
2
3/* 2/*
4 * Copyright (c) 1983, 1993 3 * Copyright (c) 1983, 1993
5 * The Regents of the University of California. All rights reserved. 4 * The Regents of the University of California. All rights reserved.
@@ -12,11 +11,7 @@
12 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software 14 * 3. Neither the name of the University nor the names of its contributors
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software 15 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission. 16 * without specific prior written permission.
22 * 17 *
@@ -33,69 +28,66 @@
33 * SUCH DAMAGE. 28 * SUCH DAMAGE.
34 */ 29 */
35 30
36#if defined(LIBC_SCCS) && !defined(lint)
37#if 0
38static char sccsid[] = "@(#)getprotoent.c 8.1 (Berkeley) 6/4/93";
39#else
40static char rcsid[] = "$NetBSD: getprotoent.c,v 1.4 1995/02/25 06:20:35 cgd Exp $";
41#endif
42#endif /* LIBC_SCCS and not lint */
43
44#include <sys/types.h> 31#include <sys/types.h>
45#include <sys/socket.h> 32#include <sys/socket.h>
33
34#include <errno.h>
35#include <limits.h>
46#include <netdb.h> 36#include <netdb.h>
47#include <stdio.h> 37#include <stdio.h>
48#include <stdlib.h> 38#include <stdlib.h>
49#include <string.h> 39#include <string.h>
50 40
51#define MAXALIASES 35
52
53static FILE *protof = NULL;
54static char line[BUFSIZ+1];
55static struct protoent proto;
56static char *proto_aliases[MAXALIASES];
57int _proto_stayopen;
58
59void 41void
60setprotoent(f) 42setprotoent_r(int f, struct protoent_data *pd)
61 int f;
62{ 43{
63 if (protof == NULL) 44 if (pd->fp == NULL)
64 protof = fopen(_PATH_PROTOCOLS, "r" ); 45 pd->fp = fopen(_PATH_PROTOCOLS, "r" );
65 else 46 else
66 rewind(protof); 47 rewind(pd->fp);
67 _proto_stayopen |= f; 48 pd->stayopen |= f;
68} 49}
69 50
70void 51void
71endprotoent() 52endprotoent_r(struct protoent_data *pd)
72{ 53{
73 if (protof) { 54 if (pd->fp) {
74 fclose(protof); 55 fclose(pd->fp);
75 protof = NULL; 56 pd->fp = NULL;
76 } 57 }
77 _proto_stayopen = 0; 58 free(pd->aliases);
59 pd->aliases = NULL;
60 pd->maxaliases = 0;
61 free(pd->line);
62 pd->line = NULL;
63 pd->stayopen = 0;
78} 64}
79 65
80struct protoent * 66int
81getprotoent() 67getprotoent_r(struct protoent *pe, struct protoent_data *pd)
82{ 68{
83 char *p; 69 char *p, *cp, **q, *endp;
84 register char *cp, **q; 70 size_t len;
71 long l;
72 int serrno;
85 73
86 if (protof == NULL && (protof = fopen(_PATH_PROTOCOLS, "r" )) == NULL) 74 if (pd->fp == NULL && (pd->fp = fopen(_PATH_PROTOCOLS, "r" )) == NULL)
87 return (NULL); 75 return (-1);
88again: 76again:
89 if ((p = fgets(line, BUFSIZ, protof)) == NULL) 77 if ((p = fgetln(pd->fp, &len)) == NULL)
90 return (NULL); 78 return (-1);
91 if (*p == '#') 79 if (len == 0 || *p == '#' || *p == '\n')
92 goto again; 80 goto again;
93 cp = strpbrk(p, "#\n"); 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);
94 if (cp == NULL) 86 if (cp == NULL)
95 goto again; 87 return (-1);
96 *cp = '\0'; 88 pd->line = pe->p_name = memcpy(cp, p, len);
97 proto.p_name = p; 89 cp[len] = '\0';
98 cp = strpbrk(p, " \t"); 90 cp = strpbrk(cp, " \t");
99 if (cp == NULL) 91 if (cp == NULL)
100 goto again; 92 goto again;
101 *cp++ = '\0'; 93 *cp++ = '\0';
@@ -104,8 +96,21 @@ again:
104 p = strpbrk(cp, " \t"); 96 p = strpbrk(cp, " \t");
105 if (p != NULL) 97 if (p != NULL)
106 *p++ = '\0'; 98 *p++ = '\0';
107 proto.p_proto = atoi(cp); 99 l = strtol(cp, &endp, 10);
108 q = proto.p_aliases = proto_aliases; 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 = calloc(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;
109 if (p != NULL) { 114 if (p != NULL) {
110 cp = p; 115 cp = p;
111 while (cp && *cp) { 116 while (cp && *cp) {
@@ -113,13 +118,49 @@ again:
113 cp++; 118 cp++;
114 continue; 119 continue;
115 } 120 }
116 if (q < &proto_aliases[MAXALIASES - 1]) 121 if (q == &pe->p_aliases[pd->maxaliases - 1]) {
117 *q++ = cp; 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;
118 cp = strpbrk(cp, " \t"); 135 cp = strpbrk(cp, " \t");
119 if (cp != NULL) 136 if (cp != NULL)
120 *cp++ = '\0'; 137 *cp++ = '\0';
121 } 138 }
122 } 139 }
123 *q = NULL; 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);
124 return (&proto); 165 return (&proto);
125} 166}
diff --git a/src/lib/libc/net/getprotoname.c b/src/lib/libc/net/getprotoname.c
index 4f8cf21c3f..749b6b3f13 100644
--- a/src/lib/libc/net/getprotoname.c
+++ b/src/lib/libc/net/getprotoname.c
@@ -1,5 +1,4 @@
1/* $NetBSD: getprotoname.c,v 1.4 1995/02/25 06:20:36 cgd Exp $ */ 1/* $OpenBSD: getprotoname.c,v 1.7 2005/08/06 20:30:03 espie Exp $ */
2
3/* 2/*
4 * Copyright (c) 1983, 1993 3 * Copyright (c) 1983, 1993
5 * The Regents of the University of California. All rights reserved. 4 * The Regents of the University of California. All rights reserved.
@@ -12,11 +11,7 @@
12 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software 14 * 3. Neither the name of the University nor the names of its contributors
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software 15 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission. 16 * without specific prior written permission.
22 * 17 *
@@ -33,36 +28,40 @@
33 * SUCH DAMAGE. 28 * SUCH DAMAGE.
34 */ 29 */
35 30
36#if defined(LIBC_SCCS) && !defined(lint)
37#if 0
38static char sccsid[] = "@(#)getprotoname.c 8.1 (Berkeley) 6/4/93";
39#else
40static char rcsid[] = "$NetBSD: getprotoname.c,v 1.4 1995/02/25 06:20:36 cgd Exp $";
41#endif
42#endif /* LIBC_SCCS and not lint */
43
44#include <netdb.h> 31#include <netdb.h>
32#include <stdio.h>
45#include <string.h> 33#include <string.h>
46 34
47extern int _proto_stayopen; 35int
48 36getprotobyname_r(const char *name, struct protoent *pe,
49struct protoent * 37 struct protoent_data *pd)
50getprotobyname(name)
51 register const char *name;
52{ 38{
53 register struct protoent *p; 39 char **cp;
54 register char **cp; 40 int error;
55 41
56 setprotoent(_proto_stayopen); 42 setprotoent_r(pd->stayopen, pd);
57 while (p = getprotoent()) { 43 while ((error = getprotoent_r(pe, pd)) == 0) {
58 if (strcmp(p->p_name, name) == 0) 44 if (strcmp(pe->p_name, name) == 0)
59 break; 45 break;
60 for (cp = p->p_aliases; *cp != 0; cp++) 46 for (cp = pe->p_aliases; *cp != 0; cp++)
61 if (strcmp(*cp, name) == 0) 47 if (strcmp(*cp, name) == 0)
62 goto found; 48 goto found;
63 } 49 }
64found: 50found:
65 if (!_proto_stayopen) 51 if (!pd->stayopen && pd->fp != NULL) {
66 endprotoent(); 52 fclose(pd->fp);
67 return (p); 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);
68} 67}
diff --git a/src/lib/libc/net/getrrsetbyname.3 b/src/lib/libc/net/getrrsetbyname.3
new file mode 100644
index 0000000000..121cb67fcc
--- /dev/null
+++ b/src/lib/libc/net/getrrsetbyname.3
@@ -0,0 +1,166 @@
1.\" $OpenBSD: getrrsetbyname.3,v 1.15 2007/05/31 19:19:30 jmc Exp $
2.\"
3.\" Copyright (C) 2000, 2001 Internet Software Consortium.
4.\"
5.\" Permission to use, copy, modify, and distribute this software for any
6.\" purpose with or without fee is hereby granted, provided that the above
7.\" copyright notice and this permission notice appear in all copies.
8.\"
9.\" THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
10.\" DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
11.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
12.\" INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
13.\" INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
14.\" FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
15.\" NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
16.\" WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17.\"
18.Dd $Mdocdate: May 31 2007 $
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..2bbb6ccf83
--- /dev/null
+++ b/src/lib/libc/net/getrrsetbyname.c
@@ -0,0 +1,517 @@
1/* $OpenBSD: getrrsetbyname.c,v 1.12 2010/06/29 09:22:06 deraadt 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 MAXPACKET 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 union {
109 HEADER hdr;
110 u_char buf[MAXPACKET];
111 } answer;
112
113 /* check for invalid class and type */
114 if (rdclass > 0xffff || rdtype > 0xffff) {
115 result = ERRSET_INVAL;
116 goto fail;
117 }
118
119 /* don't allow queries of class or type ANY */
120 if (rdclass == 0xff || rdtype == 0xff) {
121 result = ERRSET_INVAL;
122 goto fail;
123 }
124
125 /* don't allow flags yet, unimplemented */
126 if (flags) {
127 result = ERRSET_INVAL;
128 goto fail;
129 }
130
131 /* initialize resolver */
132 if (_res_init(0) == -1) {
133 result = ERRSET_FAIL;
134 goto fail;
135 }
136
137#ifdef DEBUG
138 _resp->options |= RES_DEBUG;
139#endif /* DEBUG */
140
141#ifdef RES_USE_DNSSEC
142 /* turn on DNSSEC if EDNS0 is configured */
143 if (_resp->options & RES_USE_EDNS0)
144 _resp->options |= RES_USE_DNSSEC;
145#endif /* RES_USE_DNSEC */
146
147 /* make query */
148 length = res_query(hostname, (signed int) rdclass, (signed int) rdtype,
149 answer.buf, sizeof(answer.buf));
150 if (length < 0) {
151 switch(h_errno) {
152 case HOST_NOT_FOUND:
153 result = ERRSET_NONAME;
154 goto fail;
155 case NO_DATA:
156 result = ERRSET_NODATA;
157 goto fail;
158 default:
159 result = ERRSET_FAIL;
160 goto fail;
161 }
162 }
163
164 /* parse result */
165 response = parse_dns_response(answer.buf, length);
166 if (response == NULL) {
167 result = ERRSET_FAIL;
168 goto fail;
169 }
170
171 if (response->header.qdcount != 1) {
172 result = ERRSET_FAIL;
173 goto fail;
174 }
175
176 /* initialize rrset */
177 rrset = calloc(1, sizeof(struct rrsetinfo));
178 if (rrset == NULL) {
179 result = ERRSET_NOMEMORY;
180 goto fail;
181 }
182 rrset->rri_rdclass = response->query->class;
183 rrset->rri_rdtype = response->query->type;
184 rrset->rri_ttl = response->answer->ttl;
185 rrset->rri_nrdatas = response->header.ancount;
186
187 /* check for authenticated data */
188 if (response->header.ad == 1)
189 rrset->rri_flags |= RRSET_VALIDATED;
190
191 /* copy name from answer section */
192 rrset->rri_name = strdup(response->answer->name);
193 if (rrset->rri_name == NULL) {
194 result = ERRSET_NOMEMORY;
195 goto fail;
196 }
197
198 /* count answers */
199 rrset->rri_nrdatas = count_dns_rr(response->answer, rrset->rri_rdclass,
200 rrset->rri_rdtype);
201 rrset->rri_nsigs = count_dns_rr(response->answer, rrset->rri_rdclass,
202 T_RRSIG);
203
204 /* allocate memory for answers */
205 rrset->rri_rdatas = calloc(rrset->rri_nrdatas,
206 sizeof(struct rdatainfo));
207 if (rrset->rri_rdatas == NULL) {
208 result = ERRSET_NOMEMORY;
209 goto fail;
210 }
211
212 /* allocate memory for signatures */
213 rrset->rri_sigs = calloc(rrset->rri_nsigs, sizeof(struct rdatainfo));
214 if (rrset->rri_sigs == NULL) {
215 result = ERRSET_NOMEMORY;
216 goto fail;
217 }
218
219 /* copy answers & signatures */
220 for (rr = response->answer, index_ans = 0, index_sig = 0;
221 rr; rr = rr->next) {
222
223 rdata = NULL;
224
225 if (rr->class == rrset->rri_rdclass &&
226 rr->type == rrset->rri_rdtype)
227 rdata = &rrset->rri_rdatas[index_ans++];
228
229 if (rr->class == rrset->rri_rdclass &&
230 rr->type == T_RRSIG)
231 rdata = &rrset->rri_sigs[index_sig++];
232
233 if (rdata) {
234 rdata->rdi_length = rr->size;
235 rdata->rdi_data = malloc(rr->size);
236
237 if (rdata->rdi_data == NULL) {
238 result = ERRSET_NOMEMORY;
239 goto fail;
240 }
241 memcpy(rdata->rdi_data, rr->rdata, rr->size);
242 }
243 }
244 free_dns_response(response);
245
246 *res = rrset;
247 return (ERRSET_SUCCESS);
248
249fail:
250 if (rrset != NULL)
251 freerrset(rrset);
252 if (response != NULL)
253 free_dns_response(response);
254 return (result);
255}
256
257void
258freerrset(struct rrsetinfo *rrset)
259{
260 u_int16_t i;
261
262 if (rrset == NULL)
263 return;
264
265 if (rrset->rri_rdatas) {
266 for (i = 0; i < rrset->rri_nrdatas; i++) {
267 if (rrset->rri_rdatas[i].rdi_data == NULL)
268 break;
269 free(rrset->rri_rdatas[i].rdi_data);
270 }
271 free(rrset->rri_rdatas);
272 }
273
274 if (rrset->rri_sigs) {
275 for (i = 0; i < rrset->rri_nsigs; i++) {
276 if (rrset->rri_sigs[i].rdi_data == NULL)
277 break;
278 free(rrset->rri_sigs[i].rdi_data);
279 }
280 free(rrset->rri_sigs);
281 }
282
283 if (rrset->rri_name)
284 free(rrset->rri_name);
285 free(rrset);
286}
287
288/*
289 * DNS response parsing routines
290 */
291static struct dns_response *
292parse_dns_response(const u_char *answer, int size)
293{
294 struct dns_response *resp;
295 const u_char *cp;
296
297 /* allocate memory for the response */
298 resp = calloc(1, sizeof(*resp));
299 if (resp == NULL)
300 return (NULL);
301
302 /* initialize current pointer */
303 cp = answer;
304
305 /* copy header */
306 memcpy(&resp->header, cp, HFIXEDSZ);
307 cp += HFIXEDSZ;
308
309 /* fix header byte order */
310 resp->header.qdcount = ntohs(resp->header.qdcount);
311 resp->header.ancount = ntohs(resp->header.ancount);
312 resp->header.nscount = ntohs(resp->header.nscount);
313 resp->header.arcount = ntohs(resp->header.arcount);
314
315 /* there must be at least one query */
316 if (resp->header.qdcount < 1) {
317 free_dns_response(resp);
318 return (NULL);
319 }
320
321 /* parse query section */
322 resp->query = parse_dns_qsection(answer, size, &cp,
323 resp->header.qdcount);
324 if (resp->header.qdcount && resp->query == NULL) {
325 free_dns_response(resp);
326 return (NULL);
327 }
328
329 /* parse answer section */
330 resp->answer = parse_dns_rrsection(answer, size, &cp,
331 resp->header.ancount);
332 if (resp->header.ancount && resp->answer == NULL) {
333 free_dns_response(resp);
334 return (NULL);
335 }
336
337 /* parse authority section */
338 resp->authority = parse_dns_rrsection(answer, size, &cp,
339 resp->header.nscount);
340 if (resp->header.nscount && resp->authority == NULL) {
341 free_dns_response(resp);
342 return (NULL);
343 }
344
345 /* parse additional section */
346 resp->additional = parse_dns_rrsection(answer, size, &cp,
347 resp->header.arcount);
348 if (resp->header.arcount && resp->additional == NULL) {
349 free_dns_response(resp);
350 return (NULL);
351 }
352
353 return (resp);
354}
355
356static struct dns_query *
357parse_dns_qsection(const u_char *answer, int size, const u_char **cp, int count)
358{
359 struct dns_query *head, *curr, *prev;
360 int i, length;
361 char name[MAXDNAME];
362
363 for (i = 1, head = NULL, prev = NULL; i <= count; i++, prev = curr) {
364
365 /* allocate and initialize struct */
366 curr = calloc(1, sizeof(struct dns_query));
367 if (curr == NULL) {
368 free_dns_query(head);
369 return (NULL);
370 }
371 if (head == NULL)
372 head = curr;
373 if (prev != NULL)
374 prev->next = curr;
375
376 /* name */
377 length = dn_expand(answer, answer + size, *cp, name,
378 sizeof(name));
379 if (length < 0) {
380 free_dns_query(head);
381 return (NULL);
382 }
383 curr->name = strdup(name);
384 if (curr->name == NULL) {
385 free_dns_query(head);
386 return (NULL);
387 }
388 *cp += length;
389
390 /* type */
391 curr->type = _getshort(*cp);
392 *cp += INT16SZ;
393
394 /* class */
395 curr->class = _getshort(*cp);
396 *cp += INT16SZ;
397 }
398
399 return (head);
400}
401
402static struct dns_rr *
403parse_dns_rrsection(const u_char *answer, int size, const u_char **cp,
404 int count)
405{
406 struct dns_rr *head, *curr, *prev;
407 int i, length;
408 char name[MAXDNAME];
409
410 for (i = 1, head = NULL, prev = NULL; i <= count; i++, prev = curr) {
411
412 /* allocate and initialize struct */
413 curr = calloc(1, sizeof(struct dns_rr));
414 if (curr == NULL) {
415 free_dns_rr(head);
416 return (NULL);
417 }
418 if (head == NULL)
419 head = curr;
420 if (prev != NULL)
421 prev->next = curr;
422
423 /* name */
424 length = dn_expand(answer, answer + size, *cp, name,
425 sizeof(name));
426 if (length < 0) {
427 free_dns_rr(head);
428 return (NULL);
429 }
430 curr->name = strdup(name);
431 if (curr->name == NULL) {
432 free_dns_rr(head);
433 return (NULL);
434 }
435 *cp += length;
436
437 /* type */
438 curr->type = _getshort(*cp);
439 *cp += INT16SZ;
440
441 /* class */
442 curr->class = _getshort(*cp);
443 *cp += INT16SZ;
444
445 /* ttl */
446 curr->ttl = _getlong(*cp);
447 *cp += INT32SZ;
448
449 /* rdata size */
450 curr->size = _getshort(*cp);
451 *cp += INT16SZ;
452
453 /* rdata itself */
454 curr->rdata = malloc(curr->size);
455 if (curr->rdata == NULL) {
456 free_dns_rr(head);
457 return (NULL);
458 }
459 memcpy(curr->rdata, *cp, curr->size);
460 *cp += curr->size;
461 }
462
463 return (head);
464}
465
466static void
467free_dns_query(struct dns_query *p)
468{
469 if (p == NULL)
470 return;
471
472 if (p->name)
473 free(p->name);
474 free_dns_query(p->next);
475 free(p);
476}
477
478static void
479free_dns_rr(struct dns_rr *p)
480{
481 if (p == NULL)
482 return;
483
484 if (p->name)
485 free(p->name);
486 if (p->rdata)
487 free(p->rdata);
488 free_dns_rr(p->next);
489 free(p);
490}
491
492static void
493free_dns_response(struct dns_response *p)
494{
495 if (p == NULL)
496 return;
497
498 free_dns_query(p->query);
499 free_dns_rr(p->answer);
500 free_dns_rr(p->authority);
501 free_dns_rr(p->additional);
502 free(p);
503}
504
505static int
506count_dns_rr(struct dns_rr *p, u_int16_t class, u_int16_t type)
507{
508 int n = 0;
509
510 while(p) {
511 if (p->class == class && p->type == type)
512 n++;
513 p = p->next;
514 }
515
516 return (n);
517}
diff --git a/src/lib/libc/net/getservbyname.c b/src/lib/libc/net/getservbyname.c
index b4a6311966..beb8943af6 100644
--- a/src/lib/libc/net/getservbyname.c
+++ b/src/lib/libc/net/getservbyname.c
@@ -1,5 +1,4 @@
1/* $NetBSD: getservbyname.c,v 1.4 1995/02/25 06:20:36 cgd Exp $ */ 1/* $OpenBSD: getservbyname.c,v 1.10 2005/08/06 20:30:03 espie Exp $ */
2
3/* 2/*
4 * Copyright (c) 1983, 1993 3 * Copyright (c) 1983, 1993
5 * The Regents of the University of California. All rights reserved. 4 * The Regents of the University of California. All rights reserved.
@@ -12,11 +11,7 @@
12 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software 14 * 3. Neither the name of the University nor the names of its contributors
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software 15 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission. 16 * without specific prior written permission.
22 * 17 *
@@ -33,39 +28,43 @@
33 * SUCH DAMAGE. 28 * SUCH DAMAGE.
34 */ 29 */
35 30
36#if defined(LIBC_SCCS) && !defined(lint)
37#if 0
38static char sccsid[] = "@(#)getservbyname.c 8.1 (Berkeley) 6/4/93";
39#else
40static char rcsid[] = "$NetBSD: getservbyname.c,v 1.4 1995/02/25 06:20:36 cgd Exp $";
41#endif
42#endif /* LIBC_SCCS and not lint */
43
44#include <netdb.h> 31#include <netdb.h>
32#include <stdio.h>
45#include <string.h> 33#include <string.h>
46 34
47extern int _serv_stayopen; 35int
48 36getservbyname_r(const char *name, const char *proto, struct servent *se,
49struct servent * 37 struct servent_data *sd)
50getservbyname(name, proto)
51 const char *name, *proto;
52{ 38{
53 register struct servent *p; 39 char **cp;
54 register char **cp; 40 int error;
55 41
56 setservent(_serv_stayopen); 42 setservent_r(sd->stayopen, sd);
57 while (p = getservent()) { 43 while ((error = getservent_r(se, sd)) == 0) {
58 if (strcmp(name, p->s_name) == 0) 44 if (strcmp(name, se->s_name) == 0)
59 goto gotname; 45 goto gotname;
60 for (cp = p->s_aliases; *cp; cp++) 46 for (cp = se->s_aliases; *cp; cp++)
61 if (strcmp(name, *cp) == 0) 47 if (strcmp(name, *cp) == 0)
62 goto gotname; 48 goto gotname;
63 continue; 49 continue;
64gotname: 50gotname:
65 if (proto == 0 || strcmp(p->s_proto, proto) == 0) 51 if (proto == 0 || strcmp(se->s_proto, proto) == 0)
66 break; 52 break;
67 } 53 }
68 if (!_serv_stayopen) 54 if (!sd->stayopen && sd->fp != NULL) {
69 endservent(); 55 fclose(sd->fp);
70 return (p); 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);
71} 70}
diff --git a/src/lib/libc/net/getservbyport.c b/src/lib/libc/net/getservbyport.c
index c34790737b..46679ba366 100644
--- a/src/lib/libc/net/getservbyport.c
+++ b/src/lib/libc/net/getservbyport.c
@@ -1,5 +1,4 @@
1/* $NetBSD: getservbyport.c,v 1.4 1995/02/25 06:20:37 cgd Exp $ */ 1/* $OpenBSD: getservbyport.c,v 1.7 2005/08/06 20:30:03 espie Exp $ */
2
3/* 2/*
4 * Copyright (c) 1983, 1993 3 * Copyright (c) 1983, 1993
5 * The Regents of the University of California. All rights reserved. 4 * The Regents of the University of California. All rights reserved.
@@ -12,11 +11,7 @@
12 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software 14 * 3. Neither the name of the University nor the names of its contributors
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software 15 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission. 16 * without specific prior written permission.
22 * 17 *
@@ -33,34 +28,37 @@
33 * SUCH DAMAGE. 28 * SUCH DAMAGE.
34 */ 29 */
35 30
36#if defined(LIBC_SCCS) && !defined(lint)
37#if 0
38static char sccsid[] = "@(#)getservbyport.c 8.1 (Berkeley) 6/4/93";
39#else
40static char rcsid[] = "$NetBSD: getservbyport.c,v 1.4 1995/02/25 06:20:37 cgd Exp $";
41#endif
42#endif /* LIBC_SCCS and not lint */
43
44#include <netdb.h> 31#include <netdb.h>
32#include <stdio.h>
45#include <string.h> 33#include <string.h>
46 34
47extern int _serv_stayopen; 35int
48 36getservbyport_r(int port, const char *proto, struct servent *se,
49struct servent * 37 struct servent_data *sd)
50getservbyport(port, proto)
51 int port;
52 const char *proto;
53{ 38{
54 register struct servent *p; 39 int error;
55 40
56 setservent(_serv_stayopen); 41 setservent_r(sd->stayopen, sd);
57 while (p = getservent()) { 42 while ((error = getservent_r(se, sd)) == 0) {
58 if (p->s_port != port) 43 if (se->s_port != port)
59 continue; 44 continue;
60 if (proto == 0 || strcmp(p->s_proto, proto) == 0) 45 if (proto == 0 || strcmp(se->s_proto, proto) == 0)
61 break; 46 break;
62 } 47 }
63 if (!_serv_stayopen) 48 if (!sd->stayopen && sd->fp != NULL) {
64 endservent(); 49 fclose(sd->fp);
65 return (p); 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);
66} 64}
diff --git a/src/lib/libc/net/getservent.3 b/src/lib/libc/net/getservent.3
index 9e0656be00..7888b5f1b8 100644
--- a/src/lib/libc/net/getservent.3
+++ b/src/lib/libc/net/getservent.3
@@ -1,4 +1,4 @@
1.\" $NetBSD: getservent.3,v 1.3 1995/02/25 06:20:38 cgd Exp $ 1.\" $OpenBSD: getservent.3,v 1.20 2007/05/31 19:19:30 jmc Exp $
2.\" 2.\"
3.\" Copyright (c) 1983, 1991, 1993 3.\" Copyright (c) 1983, 1991, 1993
4.\" The Regents of the University of California. All rights reserved. 4.\" The Regents of the University of California. All rights reserved.
@@ -11,11 +11,7 @@
11.\" 2. Redistributions in binary form must reproduce the above copyright 11.\" 2. Redistributions in binary form must reproduce the above copyright
12.\" notice, this list of conditions and the following disclaimer in the 12.\" notice, this list of conditions and the following disclaimer in the
13.\" documentation and/or other materials provided with the distribution. 13.\" documentation and/or other materials provided with the distribution.
14.\" 3. All advertising materials mentioning features or use of this software 14.\" 3. Neither the name of the University nor the names of its contributors
15.\" must display the following acknowledgement:
16.\" This product includes software developed by the University of
17.\" California, Berkeley and its contributors.
18.\" 4. Neither the name of the University nor the names of its contributors
19.\" may be used to endorse or promote products derived from this software 15.\" may be used to endorse or promote products derived from this software
20.\" without specific prior written permission. 16.\" without specific prior written permission.
21.\" 17.\"
@@ -31,41 +27,51 @@
31.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32.\" SUCH DAMAGE. 28.\" SUCH DAMAGE.
33.\" 29.\"
34.\" @(#)getservent.3 8.3 (Berkeley) 1/12/94 30.Dd $Mdocdate: May 31 2007 $
35.\"
36.Dd January 12, 1994
37.Dt GETSERVENT 3 31.Dt GETSERVENT 3
38.Os BSD 4.2 32.Os
39.Sh NAME 33.Sh NAME
40.Nm getservent , 34.Nm getservent ,
35.Nm getservent_r ,
41.Nm getservbyport , 36.Nm getservbyport ,
37.Nm getservbyport_r ,
42.Nm getservbyname , 38.Nm getservbyname ,
39.Nm getservbyname_r ,
43.Nm setservent , 40.Nm setservent ,
44.Nm endservent 41.Nm setservent_r ,
42.Nm endservent ,
43.Nm endservent_r
45.Nd get service entry 44.Nd get service entry
46.Sh SYNOPSIS 45.Sh SYNOPSIS
47.Fd #include <netdb.h> 46.Fd #include <netdb.h>
48.Ft struct servent * 47.Ft struct servent *
49.Fn getservent 48.Fn getservent "void"
49.Ft int
50.Fn getservent_r "struct servent *servent" "struct servent_data *servent_data"
50.Ft struct servent * 51.Ft struct servent *
51.Fn getservbyname "char *name" "char *proto" 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"
52.Ft struct servent * 55.Ft struct servent *
53.Fn getservbyport "int port" proto 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"
54.Ft void 59.Ft void
55.Fn setservent "int stayopen" 60.Fn setservent "int stayopen"
56.Ft void 61.Ft void
57.Fn endservent 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"
58.Sh DESCRIPTION 67.Sh DESCRIPTION
59The 68The
60.Fn getservent , 69.Fn getservent ,
61.Fn getservbyname , 70.Fn getservbyname ,
62and 71and
63.Fn getservbyport 72.Fn getservbyport
64functions 73functions each return a pointer to an object with the following structure
65each return a pointer to an object with the 74containing the broken-out fields of a line in the network services database,
66following structure
67containing the broken-out
68fields of a line in the network services data base,
69.Pa /etc/services . 75.Pa /etc/services .
70.Bd -literal -offset indent 76.Bd -literal -offset indent
71struct servent { 77struct servent {
@@ -81,64 +87,113 @@ The members of this structure are:
81.It Fa s_name 87.It Fa s_name
82The official name of the service. 88The official name of the service.
83.It Fa s_aliases 89.It Fa s_aliases
84A zero terminated list of alternate names for the service. 90A null-terminated list of alternate names for the service.
85.It Fa s_port 91.It Fa s_port
86The port number at which the service resides. 92The port number at which the service resides.
87Port numbers are returned in network byte order. 93Port numbers are returned in network byte order.
88.It Fa s_proto 94.It Fa s_proto
89The name of the protocol to use when contacting the 95The name of the protocol to use when contacting the service.
90service.
91.El 96.El
92.Pp 97.Pp
93The 98The
94.Fn getservent 99.Fn getservent
95function 100function reads the next line of the file, opening the file if necessary.
96reads the next line of the file, opening the file if necessary.
97.Pp 101.Pp
98The 102The
99.Fn setservent 103.Fn setservent
100function 104function opens and rewinds the file.
101opens and rewinds the file. If the 105If the
102.Fa stayopen 106.Fa stayopen
103flag is non-zero, 107flag is non-zero,
104the net data base will not be closed after each call to 108the services database will not be closed after each call to
105.Fn getservbyname 109.Fn getservbyname
106or 110or
107.Fn getservbyport . 111.Fn getservbyport .
108.Pp 112.Pp
109The 113The
110.Fn endservent 114.Fn endservent
111function 115function closes the file.
112closes the file.
113.Pp 116.Pp
114The 117The
115.Fn getservbyname 118.Fn getservbyname
116and 119and
117.Fn getservbyport 120.Fn getservbyport
118functions 121functions sequentially search from the beginning of the file until a
119sequentially search from the beginning 122matching protocol name or port number (specified in network byte order)
120of the file until a matching 123is found, or until
121protocol name or
122port number is found,
123or until
124.Dv EOF 124.Dv EOF
125is encountered. 125is encountered.
126If a protocol name is also supplied (non- 126If a protocol name is also supplied (non-null),
127.Dv NULL ) ,
128searches must also match the protocol. 127searches must also match the protocol.
129.ne 1i 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.
130.Sh FILES 170.Sh FILES
131.Bl -tag -width /etc/services -compact 171.Bl -tag -width /etc/services -compact
132.It Pa /etc/services 172.It Pa /etc/services
133.El 173.El
134.Sh DIAGNOSTICS
135Null pointer
136(0) returned on
137.Dv EOF
138or error.
139.Sh SEE ALSO 174.Sh SEE ALSO
140.Xr getprotoent 3 , 175.Xr getprotoent 3 ,
141.Xr services 5 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.
142.Sh HISTORY 197.Sh HISTORY
143The 198The
144.Fn getservent , 199.Fn getservent ,
@@ -147,11 +202,19 @@ The
147.Fn setservent , 202.Fn setservent ,
148and 203and
149.Fn endservent 204.Fn endservent
150functions appeared in 205functions appeared in
151.Bx 4.2 . 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 .
152.Sh BUGS 217.Sh BUGS
153These functions use static data storage; 218The non-reentrant functions use static data storage; if the data is needed
154if the data is needed for future use, it should be 219for future use, it should be copied before any subsequent calls overwrite it.
155copied before any subsequent calls overwrite it. 220Expecting port numbers to fit in a 32-bit quantity is probably naive.
156Expecting port numbers to fit in a 32 bit
157quantity is probably naive.
diff --git a/src/lib/libc/net/getservent.c b/src/lib/libc/net/getservent.c
index 316891450e..c81a4cf3e2 100644
--- a/src/lib/libc/net/getservent.c
+++ b/src/lib/libc/net/getservent.c
@@ -1,5 +1,4 @@
1/* $NetBSD: getservent.c,v 1.4 1995/02/25 06:20:38 cgd Exp $ */ 1/* $OpenBSD: getservent.c,v 1.12 2007/09/02 15:19:17 deraadt Exp $ */
2
3/* 2/*
4 * Copyright (c) 1983, 1993 3 * Copyright (c) 1983, 1993
5 * The Regents of the University of California. All rights reserved. 4 * The Regents of the University of California. All rights reserved.
@@ -12,11 +11,7 @@
12 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software 14 * 3. Neither the name of the University nor the names of its contributors
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software 15 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission. 16 * without specific prior written permission.
22 * 17 *
@@ -33,69 +28,66 @@
33 * SUCH DAMAGE. 28 * SUCH DAMAGE.
34 */ 29 */
35 30
36#if defined(LIBC_SCCS) && !defined(lint)
37#if 0
38static char sccsid[] = "@(#)getservent.c 8.1 (Berkeley) 6/4/93";
39#else
40static char rcsid[] = "$NetBSD: getservent.c,v 1.4 1995/02/25 06:20:38 cgd Exp $";
41#endif
42#endif /* LIBC_SCCS and not lint */
43
44#include <sys/types.h> 31#include <sys/types.h>
45#include <sys/socket.h> 32#include <sys/socket.h>
33
34#include <errno.h>
35#include <limits.h>
46#include <netdb.h> 36#include <netdb.h>
47#include <stdio.h> 37#include <stdio.h>
48#include <string.h> 38#include <string.h>
49#include <stdlib.h> 39#include <stdlib.h>
50 40
51#define MAXALIASES 35
52
53static FILE *servf = NULL;
54static char line[BUFSIZ+1];
55static struct servent serv;
56static char *serv_aliases[MAXALIASES];
57int _serv_stayopen;
58
59void 41void
60setservent(f) 42setservent_r(int f, struct servent_data *sd)
61 int f;
62{ 43{
63 if (servf == NULL) 44 if (sd->fp == NULL)
64 servf = fopen(_PATH_SERVICES, "r" ); 45 sd->fp = fopen(_PATH_SERVICES, "r" );
65 else 46 else
66 rewind(servf); 47 rewind(sd->fp);
67 _serv_stayopen |= f; 48 sd->stayopen |= f;
68} 49}
69 50
70void 51void
71endservent() 52endservent_r(struct servent_data *sd)
72{ 53{
73 if (servf) { 54 if (sd->fp) {
74 fclose(servf); 55 fclose(sd->fp);
75 servf = NULL; 56 sd->fp = NULL;
76 } 57 }
77 _serv_stayopen = 0; 58 free(sd->aliases);
59 sd->aliases = NULL;
60 sd->maxaliases = 0;
61 free(sd->line);
62 sd->line = NULL;
63 sd->stayopen = 0;
78} 64}
79 65
80struct servent * 66int
81getservent() 67getservent_r(struct servent *se, struct servent_data *sd)
82{ 68{
83 char *p; 69 char *p, *cp, **q, *endp;
84 register char *cp, **q; 70 size_t len;
71 long l;
72 int serrno;
85 73
86 if (servf == NULL && (servf = fopen(_PATH_SERVICES, "r" )) == NULL) 74 if (sd->fp == NULL && (sd->fp = fopen(_PATH_SERVICES, "r" )) == NULL)
87 return (NULL); 75 return (-1);
88again: 76again:
89 if ((p = fgets(line, BUFSIZ, servf)) == NULL) 77 if ((p = fgetln(sd->fp, &len)) == NULL)
90 return (NULL); 78 return (-1);
91 if (*p == '#') 79 if (len == 0 || *p == '#' || *p == '\n')
92 goto again; 80 goto again;
93 cp = strpbrk(p, "#\n"); 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);
94 if (cp == NULL) 86 if (cp == NULL)
95 goto again; 87 return (-1);
96 *cp = '\0'; 88 sd->line = se->s_name = memcpy(cp, p, len);
97 serv.s_name = p; 89 cp[len] = '\0';
98 p = strpbrk(p, " \t"); 90 p = strpbrk(cp, " \t");
99 if (p == NULL) 91 if (p == NULL)
100 goto again; 92 goto again;
101 *p++ = '\0'; 93 *p++ = '\0';
@@ -105,9 +97,22 @@ again:
105 if (cp == NULL) 97 if (cp == NULL)
106 goto again; 98 goto again;
107 *cp++ = '\0'; 99 *cp++ = '\0';
108 serv.s_port = htons((u_short)atoi(p)); 100 l = strtol(p, &endp, 10);
109 serv.s_proto = cp; 101 if (endp == p || *endp != '\0' || l < 0 || l > USHRT_MAX)
110 q = serv.s_aliases = serv_aliases; 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 = calloc(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;
111 cp = strpbrk(cp, " \t"); 116 cp = strpbrk(cp, " \t");
112 if (cp != NULL) 117 if (cp != NULL)
113 *cp++ = '\0'; 118 *cp++ = '\0';
@@ -116,12 +121,48 @@ again:
116 cp++; 121 cp++;
117 continue; 122 continue;
118 } 123 }
119 if (q < &serv_aliases[MAXALIASES - 1]) 124 if (q == &se->s_aliases[sd->maxaliases - 1]) {
120 *q++ = cp; 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;
121 cp = strpbrk(cp, " \t"); 138 cp = strpbrk(cp, " \t");
122 if (cp != NULL) 139 if (cp != NULL)
123 *cp++ = '\0'; 140 *cp++ = '\0';
124 } 141 }
125 *q = NULL; 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);
126 return (&serv); 167 return (&serv);
127} 168}
diff --git a/src/lib/libc/net/herror.c b/src/lib/libc/net/herror.c
index 41adbf1055..7787115a9d 100644
--- a/src/lib/libc/net/herror.c
+++ b/src/lib/libc/net/herror.c
@@ -1,9 +1,11 @@
1/* $NetBSD: herror.c,v 1.5 1995/02/25 06:20:39 cgd Exp $ */ 1/* $OpenBSD: herror.c,v 1.8 2005/08/06 20:30:03 espie Exp $ */
2 2
3/*- 3/*
4 * ++Copyright++ 1987, 1993
5 * -
4 * Copyright (c) 1987, 1993 6 * Copyright (c) 1987, 1993
5 * The Regents of the University of California. All rights reserved. 7 * The Regents of the University of California. All rights reserved.
6 * 8 *
7 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
9 * are met: 11 * are met:
@@ -12,14 +14,10 @@
12 * 2. Redistributions in binary form must reproduce the above copyright 14 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 15 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 16 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software 17 * 3. Neither the name of the University nor the names of its contributors
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software 18 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission. 19 * without specific prior written permission.
22 * 20 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -53,29 +51,21 @@
53 * --Copyright-- 51 * --Copyright--
54 */ 52 */
55 53
56#if defined(LIBC_SCCS) && !defined(lint)
57#if 0
58static char sccsid[] = "@(#)herror.c 8.1 (Berkeley) 6/4/93";
59static char rcsid[] = "$Id: herror.c,v 4.9.1.1 1993/05/02 23:14:35 vixie Rel ";
60#else
61static char rcsid[] = "$NetBSD: herror.c,v 1.5 1995/02/25 06:20:39 cgd Exp $";
62#endif
63#endif /* LIBC_SCCS and not lint */
64
65#include <sys/types.h> 54#include <sys/types.h>
55#include <sys/param.h>
66#include <sys/uio.h> 56#include <sys/uio.h>
67#include <netdb.h> 57#include <netdb.h>
68#include <unistd.h> 58#include <unistd.h>
69#include <string.h> 59#include <string.h>
70 60
71char *h_errlist[] = { 61const char * const h_errlist[] = {
72 "Error 0", 62 "Resolver Error 0 (no error)",
73 "Unknown host", /* 1 HOST_NOT_FOUND */ 63 "Unknown host", /* 1 HOST_NOT_FOUND */
74 "Host name lookup failure", /* 2 TRY_AGAIN */ 64 "Host name lookup failure", /* 2 TRY_AGAIN */
75 "Unknown server error", /* 3 NO_RECOVERY */ 65 "Unknown server error", /* 3 NO_RECOVERY */
76 "No address associated with name", /* 4 NO_ADDRESS */ 66 "No address associated with name", /* 4 NO_ADDRESS */
77}; 67};
78int h_nerr = { sizeof(h_errlist)/sizeof(h_errlist[0]) }; 68const int h_nerr = { sizeof h_errlist / sizeof h_errlist[0] };
79 69
80extern int h_errno; 70extern int h_errno;
81 71
@@ -84,11 +74,10 @@ extern int h_errno;
84 * print the error indicated by the h_errno value. 74 * print the error indicated by the h_errno value.
85 */ 75 */
86void 76void
87herror(s) 77herror(const char *s)
88 const char *s;
89{ 78{
90 struct iovec iov[4]; 79 struct iovec iov[4];
91 register struct iovec *v = iov; 80 struct iovec *v = iov;
92 81
93 if (s && *s) { 82 if (s && *s) {
94 v->iov_base = (char *)s; 83 v->iov_base = (char *)s;
@@ -98,8 +87,7 @@ herror(s)
98 v->iov_len = 2; 87 v->iov_len = 2;
99 v++; 88 v++;
100 } 89 }
101 v->iov_base = (u_int)h_errno < h_nerr ? 90 v->iov_base = (char *)hstrerror(h_errno);
102 h_errlist[h_errno] : "Unknown error";
103 v->iov_len = strlen(v->iov_base); 91 v->iov_len = strlen(v->iov_base);
104 v++; 92 v++;
105 v->iov_base = "\n"; 93 v->iov_base = "\n";
@@ -107,9 +95,12 @@ herror(s)
107 writev(STDERR_FILENO, iov, (v - iov) + 1); 95 writev(STDERR_FILENO, iov, (v - iov) + 1);
108} 96}
109 97
110char * 98const char *
111hstrerror(err) 99hstrerror(int err)
112 int err;
113{ 100{
114 return (u_int)err < h_nerr ? h_errlist[err] : "Unknown resolver error"; 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");
115} 106}
diff --git a/src/lib/libc/net/htonl.c b/src/lib/libc/net/htonl.c
index ac85cb0fd7..5ab4189597 100644
--- a/src/lib/libc/net/htonl.c
+++ b/src/lib/libc/net/htonl.c
@@ -1,29 +1,21 @@
1/* $NetBSD: htonl.c,v 1.5 1995/04/28 23:25:14 jtc Exp $ */ 1/* $OpenBSD: htonl.c,v 1.6 2005/08/06 20:30:03 espie Exp $ */
2
3/* 2/*
4 * Written by J.T. Conklin <jtc@netbsd.org>. 3 * Written by J.T. Conklin <jtc@netbsd.org>.
5 * Public domain. 4 * Public domain.
6 */ 5 */
7 6
8#if defined(LIBC_SCCS) && !defined(lint)
9static char *rcsid = "$NetBSD: htonl.c,v 1.5 1995/04/28 23:25:14 jtc Exp $";
10#endif
11
12#include <sys/types.h> 7#include <sys/types.h>
13#include <machine/endian.h> 8#include <machine/endian.h>
14 9
15#undef htonl 10#undef htonl
16 11
17unsigned long 12u_int32_t
18htonl(x) 13htonl(u_int32_t x)
19 unsigned long x;
20{ 14{
21 u_int32_t y = x;
22
23#if BYTE_ORDER == LITTLE_ENDIAN 15#if BYTE_ORDER == LITTLE_ENDIAN
24 u_char *s = (u_char *)&y; 16 u_char *s = (u_char *)&x;
25 return s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3]; 17 return (u_int32_t)(s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3]);
26#else 18#else
27 return y; 19 return x;
28#endif 20#endif
29} 21}
diff --git a/src/lib/libc/net/htons.c b/src/lib/libc/net/htons.c
index b2500a51d1..c8b73fdbb7 100644
--- a/src/lib/libc/net/htons.c
+++ b/src/lib/libc/net/htons.c
@@ -1,26 +1,20 @@
1/* $NetBSD: htons.c,v 1.5 1995/04/28 23:25:19 jtc Exp $ */ 1/* $OpenBSD: htons.c,v 1.8 2005/08/06 20:30:03 espie Exp $ */
2
3/* 2/*
4 * Written by J.T. Conklin <jtc@netbsd.org>. 3 * Written by J.T. Conklin <jtc@netbsd.org>.
5 * Public domain. 4 * Public domain.
6 */ 5 */
7 6
8#if defined(LIBC_SCCS) && !defined(lint)
9static char *rcsid = "$NetBSD: htons.c,v 1.5 1995/04/28 23:25:19 jtc Exp $";
10#endif
11
12#include <sys/types.h> 7#include <sys/types.h>
13#include <machine/endian.h> 8#include <machine/endian.h>
14 9
15#undef htons 10#undef htons
16 11
17unsigned short 12u_int16_t
18htons(x) 13htons(u_int16_t x)
19 unsigned short x;
20{ 14{
21#if BYTE_ORDER == LITTLE_ENDIAN 15#if BYTE_ORDER == LITTLE_ENDIAN
22 u_char *s = (u_char *) &x; 16 u_char *s = (u_char *) &x;
23 return s[0] << 8 | s[1]; 17 return (u_int16_t)(s[0] << 8 | s[1]);
24#else 18#else
25 return x; 19 return x;
26#endif 20#endif
diff --git a/src/lib/libc/net/if_indextoname.3 b/src/lib/libc/net/if_indextoname.3
new file mode 100644
index 0000000000..8ffc35a5fa
--- /dev/null
+++ b/src/lib/libc/net/if_indextoname.3
@@ -0,0 +1,144 @@
1.\" $OpenBSD: if_indextoname.3,v 1.11 2007/05/31 19:19:30 jmc Exp $
2.\" Copyright (c) 1983, 1991, 1993
3.\" The Regents of the University of California. All rights reserved.
4.\"
5.\" Redistribution and use in source and binary forms, with or without
6.\" modification, are permitted provided that the following conditions
7.\" are met:
8.\" 1. Redistributions of source code must retain the above copyright
9.\" notice, this list of conditions and the following disclaimer.
10.\" 2. Redistributions in binary form must reproduce the above copyright
11.\" notice, this list of conditions and the following disclaimer in the
12.\" documentation and/or other materials provided with the distribution.
13.\" 3. Neither the name of the University nor the names of its contributors
14.\" may be used to endorse or promote products derived from this software
15.\" without specific prior written permission.
16.\"
17.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27.\" SUCH DAMAGE.
28.\"
29.\" From: @(#)rcmd.3 8.1 (Berkeley) 6/4/93
30.\"
31.Dd $Mdocdate: May 31 2007 $
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..c5a771869b
--- /dev/null
+++ b/src/lib/libc/net/if_nameindex.c
@@ -0,0 +1,146 @@
1/* $OpenBSD: if_nameindex.c,v 1.10 2010/09/24 13:29:29 claudio 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}
141
142void
143if_freenameindex(struct if_nameindex *ptr)
144{
145 free(ptr);
146}
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
index 49bac97e96..3f198ae8e0 100644
--- a/src/lib/libc/net/inet.3
+++ b/src/lib/libc/net/inet.3
@@ -1,4 +1,5 @@
1.\" $NetBSD: inet.3,v 1.4 1995/02/27 09:45:26 chopps Exp $ 1.\" $OpenBSD: inet.3,v 1.22 2008/12/09 19:38:38 otto Exp $
2.\" $NetBSD: inet.3,v 1.7 1997/06/18 02:25:24 lukem Exp $
2.\" 3.\"
3.\" Copyright (c) 1983, 1990, 1991, 1993 4.\" Copyright (c) 1983, 1990, 1991, 1993
4.\" The Regents of the University of California. All rights reserved. 5.\" The Regents of the University of California. All rights reserved.
@@ -11,11 +12,7 @@
11.\" 2. Redistributions in binary form must reproduce the above copyright 12.\" 2. Redistributions in binary form must reproduce the above copyright
12.\" notice, this list of conditions and the following disclaimer in the 13.\" notice, this list of conditions and the following disclaimer in the
13.\" documentation and/or other materials provided with the distribution. 14.\" documentation and/or other materials provided with the distribution.
14.\" 3. All advertising materials mentioning features or use of this software 15.\" 3. Neither the name of the University nor the names of its contributors
15.\" must display the following acknowledgement:
16.\" This product includes software developed by the University of
17.\" California, Berkeley and its contributors.
18.\" 4. Neither the name of the University nor the names of its contributors
19.\" may be used to endorse or promote products derived from this software 16.\" may be used to endorse or promote products derived from this software
20.\" without specific prior written permission. 17.\" without specific prior written permission.
21.\" 18.\"
@@ -33,52 +30,74 @@
33.\" 30.\"
34.\" @(#)inet.3 8.1 (Berkeley) 6/4/93 31.\" @(#)inet.3 8.1 (Berkeley) 6/4/93
35.\" 32.\"
36.Dd June 4, 1993 33.Dd $Mdocdate: December 9 2008 $
37.Dt INET 3 34.Dt INET 3
38.Os BSD 4.2 35.Os
39.Sh NAME 36.Sh NAME
40.Nm inet_aton ,
41.Nm inet_addr , 37.Nm inet_addr ,
38.Nm inet_aton ,
39.Nm inet_lnaof ,
40.Nm inet_makeaddr ,
41.Nm inet_netof ,
42.Nm inet_network , 42.Nm inet_network ,
43.Nm inet_ntoa , 43.Nm inet_ntoa ,
44.Nm inet_makeaddr , 44.Nm inet_ntop ,
45.Nm inet_lnaof , 45.Nm inet_pton
46.Nm inet_netof
47.Nd Internet address manipulation routines 46.Nd Internet address manipulation routines
48.Sh SYNOPSIS 47.Sh SYNOPSIS
48.Fd #include <sys/types.h>
49.Fd #include <sys/socket.h> 49.Fd #include <sys/socket.h>
50.Fd #include <netinet/in.h> 50.Fd #include <netinet/in.h>
51.Fd #include <arpa/inet.h> 51.Fd #include <arpa/inet.h>
52.Ft int 52.Ft in_addr_t
53.Fn inet_aton "const char *cp" "struct in_addr *pin"
54.Ft unsigned long
55.Fn inet_addr "const char *cp" 53.Fn inet_addr "const char *cp"
56.Ft unsigned long 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
57.Fn inet_network "const char *cp" 63.Fn inet_network "const char *cp"
58.Ft char * 64.Ft char *
59.Fn inet_ntoa "struct in_addr in" 65.Fn inet_ntoa "struct in_addr in"
60.Ft struct in_addr 66.Ft const char *
61.Fn inet_makeaddr "int net" "int lna" 67.Fn inet_ntop "int af" "const void *src" "char *dst" "socklen_t size"
62.Ft unsigned long 68.Ft int
63.Fn inet_lnaof "struct in_addr in" 69.Fn inet_pton "int af" "const char *src" "void *dst"
64.Ft unsigned long
65.Fn inet_netof "struct in_addr in"
66.Sh DESCRIPTION 70.Sh DESCRIPTION
67The routines 71The routines
68.Fn inet_aton , 72.Fn inet_aton ,
69.Fn inet_addr 73.Fn inet_addr ,
70and 74and
71.Fn inet_network 75.Fn inet_network
72interpret character strings representing 76interpret character strings representing
73numbers expressed in the Internet standard 77numbers expressed in the Internet standard
74.Ql \&. 78.Dq dot
75notation. 79notation.
76The 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
77.Fn inet_aton 96.Fn inet_aton
78routine interprets the specified character string as an Internet address, 97routine interprets the specified character string as an Internet address,
79placing the address into the structure provided. 98placing the address into the structure provided.
80It returns 1 if the string was successfully interpreted, 99It returns 1 if the string was successfully interpreted,
81or 0 if the string is invalid. 100or 0 if the string was invalid.
82The 101The
83.Fn inet_addr 102.Fn inet_addr
84and 103and
@@ -86,17 +105,29 @@ and
86functions return numbers suitable for use 105functions return numbers suitable for use
87as Internet addresses and Internet network 106as Internet addresses and Internet network
88numbers, respectively. 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.
89The routine 121The routine
90.Fn inet_ntoa 122.Fn inet_ntoa
91takes an Internet address and returns an 123takes an Internet address and returns an
92.Tn ASCII 124ASCII string representing the address in dot notation.
93string representing the address in 125The routine
94.Ql \&.
95notation. The routine
96.Fn inet_makeaddr 126.Fn inet_makeaddr
97takes an Internet network number and a local 127takes an Internet network number and a local
98network address and constructs an Internet address 128network address and constructs an Internet address
99from it. The routines 129from it.
130The routines
100.Fn inet_netof 131.Fn inet_netof
101and 132and
102.Fn inet_lnaof 133.Fn inet_lnaof
@@ -108,11 +139,8 @@ All Internet addresses are returned in network
108order (bytes ordered from left to right). 139order (bytes ordered from left to right).
109All network numbers and local address parts are 140All network numbers and local address parts are
110returned as machine format integer values. 141returned as machine format integer values.
111.Sh INTERNET ADDRESSES 142.Sh INTERNET ADDRESSES (IP VERSION 4)
112Values specified using the 143Values specified using dot notation take one of the following forms:
113.Ql \&.
114notation take one
115of the following forms:
116.Bd -literal -offset indent 144.Bd -literal -offset indent
117a.b.c.d 145a.b.c.d
118a.b.c 146a.b.c
@@ -122,28 +150,25 @@ a
122.Pp 150.Pp
123When four parts are specified, each is interpreted 151When four parts are specified, each is interpreted
124as a byte of data and assigned, from left to right, 152as a byte of data and assigned, from left to right,
125to the four bytes of an Internet address. Note 153to the four bytes of an Internet address.
126that when an Internet address is viewed as a 32-bit 154Note that when an Internet address is viewed as a 32-bit
127integer quantity on the 155integer quantity on a system that uses little-endian
128.Tn VAX 156byte order
129the bytes referred to 157(such as the Intel 386, 486 and Pentium processors)
130above appear as 158the bytes referred to above appear as
131.Dq Li d.c.b.a . 159.Dq Li d.c.b.a .
132That is, 160That is, little-endian bytes are ordered from right to left.
133.Tn VAX
134bytes are
135ordered from right to left.
136.Pp 161.Pp
137When a three part address is specified, the last 162When a three part address is specified, the last
138part is interpreted as a 16-bit quantity and placed 163part is interpreted as a 16-bit quantity and placed
139in the right-most two bytes of the network address. 164in the rightmost two bytes of the network address.
140This makes the three part address format convenient 165This makes the three part address format convenient
141for specifying Class B network addresses as 166for specifying Class B network addresses as
142.Dq Li 128.net.host . 167.Dq Li 128.net.host .
143.Pp 168.Pp
144When a two part address is supplied, the last part 169When a two part address is supplied, the last part
145is interpreted as a 24-bit quantity and placed in 170is interpreted as a 24-bit quantity and placed in
146the right most three bytes of the network address. 171the rightmost three bytes of the network address.
147This makes the two part address format convenient 172This makes the two part address format convenient
148for specifying Class A network addresses as 173for specifying Class A network addresses as
149.Dq Li net.host . 174.Dq Li net.host .
@@ -154,13 +179,88 @@ rearrangement.
154.Pp 179.Pp
155All numbers supplied as 180All numbers supplied as
156.Dq parts 181.Dq parts
157in a 182in a dot notation
158.Ql \&.
159notation
160may be decimal, octal, or hexadecimal, as specified 183may be decimal, octal, or hexadecimal, as specified
161in the C language (i.e., a leading 0x or 0X implies 184in the C language (i.e., a leading 0x or 0X implies
162hexadecimal; otherwise, a leading 0 implies octal; 185hexadecimal; a leading 0 implies octal;
163otherwise, the number is interpreted as decimal). 186otherwise, the number is interpreted as decimal).
187.Sh INTERNET ADDRESSES (IP VERSION 6)
188In order to support scoped IPv6 addresses,
189.Xr getaddrinfo 3
190and
191.Xr getnameinfo 3
192are recommended rather than the functions presented here.
193.Pp
194The presentation format of an IPv6 address is given in RFC 2373:
195.Pp
196There are three conventional forms for representing IPv6 addresses as
197text strings:
198.Bl -enum
199.It
200The preferred form is x:x:x:x:x:x:x:x, where the 'x's are the
201hexadecimal values of the eight 16-bit pieces of the address.
202Examples:
203.Bd -literal -offset indent
204FEDC:BA98:7654:3210:FEDC:BA98:7654:3210
2051080:0:0:0:8:800:200C:417A
206.Ed
207.Pp
208Note that it is not necessary to write the leading zeros in an
209individual field, but there must be at least one numeral in
210every field (except for the case described in 2.).
211.It
212Due to the method of allocating certain styles of IPv6
213addresses, it will be common for addresses to contain long
214strings of zero bits.
215In order to make writing addresses
216containing zero bits easier, a special syntax is available to
217compress the zeros.
218The use of
219.Dq \&:\&:
220indicates multiple groups
221of 16 bits of zeros.
222The
223.Dq \&:\&:
224can only appear once in an
225address.
226The
227.Dq \&:\&:
228can also be used to compress the leading and/or trailing zeros in an address.
229.Pp
230For example the following addresses:
231.Bd -literal -offset indent
2321080:0:0:0:8:800:200C:417A a unicast address
233FF01:0:0:0:0:0:0:43 a multicast address
2340:0:0:0:0:0:0:1 the loopback address
2350:0:0:0:0:0:0:0 the unspecified addresses
236.Ed
237.Pp
238may be represented as:
239.Bd -literal -offset indent
2401080::8:800:200C:417A a unicast address
241FF01::43 a multicast address
242::1 the loopback address
243:: the unspecified addresses
244.Ed
245.It
246An alternative form that is sometimes more convenient when
247dealing with a mixed environment of IPv4 and IPv6 nodes is
248x:x:x:x:x:x:d.d.d.d, where the 'x's are the hexadecimal values
249of the six high-order 16-bit pieces of the address, and the 'd's
250are the decimal values of the four low-order 8-bit pieces of the
251address (standard IPv4 representation).
252Examples:
253.Bd -literal -offset indent
2540:0:0:0:0:0:13.1.68.3
2550:0:0:0:0:FFFF:129.144.52.38
256.Ed
257.Pp
258or in compressed form:
259.Bd -literal -offset indent
260::13.1.68.3
261::FFFF:129.144.52.38
262.Ed
263.El
164.Sh DIAGNOSTICS 264.Sh DIAGNOSTICS
165The constant 265The constant
166.Dv INADDR_NONE 266.Dv INADDR_NONE
@@ -170,28 +270,76 @@ and
170.Fn inet_network 270.Fn inet_network
171for malformed requests. 271for malformed requests.
172.Sh SEE ALSO 272.Sh SEE ALSO
273.Xr byteorder 3 ,
173.Xr gethostbyname 3 , 274.Xr gethostbyname 3 ,
174.Xr getnetent 3 , 275.Xr getnetent 3 ,
276.Xr inet_net 3 ,
175.Xr hosts 5 , 277.Xr hosts 5 ,
176.Xr networks 5 , 278.Xr networks 5
279.Rs
280.%R RFC 2373
281.%D July 1998
282.%T "IP Version 6 Addressing Architecture"
283.Re
284.Rs
285.%R RFC 3493
286.%D February 2003
287.%T "Basic Socket Interface Extensions for IPv6"
288.Re
289.Sh STANDARDS
290The
291.Nm inet_ntop
292and
293.Nm inet_pton
294functions conform to the IETF IPv6 BSD API and address formatting
295specifications.
296Note that
297.Nm inet_pton
298does not accept 1-, 2-, or 3-part dotted addresses; all four parts
299must be specified.
300This is a narrower input set than that accepted by
301.Nm inet_aton .
177.Sh HISTORY 302.Sh HISTORY
178These 303The
179functions appeared in 304.Nm inet_addr ,
305.Nm inet_network ,
306.Nm inet_makeaddr ,
307.Nm inet_lnaof ,
308and
309.Nm inet_netof
310functions appeared in
180.Bx 4.2 . 311.Bx 4.2 .
312The
313.Nm inet_aton
314and
315.Nm inet_ntoa
316functions appeared in
317.Bx 4.3 .
318The
319.Nm inet_pton
320and
321.Nm inet_ntop
322functions appeared in BIND 4.9.4.
181.Sh BUGS 323.Sh BUGS
182The value 324The value
183.Dv INADDR_NONE 325.Dv INADDR_NONE
184(0xffffffff) is a valid broadcast address, but 326(0xffffffff) is a valid broadcast address, but
185.Fn inet_addr 327.Fn inet_addr
186cannot return that value without indicating failure. 328cannot return that value without indicating failure.
329Also,
330.Fn inet_addr
331should have been designed to return a
332.Li struct in_addr .
187The newer 333The newer
188.Fn inet_aton 334.Fn inet_aton
189function does not share this problem. 335function does not share these problems, and almost all existing code
336should be modified to use
337.Fn inet_aton
338instead.
339.Pp
190The problem of host byte ordering versus network byte ordering is 340The problem of host byte ordering versus network byte ordering is
191confusing. 341confusing.
342.Pp
192The string returned by 343The string returned by
193.Fn inet_ntoa 344.Fn inet_ntoa
194resides in a static memory area. 345resides in a static memory area.
195.Pp
196Inet_addr should return a
197.Fa struct in_addr .
diff --git a/src/lib/libc/net/inet6_opt_init.3 b/src/lib/libc/net/inet6_opt_init.3
new file mode 100644
index 0000000000..21880a6382
--- /dev/null
+++ b/src/lib/libc/net/inet6_opt_init.3
@@ -0,0 +1,338 @@
1.\" $OpenBSD: inet6_opt_init.3,v 1.3 2007/05/31 19:19:30 jmc Exp $
2.\" $KAME: inet6_opt_init.3,v 1.7 2004/12/27 05:08:23 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 $Mdocdate: May 31 2007 $
32.Dt INET6_OPT_INIT 3
33.Os
34.\"
35.Sh NAME
36.Nm inet6_opt_init ,
37.Nm inet6_opt_append ,
38.Nm inet6_opt_finish ,
39.Nm inet6_opt_set_val ,
40.Nm inet6_opt_next ,
41.Nm inet6_opt_find ,
42.Nm inet6_opt_get_val
43.Nd IPv6 Hop-by-Hop and Destination Options manipulation
44.\"
45.Sh SYNOPSIS
46.In netinet/in.h
47.Ft "int"
48.Fn inet6_opt_init "void *extbuf" "socklen_t extlen"
49.Ft "int"
50.Fn inet6_opt_append "void *extbuf" "socklen_t extlen" "int offset" "u_int8_t type" "socklen_t len" "u_int8_t align" "void **databufp"
51.Ft "int"
52.Fn inet6_opt_finish "void *extbuf" "socklen_t extlen" "int offset"
53.Ft "int"
54.Fn inet6_opt_set_val "void *databuf" "int offset" "void *val" "socklen_t vallen"
55.Ft "int"
56.Fn inet6_opt_next "void *extbuf" "socklen_t extlen" "int offset" "u_int8_t *typep" "socklen_t *lenp" "void **databufp"
57.Ft "int"
58.Fn inet6_opt_find "void *extbuf" "socklen_t extlen" "int offset" "u_int8_t type" "socklen_t *lenp" "void **databufp"
59.Ft "int"
60.Fn inet6_opt_get_val "void *databuf" "socklen_t offset" "void *val" "socklen_t vallen"
61.\"
62.Sh DESCRIPTION
63Building and parsing the Hop-by-Hop and Destination options is
64complicated.
65The advanced sockets API defines a set of functions to
66help applications create and manipulate Hop-by-Hop and Destination
67options.
68.\"This man page describes the functions specified in
69.\"IETF Draft RFC 3542 while the
70.\".Xr inet6_options_space 3
71.\"man page documents the functions defined in RFC 2292.
72.\"It is expected
73.\"that this set of functions will supersede those in RFC 2292 but for
74.\"the time being both APIs are retained.
75These functions use the
76formatting rules specified in Appendix B in RFC 2460, i.e. that the
77largest field is placed last in the option.
78The function prototypes
79for these functions are all contained in the header file
80.Aq Pa netinet/in.h .
81.\"
82.Ss inet6_opt_init
83The
84.Fn inet6_opt_init
85function
86returns the number of bytes needed for an empty
87extension header, one without any options.
88If the
89.Va extbuf
90argument points to a valid section of memory
91then the
92.Fn inet6_opt_init
93function also initializes the extension header's length field.
94When attempting to initialize an extension buffer passed in the
95.Va extbuf
96argument,
97.Fa extlen
98must be a positive multiple of 8 or else the function fails and
99returns \-1 to the caller.
100.\"
101.Ss inet6_opt_append
102The
103.Fn inet6_opt_append
104function can perform different jobs.
105When a valid
106.Fa extbuf
107argument is supplied it appends an option to the extension buffer and
108returns the updated total length as well as a pointer to the newly
109created option in
110.Fa databufp .
111If the value
112of
113.Fa extbuf
114is
115.Dv NULL
116then the
117.Fn inet6_opt_append
118function only reports what the total length would
119be if the option were actually appended.
120The
121.Fa len
122and
123.Fa align
124arguments specify the length of the option and the required data
125alignment which must be used when appending the option.
126The
127.Fa offset
128argument should be the length returned by the
129.Fn inet6_opt_init
130function or a previous call to
131.Fn inet6_opt_append .
132.Pp
133The
134.Fa type
135argument is the 8-bit option type.
136.Pp
137After
138.Fn inet6_opt_append
139has been called, the application can use the buffer pointed to by
140.Fa databufp
141directly, or use
142.Fn inet6_opt_set_val
143to specify the data to be contained in the option.
144.Pp
145Option types of
146.Li 0
147and
148.Li 1
149are reserved for the
150.Li Pad1
151and
152.Li PadN
153options.
154All other values from 2 through 255 may be used by applications.
155.Pp
156The length of the option data is contained in an 8-bit value and so
157may contain any value from 0 through 255.
158.Pp
159The
160.Fa align
161parameter must have a value of 1, 2, 4, or 8 and cannot exceed the
162value of
163.Fa len .
164The alignment values represent no alignment, 16-bit, 32-bit and 64-bit
165alignments respectively.
166.\"
167.Ss inet6_opt_finish
168The
169.Fn inet6_opt_finish
170calculates the final padding necessary to make the extension header a
171multiple of 8 bytes, as required by the IPv6 extension header
172specification, and returns the extension header's updated total
173length.
174The
175.Fa offset
176argument should be the length returned by
177.Fn inet6_opt_init
178or
179.Fn inet6_opt_append .
180When
181.Fa extbuf
182is not
183.Dv NULL
184the function also sets up the appropriate padding bytes by inserting a
185Pad1 or PadN option of the proper length.
186.Pp
187If the extension header is too small to contain the proper padding
188then an error of \-1 is returned to the caller.
189.\"
190.Ss inet6_opt_set_val
191The
192.Fn inet6_opt_set_val
193function inserts data items of various sizes into the data portion of
194the option.
195The
196.Fa databuf
197argument is a pointer to memory that was returned by the
198.Fn inet6_opt_append
199call and the
200.Fa offset
201argument specifies where the option should be placed in the
202data buffer.
203The
204.Fa val
205argument points to an area of memory containing the data to be
206inserted into the extension header, and the
207.Fa vallen
208argument indicates how much data to copy.
209.Pp
210The caller should ensure that each field is aligned on its natural
211boundaries as described in Appendix B of RFC 2460.
212.Pp
213The function returns the offset for the next field which is calculated as
214.Fa offset
215+
216.Fa vallen
217and is used when composing options with multiple fields.
218.\"
219.Ss inet6_opt_next
220The
221.Fn inet6_opt_next
222function parses received extension headers.
223The
224.Fa extbuf
225and
226.Fa extlen
227arguments specify the location and length of the extension header
228being parsed.
229The
230.Fa offset
231argument should either be zero, for the first option, or the length value
232returned by a previous call to
233.Fn inet6_opt_next
234or
235.Fn inet6_opt_find .
236The return value specifies the position where to continue scanning the
237extension buffer.
238The option is returned in the arguments
239.Fa typep , lenp ,
240and
241.Fa databufp .
242.Fa typep , lenp ,
243and
244.Fa databufp
245point to the 8-bit option type, the 8-bit option length and the option
246data respectively.
247This function does not return any PAD1 or PADN options.
248When an error occurs or there are no more options the return
249value is \-1.
250.\"
251.Ss inet6_opt_find
252The
253.Fn inet6_opt_find
254function searches the extension buffer for a particular option type,
255passed in through the
256.Fa type
257argument.
258If the option is found then the
259.Fa lenp
260and
261.Fa databufp
262arguments are updated to point to the option's length and data
263respectively.
264.Fa extbuf
265and
266.Fa extlen
267must point to a valid extension buffer and give its length.
268The
269.Fa offset
270argument can be used to search from a location anywhere in the
271extension header.
272.Ss inet6_opt_get_val
273The
274.Fn inet6_opt_get_val
275function extracts data items of various sizes in the data portion of
276the option.
277The
278.Fa databuf
279is a pointer returned by the
280.Fn inet6_opt_next
281or
282.Fn inet6_opt_find
283functions.
284The
285.Fa val
286argument points to where the data will be extracted.
287The
288.Fa offset
289argument specifies from where in the data portion of the option the
290value should be extracted; the first byte of option data is specified
291by an offset of zero.
292.Pp
293It is expected that each field is aligned on its natural boundaries as
294described in Appendix B of RFC 2460.
295.Pp
296The function returns the offset for the next field
297by calculating
298.Fa offset
299+
300.Fa vallen
301which can be used when extracting option content with multiple fields.
302Robust receivers must verify alignment before calling this function.
303.\"
304.Sh EXAMPLES
305RFC 3542 gives comprehensive examples in Section 23.
306KAME also provides examples in the
307.Pa advapitest
308directory of its kit.
309.\"
310.Sh DIAGNOSTICS
311All the functions return
312\-1
313on an error.
314.\"
315.Sh SEE ALSO
316.Rs
317.%A W. Stevens
318.%A M. Thomas
319.%A E. Nordmark
320.%A T. Jinmei
321.%T "Advanced Sockets API for IPv6"
322.%N RFC 3542
323.%D October 2002
324.Re
325.Rs
326.%A S. Deering
327.%A R. Hinden
328.%T "Internet Protocol, Version 6 (IPv6) Specification"
329.%N RFC 2460
330.%D December 1998
331.Re
332.Sh STANDARDS
333The functions are documented in
334.Dq Advanced Sockets API for IPv6
335.Pq RFC 3542 .
336.Sh HISTORY
337The implementation first appeared in KAME advanced networking kit.
338.\"
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..8aa79a6d0b
--- /dev/null
+++ b/src/lib/libc/net/inet6_option_space.3
@@ -0,0 +1,444 @@
1.\" $OpenBSD: inet6_option_space.3,v 1.21 2007/05/31 19:19:30 jmc 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 $Mdocdate: May 31 2007 $
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.\"
62Note:
63RFC 2292 has been superseded by RFC 3542.
64The use of functions described in this page is deprecated.
65See
66.Xr inet6_opt_init 3 .
67.Pp
68Manipulating and parsing IPv6's Hop-by-Hop and Destination options is
69complicated by the need to properly align and pad data as well as the
70need to manipulate ancillary information that is not part of the data
71stream.
72RFC 2292 defines a set of functions, which are implemented as
73part of the Kame libraries, to help developers create, change,
74and parse Hop-by-Hop and Destination options.
75All of the prototypes
76for the option functions are defined in the
77.Aq Pa netinet/in.h
78header file.
79.\"
80.Ss inet6_option_space
81In order to determine the amount of space necessary to hold any option
82the
83.Fn inet6_option_space
84function is called.
85It returns the number of bytes required to hold
86an option when it is stored as ancillary data, including the
87.Li cmsghdr
88structure at the beginning, and any necessary padding at the end.
89The
90.Fa nbytes
91argument indicates the size of the structure defining the option,
92and must include any pad bytes at the beginning (the value
93.Li y
94in the alignment term
95.Dq Li "xn + y" ) ,
96the type byte, the length byte, and the option data.
97.Pp
98Note: If multiple options are stored in a single ancillary data
99object, which is the recommended technique, the
100.Fn inet6_option_space
101function overestimates the amount of space required by the size of
102.Li N-1
103.Li cmsghdr
104structures, where
105.Li N
106is the number of options to be stored in the object.
107Usually this has
108no impact because it is assumed that most Hop-by-Hop and Destination
109option headers carry only one option as indicated in appendix B of RFC 2460.
110.\"
111.Ss inet6_option_init
112The
113.Fn inet6_option_init
114function is called to initialize any ancillary data object that will contain
115a Hop-by-Hop or Destination option.
116It returns
117.Li 0
118on success and
119.Li \-1
120when an error occurs.
121.Pp
122The
123.Fa bp
124argument points to a previously allocated area of memory which must be
125large enough to contain all the arguments that the application intends
126to add later via the
127.Fn inet6_option_append
128and
129.Fn inet6_option_alloc
130routines.
131.Pp
132The
133.Fa cmsgp
134argument is a pointer to a pointer to a
135.Li cmsghdr
136structure.
137The
138.Fa *cmsgp
139argument
140points to a
141.Li cmsghdr
142structure which is constructed by this function and stored in the
143area of memory pointed to by
144.Fa bp .
145.Pp
146The
147.Fa type
148is either
149.Dv IPV6_HOPOPTS
150or
151.Dv IPV6_DSTOPTS
152and is stored in the
153.Li cmsg_type
154member of the
155.Li cmsghdr
156structure mentioned above.
157.\"
158.Ss inet6_option_append
159This function appends a Hop-by-Hop option or a Destination option into
160an ancillary data object previously initialized by a call to
161.Fn inet6_option_init .
162The
163.Fn inet6_option_append
164function returns
165.Li 0
166if it succeeds or
167.Li \-1
168when an error occurs.
169.Pp
170The
171.Fa cmsg
172argument is a pointer to the
173.Li cmsghdr
174structure that was initialized by a call to
175.Fn inet6_option_init .
176.Pp
177The
178.Fa typep
179argument is a pointer to the 8-bit option type.
180All options are
181encoded as type-length-value tuples and it is assumed that
182the
183.Fa typep
184field is immediately followed by the 8-bit option data length field,
185which is then followed by the option data.
186.Pp
187The option types of
188.Li 0
189and
190.Li 1
191are reserved for the
192.Li Pad1
193and
194.Li PadN
195options respectively.
196All other values from
197.Li 2
198through
199.Li 255
200are available for applications to use.
201.Pp
202The option data length, since it is stored in 8 bites, must have a
203value between
204.Li 0
205and
206.Li 255 ,
207inclusive.
208.Pp
209The
210.Fa multx
211argument
212is the value
213.Li x
214in the alignment term
215.Dq Li xn + y
216and indicates the byte alignment necessary for the data.
217Alignments may be specified as
218.Li 1 ,
219.Li 2 ,
220.Li 4 ,
221or
222.Li 8
223bytes, which is no alignment, 16-bit, 32-bit and 64-bit alignments
224respectively.
225.Pp
226The
227.Fa plusy
228argument
229is the value
230.Li y
231in the alignment term
232.Dq Li xn + y
233and must have a value between
234.Li 0
235and
236.Li 7 ,
237inclusive, indicating the amount of padding that is necessary for an
238option.
239.\"
240.Ss inet6_option_alloc
241The
242.Fn inet6_option_alloc
243function appends a Hop-by-Hop option or a Destination option into an
244ancillary data object that has previously been initialized by a call to
245.Fn inet6_option_init .
246A successful call to the
247.Fn inet6_option_alloc
248function returns a pointer to the 8-bit option type field,
249which is at the beginning of the allocated region.
250.Fn inet6_option_alloc
251returns
252.Dv NULL
253when an error has occurred.
254.Pp
255The difference between the
256.Fn inet6_option_alloc
257and
258.Fn inet6_option_append
259functions is that the latter copies the contents of a previously built
260option into the ancillary data object while the former returns a
261pointer to the place in the data object where the option's TLV must
262then be built by the application.
263.Pp
264The
265.Fa cmsg
266argument is a pointer to a
267.Li cmsghdr
268structure that was initialized by
269.Fn inet6_option_init .
270.Pp
271The
272.Fa datalen
273argument is the value of the option data length byte for this option.
274This value is required as an argument to allow the function to
275determine if padding must be appended at the end of the option.
276(The
277.Fn inet6_option_append
278function does not need a data length argument
279since the option data length must already be stored by the caller.)
280.Pp
281The
282.Fa multx
283and
284.Fa plusy
285arguments
286are identical to the arguments of the same name described in the
287.Fn inet6_option_init
288function above.
289.\"
290.Ss inet6_option_next
291The
292.Fn inet6_option_next
293function is used to process Hop-by-Hop and Destination options that
294are present in an ancillary data object.
295When an option remains to
296be processed, the return value of the
297.Fn inet6_option_next
298function is
299.Li 0
300and the
301.Fa *tptrp
302argument points to the 8-bit option type field, which is followed by
303the 8-bit option data length, and then the option data.
304When no more
305options remain to be processed, the return value is
306.Li \-1
307and
308.Fa *tptrp
309is
310.Dv NULL .
311When an error occurs, the return value is
312.Li \-1 ,
313but the
314.Fa *tptrp
315argument is not
316.Dv NULL .
317This set of return values allows a program to easily loop through all
318the options in an ancillary data object, checking for the error and
319end of stream conditions along the way.
320.Pp
321When a valid option is returned, the
322.Fa cmsg
323argument points to a
324.Li cmsghdr
325where the
326.Li cmsg_level
327element equals
328.Dv IPPROTO_IPV6
329and the
330.Li cmsg_type
331element is either
332.Dv IPV6_HOPOPTS
333or
334.Dv IPV6_DSTOPTS .
335.Pp
336The
337.Fa tptrp
338argument is a pointer to a pointer to an 8-bit byte and
339.Fa *tptrp
340is used by the function to remember its place in the ancillary data
341object each time the function is called.
342When the
343.Fn inet6_option_next
344function is called for the first time on a given ancillary data object,
345.Fa *tptrp
346must be set to
347.Dv NULL .
348.Pp
349Each time the function returns success,
350the
351.Fa *tptrp
352argument points to the 8-bit option type field for the next option to
353be processed.
354.\"
355.Ss inet6_option_find
356The
357.Fn inet6_option_find
358function allows an application to search for a particular option type
359in an ancillary data object.
360The
361.Fa cmsg
362argument is a pointer to a
363.Li cmsghdr
364structure in which the
365.Li cmsg_level
366element equals
367.Dv IPPROTO_IPV6
368and the
369.Li cmsg_type
370element is either
371.Dv IPV6_HOPOPTS
372or
373.Dv IPV6_DSTOPTS .
374.Pp
375The
376.Fa tptrp
377argument is handled exactly as in the
378.Fn inet6_option_next
379function described above.
380.Pp
381The
382.Fn inet6_option_find
383function starts searching for an option of the specified type
384beginning after the value of
385.Fa *tptrp .
386.\"
387.Sh EXAMPLES
388RFC 2292 gives comprehensive examples in chapter 6.
389.\"
390.Sh DIAGNOSTICS
391The
392.Fn inet6_option_init
393and
394.Fn inet6_option_append
395functions return
396.Li 0
397on success or
398.Li \-1
399on an error.
400.Pp
401The
402.Fn inet6_option_alloc
403function returns
404.Dv NULL
405on an error.
406.Pp
407When
408.Fn inet6_option_next
409or
410.Fn inet6_option_find
411detect an error they return
412.Li \-1 ,
413setting
414.Fa *tptrp
415to a non
416.Dv NULL
417value.
418.\"
419.Sh SEE ALSO
420.Xr inet6 4 ,
421.Xr ip6 4
422.Rs
423.%A W. Stevens
424.%A M. Thomas
425.%T "Advanced Sockets API for IPv6"
426.%N RFC 2292
427.%D February 1998
428.Re
429.Rs
430.%A S. Deering
431.%A R. Hinden
432.%T "Internet Protocol, Version 6 (IPv6) Specification"
433.%N RFC 2460
434.%D December 1998
435.Re
436.\"
437.Sh STANDARDS
438The functions are documented in
439.Dq Advanced Sockets API for IPv6
440(RFC 2292).
441.\"
442.Sh HISTORY
443This implementation first appeared in the KAME advanced networking kit.
444.\"
diff --git a/src/lib/libc/net/inet6_rth_space.3 b/src/lib/libc/net/inet6_rth_space.3
new file mode 100644
index 0000000000..326521def7
--- /dev/null
+++ b/src/lib/libc/net/inet6_rth_space.3
@@ -0,0 +1,219 @@
1.\" $OpenBSD: inet6_rth_space.3,v 1.3 2007/05/31 19:19:30 jmc Exp $
2.\" $KAME: inet6_rth_space.3,v 1.7 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 $Mdocdate: May 31 2007 $
32.Dt INET6_RTH_SPACE 3
33.Os
34.\"
35.Sh NAME
36.Nm inet6_rth_space ,
37.Nm inet6_rth_init ,
38.Nm inet6_rth_add ,
39.Nm inet6_rth_reverse ,
40.Nm inet6_rth_segments ,
41.Nm inet6_rth_getaddr
42.Nd IPv6 Routing Header Options manipulation
43.\"
44.Sh SYNOPSIS
45.In netinet/in.h
46.Ft socklen_t
47.Fn inet6_rth_space "int" "int"
48.Ft "void *"
49.Fn inet6_rth_init "void *" "socklen_t" "int" "int"
50.Ft int
51.Fn inet6_rth_add "void *" "const struct in6_addr *"
52.Ft int
53.Fn inet6_rth_reverse "const void *" "void *"
54.Ft int
55.Fn inet6_rth_segments "const void *"
56.Ft "struct in6_addr *"
57.Fn inet6_rth_getaddr "const void *" "int"
58.\"
59.Sh DESCRIPTION
60The IPv6 Advanced API, RFC 3542, defines the functions that an
61application calls to build and examine IPv6 Routing headers.
62Routing headers are used to perform source routing in IPv6 networks.
63The RFC uses the word
64.Dq segments
65to describe addresses and that is the term used here as well.
66All of the functions are defined in the header file
67.Aq Pa netinet/in.h .
68The functions described in this manual page all operate
69on routing header structures which are defined in
70.Aq Pa netinet/ip6.h
71but which should not need to be modified outside the use of this API.
72The size and shape of the route header structures may change, so using
73the APIs is a more portable, long term, solution.
74.Pp
75The functions in the API are split into two groups, those that build a
76routing header and those that parse a received routing header.
77The builder functions are described first, followed by the parser functions.
78.Ss inet6_rth_space
79The
80.Fn inet6_rth_space
81function returns the number of bytes required to hold a Routing Header
82of the type, specified in the
83.Fa type
84argument and containing the number of addresses specified in the
85.Fa segments
86argument.
87When the type is
88.Dv IPV6_RTHDR_TYPE_0
89the number of segments must be from 0 through 127.
90The return value from this function is the number of bytes required to
91store the routing header.
92If the value 0 is returned then either the
93route header type was not recognized or another error occurred.
94.Ss inet6_rth_init
95The
96.Fn inet6_rth_init
97function initializes the pre-allocated buffer pointed to by
98.Fa bp
99to contain a routing header of the specified type.
100The
101.Fa bp_len
102argument is used to verify that the buffer is large enough.
103The caller must allocate the buffer pointed to by bp.
104The necessary buffer size should be determined by calling
105.Fn inet6_rth_space
106described in the previous sections.
107.Pp
108The
109.Fn inet6_rth_init
110function returns a pointer to
111.Fa bp
112on success and
113.Dv NULL
114when there is an error.
115.Ss inet6_rth_add
116The
117.Fn inet6_rth_add
118function adds the IPv6 address pointed to by
119.Fa addr
120to the end of the routing header being constructed.
121.Pp
122A successful addition results in the function returning 0, otherwise
123\-1 is returned.
124.Ss inet6_rth_reverse
125The
126.Fn inet6_rth_reverse
127function takes a routing header, pointed to by the
128argument
129.Fa in ,
130and writes a new routing header into the argument pointed to by
131.Fa out .
132The routing header at that sends datagrams along the reverse of that
133route.
134Both arguments are allowed to point to the same buffer meaning
135that the reversal can occur in place.
136.Pp
137The return value of the function is 0 on success, or \-1 when
138there is an error.
139.\"
140.Pp
141The next set of functions operate on a routing header that the
142application wants to parse.
143In the usual case such a routing header
144is received from the network, although these functions can also be
145used with routing headers that the application itself created.
146.Ss inet6_rth_segments
147The
148.Fn inet6_rth_segments
149function returns the number of segments contained in the
150routing header pointed to by
151.Fa bp .
152The return value is the number of segments contained in the routing
153header, or \-1 if an error occurred.
154It is not an error for 0 to be
155returned as a routing header may contain 0 segments.
156.\"
157.Ss inet6_rth_getaddr
158The
159.Fn inet6_rth_getaddr
160function is used to retrieve a single address from a routing header.
161The
162.Fa index
163is the location in the routing header from which the application wants
164to retrieve an address.
165The
166.Fa index
167parameter must have a value between 0 and one less than the number of
168segments present in the routing header.
169The
170.Fn inet6_rth_segments
171function, described in the last section, should be used to determine
172the total number of segments in the routing header.
173The
174.Fn inet6_rth_getaddr
175function returns a pointer to an IPv6 address on success or
176.Dv NULL
177when an error has occurred.
178.\"
179.Sh EXAMPLES
180RFC 3542 gives extensive examples in Section 21, Appendix B.
181KAME also provides examples in the advapitest directory of its kit.
182.\"
183.Sh DIAGNOSTICS
184The
185.Fn inet6_rth_space
186and
187.Fn inet6_rth_getaddr
188functions return 0 on errors.
189.Pp
190The
191.Fn inet6_rthdr_init
192function returns
193.Dv NULL
194on error.
195The
196.Fn inet6_rth_add
197and
198.Fn inet6_rth_reverse
199functions return 0 on success, or \-1 upon an error.
200.\"
201.Sh SEE ALSO
202.Rs
203.%A W. Stevens
204.%A M. Thomas
205.%A E. Nordmark
206.%A T. Jinmei
207.%T "Advanced Sockets API for IPv6"
208.%N RFC 3542
209.%D May 2003
210.Re
211.Rs
212.%A S. Deering
213.%A R. Hinden
214.%T "Internet Protocol, Version 6 (IPv6) Specification"
215.%N RFC 2460
216.%D December 1998
217.Re
218.Sh HISTORY
219The implementation first appeared in KAME advanced networking kit.
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..3287bfe009
--- /dev/null
+++ b/src/lib/libc/net/inet6_rthdr_space.3
@@ -0,0 +1,314 @@
1.\" $OpenBSD: inet6_rthdr_space.3,v 1.20 2007/05/31 19:19:30 jmc 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 $Mdocdate: May 31 2007 $
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
73Note:
74RFC 2292 has been superseded by RFC 3542.
75The use of functions described in this page is deprecated.
76See
77.Xr inet6_rth_space 3 .
78.Pp
79The RFC 2292 IPv6 Advanced API defined eight functions for
80applications to use for building and parsing routing headers.
81The
82eight functions are split into two groups, the first of which builds
83the header and the second of which can parse it.
84The function prototypes for these functions are all in the
85.Aq Pa netinet/in.h
86header.
87Although direct manipulation of a routing header is possible,
88this set of APIs make it unnecessary and such direct manipulation
89should be avoided so that changes to the underlying structures do not
90break applications.
91.Pp
92Please note that RFC 2292 uses the term
93.Dq segments
94instead of the term
95.Dq addresses
96but they are considered equivalent for this manual page.
97.\"
98.Ss inet6_rthdr_space
99The
100.Fn inet6_rthdr_space
101function returns the number of bytes required to hold a routing header
102of the specified
103.Fa type
104and containing the specified number of
105.Fa segments .
106Only one
107.Fa type
108is supported,
109.Dv IPV6_RTHDR_TYPE_0 ,
110and it can hold from 1 to 23 segments.
111The return value includes the
112size of the
113.Vt cmsghdr
114structure that precedes the routing header and
115any required padding.
116.Pp
117A return value of 0 indicates an error.
118Either the type was specified
119incorrectly, or the number of segments was less than one or greater
120than 23.
121.Pp
122Note: The
123.Fn inet6_rthdr_space
124function only returns the size required by the routing header and does
125not allocate memory for the caller.
126.\"
127.Ss inet6_rthdr_init
128The
129.Fn inet6_rthdr_init
130function initializes a buffer, pointed to by
131.Fa bp
132with an appropriate
133.Li cmsghdr
134structure followed by a routing header of the specified
135.Fa type .
136.Pp
137The caller must use the
138.Fn inet6_rthdr_space
139function to determine the size of the buffer, and then allocate that
140buffer before calling
141.Fn inet6_rthdr_init .
142.Pp
143The return value is a pointer to a
144.Li cmsghdr
145structure, which is used as the first argument to the
146.Fn inet6_rthdr_add
147and
148.Fn inet6_rthdr_lasthop
149functions in order to construct the routing header.
150When an error occurs the return value is
151.Dv NULL .
152.\"
153.Ss inet6_rthdr_add
154The
155.Fn inet6_rthdr_add
156function adds the IPv6 address pointed to by
157.Fa addr
158to the end of the
159routing header being constructed and sets the type of this address to the
160value of
161.Fa flags .
162The
163.Fa flags
164must be either
165.Dv IPV6_RTHDR_LOOSE
166or
167.Dv IPV6_RTHDR_STRICT
168indicating whether loose or strict source routing is required.
169.Pp
170When the function succeeds it returns 0, otherwise \-1 is returned.
171.\"
172.Ss inet6_rthdr_lasthop
173The
174.Fn inet6_rthdr_lasthop
175function specifies the strict or loose flag for the final hop of a
176routing header.
177The
178.Fa flags
179argument must be either
180.Dv IPV6_RTHDR_LOOSE
181or
182.Dv IPV6_RTHDR_STRICT .
183.Pp
184The return value of the function is 0 upon success, and \-1 when an
185error has occurred.
186.Pp
187Please note that a routing header specifying
188.Li N
189intermediate nodes requires
190.Li N+1
191strict or loose flags meaning that
192.Fn inet6_rthdr_add
193must be called
194.Li N
195times and then
196.Fn inet6_rthdr_lasthop
197must be called once.
198.\"
199.Ss inet6_rthdr_reverse
200This function was never implemented.
201.Pp
202The following three functions provide an API for parsing a received
203routing header:
204.\"
205.Ss inet6_rthdr_segments
206The
207.Fn inet6_rthdr_segments
208function returns the number of segments contained in the routing
209header pointed to by the
210.Fa cmsg
211argument.
212On success the return value is from 1 to 23.
213When an error occurs, \-1 is returned.
214.\"
215.Ss inet6_rthdr_getaddr
216The
217.Fn inet6_rthdr_getaddr
218function returns a pointer to the IPv6 address specified by the
219.Fa index
220argument from the routing header pointed to by
221.Fa cmsg .
222The index must be between 1 and the number returned by
223.Fn inet6_rthdr_segments ,
224described above.
225An application must call
226.Fn inet6_rthdr_segments
227to obtain the number of segments in the routing header.
228.Pp
229If an error occurs,
230.Dv NULL
231is returned.
232.\"
233.Ss inet6_rthdr_getflags
234The
235.Fn inet6_rthdr_getflags
236function returns the flags value of the segment specified by
237.Fa index
238of the routing header pointed to by
239.Fa cmsg .
240The
241.Fa index
242argument must be between 0 and the value returned by
243.Fn inet6_rthdr_segments .
244The return value will be either
245.Dv IPV6_RTHDR_LOOSE
246or
247.Dv IPV6_RTHDR_STRICT
248indicating whether loose or strict source routing was requested for
249that segment.
250.Pp
251When an error occurs, \-1 is returned.
252.Pp
253Note: Flags begin at index 0 while segments begin at index 1, to
254maintain consistency with the terminology and figures in RFC 2460.
255.\"
256.Sh EXAMPLES
257RFC 2292 gives comprehensive examples in chapter 8.
258.\"
259.Sh DIAGNOSTICS
260The
261.Fn inet6_rthdr_space
262function returns 0 when an error occurs.
263.Pp
264The
265.Fn inet6_rthdr_add
266and
267.Fn inet6_rthdr_lasthop
268functions return 0 on success, and \-1 on error.
269.Pp
270The
271.Fn inet6_rthdr_init
272and
273.Fn inet6_rthdr_getaddr
274functions
275return
276.Dv NULL
277on error.
278.Pp
279The
280.Fn inet6_rthdr_segments
281and
282.Fn inet6_rthdr_getflags
283functions return \-1 on error.
284.\"
285.Sh SEE ALSO
286.Xr inet6 4 ,
287.Xr ip6 4
288.Rs
289.%A W. Stevens
290.%A M. Thomas
291.%T "Advanced Sockets API for IPv6"
292.%N RFC 2292
293.%D February 1998
294.Re
295.Rs
296.%A S. Deering
297.%A R. Hinden
298.%T "Internet Protocol, Version 6 (IPv6) Specification"
299.%N RFC 2460
300.%D December 1998
301.Re
302.\"
303.Sh HISTORY
304This implementation first appeared in the KAME advanced networking kit.
305.\"
306.Sh BUGS
307The
308.Fn inet6_rthdr_reverse
309function was never implemented.
310.\".Pp
311.\"This API is deprecated in favor of
312.\".Xr inet6_rth_space 3
313.\".Sh SEE ALSO
314.\".Xr inet6_rth_space 3
diff --git a/src/lib/libc/net/inet_addr.c b/src/lib/libc/net/inet_addr.c
index b5b9d8302f..c962a03382 100644
--- a/src/lib/libc/net/inet_addr.c
+++ b/src/lib/libc/net/inet_addr.c
@@ -1,9 +1,11 @@
1/* $NetBSD: inet_addr.c,v 1.5 1995/02/25 06:20:41 cgd Exp $ */ 1/* $OpenBSD: inet_addr.c,v 1.9 2005/08/06 20:30:03 espie Exp $ */
2 2
3/* 3/*
4 * ++Copyright++ 1983, 1990, 1993
5 * -
4 * Copyright (c) 1983, 1990, 1993 6 * Copyright (c) 1983, 1990, 1993
5 * The Regents of the University of California. All rights reserved. 7 * The Regents of the University of California. All rights reserved.
6 * 8 *
7 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
9 * are met: 11 * are met:
@@ -12,14 +14,10 @@
12 * 2. Redistributions in binary form must reproduce the above copyright 14 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 15 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 16 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software 17 * 3. Neither the name of the University nor the names of its contributors
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software 18 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission. 19 * without specific prior written permission.
22 * 20 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -31,16 +29,29 @@
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE. 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--
34 */ 52 */
35 53
36#if defined(LIBC_SCCS) && !defined(lint) 54#include <sys/types.h>
37#if 0
38static char sccsid[] = "@(#)inet_addr.c 8.1 (Berkeley) 6/17/93";
39#else
40static char rcsid[] = "$NetBSD: inet_addr.c,v 1.5 1995/02/25 06:20:41 cgd Exp $";
41#endif
42#endif /* LIBC_SCCS and not lint */
43
44#include <sys/param.h> 55#include <sys/param.h>
45#include <netinet/in.h> 56#include <netinet/in.h>
46#include <arpa/inet.h> 57#include <arpa/inet.h>
@@ -50,9 +61,8 @@ static char rcsid[] = "$NetBSD: inet_addr.c,v 1.5 1995/02/25 06:20:41 cgd Exp $"
50 * Ascii internet address interpretation routine. 61 * Ascii internet address interpretation routine.
51 * The value returned is in network order. 62 * The value returned is in network order.
52 */ 63 */
53u_long 64in_addr_t
54inet_addr(cp) 65inet_addr(const char *cp)
55 register const char *cp;
56{ 66{
57 struct in_addr val; 67 struct in_addr val;
58 68
@@ -69,60 +79,60 @@ inet_addr(cp)
69 * cannot distinguish between failure and a local broadcast address. 79 * cannot distinguish between failure and a local broadcast address.
70 */ 80 */
71int 81int
72inet_aton(cp, addr) 82inet_aton(const char *cp, struct in_addr *addr)
73 register const char *cp;
74 struct in_addr *addr;
75{ 83{
76 register u_long val; 84 in_addr_t val;
77 register int base, n; 85 int base, n;
78 register char c; 86 char c;
79 u_int parts[4]; 87 u_int parts[4];
80 register u_int *pp = parts; 88 u_int *pp = parts;
81 89
90 c = *cp;
82 for (;;) { 91 for (;;) {
83 /* 92 /*
84 * Collect number up to ``.''. 93 * Collect number up to ``.''.
85 * Values are specified as for C: 94 * Values are specified as for C:
86 * 0x=hex, 0=octal, other=decimal. 95 * 0x=hex, 0=octal, isdigit=decimal.
87 */ 96 */
97 if (!isdigit(c))
98 return (0);
88 val = 0; base = 10; 99 val = 0; base = 10;
89 if (*cp == '0') { 100 if (c == '0') {
90 if (*++cp == 'x' || *cp == 'X') 101 c = *++cp;
91 base = 16, cp++; 102 if (c == 'x' || c == 'X')
103 base = 16, c = *++cp;
92 else 104 else
93 base = 8; 105 base = 8;
94 } 106 }
95 while ((c = *cp) != '\0') { 107 for (;;) {
96 if (isascii(c) && isdigit(c)) { 108 if (isascii(c) && isdigit(c)) {
97 val = (val * base) + (c - '0'); 109 val = (val * base) + (c - '0');
98 cp++; 110 c = *++cp;
99 continue; 111 } else if (base == 16 && isascii(c) && isxdigit(c)) {
100 } 112 val = (val << 4) |
101 if (base == 16 && isascii(c) && isxdigit(c)) {
102 val = (val << 4) +
103 (c + 10 - (islower(c) ? 'a' : 'A')); 113 (c + 10 - (islower(c) ? 'a' : 'A'));
104 cp++; 114 c = *++cp;
105 continue; 115 } else
106 } 116 break;
107 break;
108 } 117 }
109 if (*cp == '.') { 118 if (c == '.') {
110 /* 119 /*
111 * Internet format: 120 * Internet format:
112 * a.b.c.d 121 * a.b.c.d
113 * a.b.c (with c treated as 16-bits) 122 * a.b.c (with c treated as 16 bits)
114 * a.b (with b treated as 24 bits) 123 * a.b (with b treated as 24 bits)
115 */ 124 */
116 if (pp >= parts + 3 || val > 0xff) 125 if (pp >= parts + 3)
117 return (0); 126 return (0);
118 *pp++ = val, cp++; 127 *pp++ = val;
128 c = *++cp;
119 } else 129 } else
120 break; 130 break;
121 } 131 }
122 /* 132 /*
123 * Check for trailing characters. 133 * Check for trailing characters.
124 */ 134 */
125 if (*cp && (!isascii(*cp) || !isspace(*cp))) 135 if (c != '\0' && (!isascii(c) || !isspace(c)))
126 return (0); 136 return (0);
127 /* 137 /*
128 * Concoct the address according to 138 * Concoct the address according to
@@ -131,23 +141,26 @@ inet_aton(cp, addr)
131 n = pp - parts + 1; 141 n = pp - parts + 1;
132 switch (n) { 142 switch (n) {
133 143
144 case 0:
145 return (0); /* initial nondigit */
146
134 case 1: /* a -- 32 bits */ 147 case 1: /* a -- 32 bits */
135 break; 148 break;
136 149
137 case 2: /* a.b -- 8.24 bits */ 150 case 2: /* a.b -- 8.24 bits */
138 if (val > 0xffffff) 151 if ((val > 0xffffff) || (parts[0] > 0xff))
139 return (0); 152 return (0);
140 val |= parts[0] << 24; 153 val |= parts[0] << 24;
141 break; 154 break;
142 155
143 case 3: /* a.b.c -- 8.8.16 bits */ 156 case 3: /* a.b.c -- 8.8.16 bits */
144 if (val > 0xffff) 157 if ((val > 0xffff) || (parts[0] > 0xff) || (parts[1] > 0xff))
145 return (0); 158 return (0);
146 val |= (parts[0] << 24) | (parts[1] << 16); 159 val |= (parts[0] << 24) | (parts[1] << 16);
147 break; 160 break;
148 161
149 case 4: /* a.b.c.d -- 8.8.8.8 bits */ 162 case 4: /* a.b.c.d -- 8.8.8.8 bits */
150 if (val > 0xff) 163 if ((val > 0xff) || (parts[0] > 0xff) || (parts[1] > 0xff) || (parts[2] > 0xff))
151 return (0); 164 return (0);
152 val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); 165 val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
153 break; 166 break;
diff --git a/src/lib/libc/net/inet_lnaof.c b/src/lib/libc/net/inet_lnaof.c
index ce1257bf68..b1a58cd2c1 100644
--- a/src/lib/libc/net/inet_lnaof.c
+++ b/src/lib/libc/net/inet_lnaof.c
@@ -1,5 +1,4 @@
1/* $NetBSD: inet_lnaof.c,v 1.4 1995/02/25 06:20:42 cgd Exp $ */ 1/* $OpenBSD: inet_lnaof.c,v 1.6 2005/08/06 20:30:03 espie Exp $ */
2
3/* 2/*
4 * Copyright (c) 1983, 1993 3 * Copyright (c) 1983, 1993
5 * The Regents of the University of California. All rights reserved. 4 * The Regents of the University of California. All rights reserved.
@@ -12,11 +11,7 @@
12 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software 14 * 3. Neither the name of the University nor the names of its contributors
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software 15 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission. 16 * without specific prior written permission.
22 * 17 *
@@ -33,14 +28,6 @@
33 * SUCH DAMAGE. 28 * SUCH DAMAGE.
34 */ 29 */
35 30
36#if defined(LIBC_SCCS) && !defined(lint)
37#if 0
38static char sccsid[] = "@(#)inet_lnaof.c 8.1 (Berkeley) 6/4/93";
39#else
40static char rcsid[] = "$NetBSD: inet_lnaof.c,v 1.4 1995/02/25 06:20:42 cgd Exp $";
41#endif
42#endif /* LIBC_SCCS and not lint */
43
44#include <sys/param.h> 31#include <sys/param.h>
45#include <netinet/in.h> 32#include <netinet/in.h>
46#include <arpa/inet.h> 33#include <arpa/inet.h>
@@ -50,11 +37,10 @@ static char rcsid[] = "$NetBSD: inet_lnaof.c,v 1.4 1995/02/25 06:20:42 cgd Exp $
50 * internet address; handles class a/b/c network 37 * internet address; handles class a/b/c network
51 * number formats. 38 * number formats.
52 */ 39 */
53u_long 40in_addr_t
54inet_lnaof(in) 41inet_lnaof(struct in_addr in)
55 struct in_addr in;
56{ 42{
57 register u_long i = ntohl(in.s_addr); 43 in_addr_t i = ntohl(in.s_addr);
58 44
59 if (IN_CLASSA(i)) 45 if (IN_CLASSA(i))
60 return ((i)&IN_CLASSA_HOST); 46 return ((i)&IN_CLASSA_HOST);
diff --git a/src/lib/libc/net/inet_makeaddr.c b/src/lib/libc/net/inet_makeaddr.c
index 84d366e03a..87d9325231 100644
--- a/src/lib/libc/net/inet_makeaddr.c
+++ b/src/lib/libc/net/inet_makeaddr.c
@@ -1,5 +1,4 @@
1/* $NetBSD: inet_makeaddr.c,v 1.4 1995/02/25 06:20:42 cgd Exp $ */ 1/* $OpenBSD: inet_makeaddr.c,v 1.6 2005/08/06 20:30:03 espie Exp $ */
2
3/* 2/*
4 * Copyright (c) 1983, 1993 3 * Copyright (c) 1983, 1993
5 * The Regents of the University of California. All rights reserved. 4 * The Regents of the University of California. All rights reserved.
@@ -12,11 +11,7 @@
12 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software 14 * 3. Neither the name of the University nor the names of its contributors
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software 15 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission. 16 * without specific prior written permission.
22 * 17 *
@@ -33,14 +28,6 @@
33 * SUCH DAMAGE. 28 * SUCH DAMAGE.
34 */ 29 */
35 30
36#if defined(LIBC_SCCS) && !defined(lint)
37#if 0
38static char sccsid[] = "@(#)inet_makeaddr.c 8.1 (Berkeley) 6/4/93";
39#else
40static char rcsid[] = "$NetBSD: inet_makeaddr.c,v 1.4 1995/02/25 06:20:42 cgd Exp $";
41#endif
42#endif /* LIBC_SCCS and not lint */
43
44#include <sys/param.h> 31#include <sys/param.h>
45#include <netinet/in.h> 32#include <netinet/in.h>
46#include <arpa/inet.h> 33#include <arpa/inet.h>
@@ -50,10 +37,9 @@ static char rcsid[] = "$NetBSD: inet_makeaddr.c,v 1.4 1995/02/25 06:20:42 cgd Ex
50 * building addresses stored in the ifnet structure. 37 * building addresses stored in the ifnet structure.
51 */ 38 */
52struct in_addr 39struct in_addr
53inet_makeaddr(net, host) 40inet_makeaddr(in_addr_t net, in_addr_t host)
54 u_long net, host;
55{ 41{
56 u_long addr; 42 in_addr_t addr;
57 43
58 if (net < 128) 44 if (net < 128)
59 addr = (net << IN_CLASSA_NSHIFT) | (host & IN_CLASSA_HOST); 45 addr = (net << IN_CLASSA_NSHIFT) | (host & IN_CLASSA_HOST);
diff --git a/src/lib/libc/net/inet_net.3 b/src/lib/libc/net/inet_net.3
new file mode 100644
index 0000000000..648d82c780
--- /dev/null
+++ b/src/lib/libc/net/inet_net.3
@@ -0,0 +1,176 @@
1.\" $OpenBSD: inet_net.3,v 1.14 2008/06/26 05:42:05 ray 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.\"
19.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
23.\" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29.\" POSSIBILITY OF SUCH DAMAGE.
30.\"
31.Dd $Mdocdate: June 26 2008 $
32.Dt INET_NET 3
33.Os
34.Sh NAME
35.Nm inet_net_ntop ,
36.Nm inet_net_pton
37.Nd Internet network number manipulation routines
38.Sh SYNOPSIS
39.Fd #include <sys/types.h>
40.Fd #include <sys/socket.h>
41.Fd #include <netinet/in.h>
42.Fd #include <arpa/inet.h>
43.Ft char *
44.Fn inet_net_ntop "int af" "const void *src" "int bits" "char *dst" "size_t size"
45.Ft int
46.Fn inet_net_pton "int af" "const char *src" "void *dst" "size_t size"
47.Sh DESCRIPTION
48The
49.Fn inet_net_ntop
50function converts an Internet network number from network format (usually a
51.Li struct in_addr
52or some other binary form, in network byte order) to CIDR presentation format
53(suitable for external display purposes).
54.Fa bits
55is the number of bits in
56.Fa src
57that are the network number.
58It returns
59.Dv NULL
60if a system error occurs (in which case,
61.Va errno
62will have been set), or it returns a pointer to the destination string.
63.Pp
64The
65.Fn inet_net_pton
66function converts a presentation format Internet network number (that is,
67printable form as held in a character string) to network format (usually a
68.Li struct in_addr
69or some other internal binary representation, in network byte order).
70It returns the number of bits (either computed based on the class, or
71specified with /CIDR), or \-1 if a failure occurred
72(in which case
73.Va errno
74will have been set.
75It will be set to
76.Er ENOENT
77if the Internet network number was not valid).
78.Pp
79Caution:
80The
81.Fa dst
82field should be zeroed before calling
83.Fn inet_net_pton
84as the function will only fill the number of bytes necessary to
85encode the network number in network byte order.
86.Pp
87The only value for
88.Fa af
89currently supported is
90.Dv AF_INET .
91.Fa size
92is the size of the result buffer
93.Fa dst .
94.Sh NETWORK NUMBERS (IP VERSION 4)
95The external representation of Internet network numbers may be specified in
96one of the following forms:
97.Bd -literal -offset indent
98a
99a.b
100a.b.c
101a.b.c.d
102.Ed
103.Pp
104Any of the above four forms may have
105.Dq Li /bits
106appended where
107.Dq Li bits
108is in the range
109.Li 0-32
110and is used to explicitly specify the number of bits in the network address.
111When
112.Dq Li /bits
113is not specified the number of bits in the network address is calculated
114as the larger of the number of bits in the class to which the address
115belongs and the number of bits provided rounded up modulo 8.
116Examples:
117.Pp
118.Bl -tag -width 10.1.2.3/24 -offset indent -compact
119.It Li 10
120an 8-bit network number (class A), value
121.Li 10.0.0.0 .
122.It Li 192
123a 24-bit network number (class C), value
124.Li 192.0.0.0 .
125.It Li 10.10
126a 16-bit network number, value
127.Li 10.10.0.0 .
128.It Li 10.1.2
129a 24-bit network number, value
130.Li 10.1.2.0 .
131.It Li 10.1.2.3
132a 32-bit network number, value
133.Li 10.1.2.3 .
134.It Li 10.1.2.3/24
135a 24-bit network number (explicit), value
136.Li 10.1.2.3 .
137.El
138.Pp
139Note that when the number of bits is specified using
140.Dq Li /bits
141notation, the value of the address still includes all bits supplied
142in the external representation, even those bits which are the host
143part of an Internet address.
144Also, unlike
145.Xr inet_pton 3
146where the external representation is assumed to be a host address, the
147external representation for
148.Fn inet_net_pton
149is assumed to be a network address.
150Thus
151.Dq Li 10.1
152is assumed to be
153.Dq Li 10.1.0.0
154not
155.Dq Li 10.0.0.1
156.Pp
157All numbers supplied as
158.Dq parts
159in a
160.Ql \&.
161notation
162may be decimal, octal, or hexadecimal, as specified
163in the C language (i.e., a leading 0x or 0X implies
164hexadecimal; otherwise, a leading 0 implies octal;
165otherwise, the number is interpreted as decimal).
166.Sh SEE ALSO
167.Xr byteorder 3 ,
168.Xr inet 3 ,
169.Xr inet_pton 3 ,
170.Xr networks 5
171.Sh HISTORY
172The
173.Nm inet_net_ntop
174and
175.Nm inet_net_pton
176functions 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..3105c33b43
--- /dev/null
+++ b/src/lib/libc/net/inet_net_pton.c
@@ -0,0 +1,191 @@
1/* $OpenBSD: inet_net_pton.c,v 1.6 2008/09/01 09:40:43 markus 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 if (bits > 32)
146 goto emsgsize;
147 } while ((ch = *src++) != '\0' &&
148 isascii(ch) && isdigit(ch));
149 if (ch != '\0')
150 goto enoent;
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
index 02f52ca318..2f468c3aca 100644
--- a/src/lib/libc/net/inet_netof.c
+++ b/src/lib/libc/net/inet_netof.c
@@ -1,5 +1,4 @@
1/* $NetBSD: inet_netof.c,v 1.4 1995/02/25 06:20:43 cgd Exp $ */ 1/* $OpenBSD: inet_netof.c,v 1.6 2005/08/06 20:30:03 espie Exp $ */
2
3/* 2/*
4 * Copyright (c) 1983, 1993 3 * Copyright (c) 1983, 1993
5 * The Regents of the University of California. All rights reserved. 4 * The Regents of the University of California. All rights reserved.
@@ -12,11 +11,7 @@
12 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software 14 * 3. Neither the name of the University nor the names of its contributors
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software 15 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission. 16 * without specific prior written permission.
22 * 17 *
@@ -33,14 +28,6 @@
33 * SUCH DAMAGE. 28 * SUCH DAMAGE.
34 */ 29 */
35 30
36#if defined(LIBC_SCCS) && !defined(lint)
37#if 0
38static char sccsid[] = "@(#)inet_netof.c 8.1 (Berkeley) 6/4/93";
39#else
40static char rcsid[] = "$NetBSD: inet_netof.c,v 1.4 1995/02/25 06:20:43 cgd Exp $";
41#endif
42#endif /* LIBC_SCCS and not lint */
43
44#include <sys/param.h> 31#include <sys/param.h>
45#include <netinet/in.h> 32#include <netinet/in.h>
46#include <arpa/inet.h> 33#include <arpa/inet.h>
@@ -49,11 +36,10 @@ static char rcsid[] = "$NetBSD: inet_netof.c,v 1.4 1995/02/25 06:20:43 cgd Exp $
49 * Return the network number from an internet 36 * Return the network number from an internet
50 * address; handles class a/b/c network #'s. 37 * address; handles class a/b/c network #'s.
51 */ 38 */
52u_long 39in_addr_t
53inet_netof(in) 40inet_netof(struct in_addr in)
54 struct in_addr in;
55{ 41{
56 register u_long i = ntohl(in.s_addr); 42 in_addr_t i = ntohl(in.s_addr);
57 43
58 if (IN_CLASSA(i)) 44 if (IN_CLASSA(i))
59 return (((i)&IN_CLASSA_NET) >> IN_CLASSA_NSHIFT); 45 return (((i)&IN_CLASSA_NET) >> IN_CLASSA_NSHIFT);
diff --git a/src/lib/libc/net/inet_network.c b/src/lib/libc/net/inet_network.c
index 35105fa75a..8b26ba8ff9 100644
--- a/src/lib/libc/net/inet_network.c
+++ b/src/lib/libc/net/inet_network.c
@@ -1,5 +1,4 @@
1/* $NetBSD: inet_network.c,v 1.4 1995/02/25 06:20:45 cgd Exp $ */ 1/* $OpenBSD: inet_network.c,v 1.10 2005/08/06 20:30:03 espie Exp $ */
2
3/* 2/*
4 * Copyright (c) 1983, 1993 3 * Copyright (c) 1983, 1993
5 * The Regents of the University of California. All rights reserved. 4 * The Regents of the University of California. All rights reserved.
@@ -12,11 +11,7 @@
12 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software 14 * 3. Neither the name of the University nor the names of its contributors
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software 15 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission. 16 * without specific prior written permission.
22 * 17 *
@@ -33,14 +28,6 @@
33 * SUCH DAMAGE. 28 * SUCH DAMAGE.
34 */ 29 */
35 30
36#if defined(LIBC_SCCS) && !defined(lint)
37#if 0
38static char sccsid[] = "@(#)inet_network.c 8.1 (Berkeley) 6/4/93";
39#else
40static char rcsid[] = "$NetBSD: inet_network.c,v 1.4 1995/02/25 06:20:45 cgd Exp $";
41#endif
42#endif /* LIBC_SCCS and not lint */
43
44#include <sys/types.h> 31#include <sys/types.h>
45#include <netinet/in.h> 32#include <netinet/in.h>
46#include <arpa/inet.h> 33#include <arpa/inet.h>
@@ -51,14 +38,13 @@ static char rcsid[] = "$NetBSD: inet_network.c,v 1.4 1995/02/25 06:20:45 cgd Exp
51 * The library routines call this routine to interpret 38 * The library routines call this routine to interpret
52 * network numbers. 39 * network numbers.
53 */ 40 */
54u_long 41in_addr_t
55inet_network(cp) 42inet_network(const char *cp)
56 register const char *cp;
57{ 43{
58 register u_long val, base, n; 44 in_addr_t val, base, n;
59 register char c; 45 char c;
60 u_long parts[4], *pp = parts; 46 in_addr_t parts[4], *pp = parts;
61 register int i; 47 int i;
62 48
63again: 49again:
64 val = 0; base = 10; 50 val = 0; base = 10;
@@ -66,7 +52,7 @@ again:
66 base = 8, cp++; 52 base = 8, cp++;
67 if (*cp == 'x' || *cp == 'X') 53 if (*cp == 'x' || *cp == 'X')
68 base = 16, cp++; 54 base = 16, cp++;
69 while (c = *cp) { 55 while ((c = *cp)) {
70 if (isdigit(c)) { 56 if (isdigit(c)) {
71 val = (val * base) + (c - '0'); 57 val = (val * base) + (c - '0');
72 cp++; 58 cp++;
@@ -80,7 +66,7 @@ again:
80 break; 66 break;
81 } 67 }
82 if (*cp == '.') { 68 if (*cp == '.') {
83 if (pp >= parts + 4) 69 if (pp >= parts + 3)
84 return (INADDR_NONE); 70 return (INADDR_NONE);
85 *pp++ = val, cp++; 71 *pp++ = val, cp++;
86 goto again; 72 goto again;
@@ -89,11 +75,10 @@ again:
89 return (INADDR_NONE); 75 return (INADDR_NONE);
90 *pp++ = val; 76 *pp++ = val;
91 n = pp - parts; 77 n = pp - parts;
92 if (n > 4) 78 for (val = 0, i = 0; i < 4; i++) {
93 return (INADDR_NONE);
94 for (val = 0, i = 0; i < n; i++) {
95 val <<= 8; 79 val <<= 8;
96 val |= parts[i] & 0xff; 80 if (i < n)
81 val |= parts[i] & 0xff;
97 } 82 }
98 return (val); 83 return (val);
99} 84}
diff --git a/src/lib/libc/net/inet_ntoa.c b/src/lib/libc/net/inet_ntoa.c
index 2da0ab00ff..ff5d93ded2 100644
--- a/src/lib/libc/net/inet_ntoa.c
+++ b/src/lib/libc/net/inet_ntoa.c
@@ -1,5 +1,4 @@
1/* $NetBSD: inet_ntoa.c,v 1.4 1995/02/25 06:20:46 cgd Exp $ */ 1/* $OpenBSD: inet_ntoa.c,v 1.6 2005/08/06 20:30:03 espie Exp $ */
2
3/* 2/*
4 * Copyright (c) 1983, 1993 3 * Copyright (c) 1983, 1993
5 * The Regents of the University of California. All rights reserved. 4 * The Regents of the University of California. All rights reserved.
@@ -12,11 +11,7 @@
12 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software 14 * 3. Neither the name of the University nor the names of its contributors
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software 15 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission. 16 * without specific prior written permission.
22 * 17 *
@@ -33,14 +28,6 @@
33 * SUCH DAMAGE. 28 * SUCH DAMAGE.
34 */ 29 */
35 30
36#if defined(LIBC_SCCS) && !defined(lint)
37#if 0
38static char sccsid[] = "@(#)inet_ntoa.c 8.1 (Berkeley) 6/4/93";
39#else
40static char rcsid[] = "$NetBSD: inet_ntoa.c,v 1.4 1995/02/25 06:20:46 cgd Exp $";
41#endif
42#endif /* LIBC_SCCS and not lint */
43
44/* 31/*
45 * Convert network-format internet address 32 * Convert network-format internet address
46 * to base 256 d.d.d.d representation. 33 * to base 256 d.d.d.d representation.
@@ -51,15 +38,14 @@ static char rcsid[] = "$NetBSD: inet_ntoa.c,v 1.4 1995/02/25 06:20:46 cgd Exp $"
51#include <stdio.h> 38#include <stdio.h>
52 39
53char * 40char *
54inet_ntoa(in) 41inet_ntoa(struct in_addr in)
55 struct in_addr in;
56{ 42{
57 static char b[18]; 43 static char b[18];
58 register char *p; 44 char *p;
59 45
60 p = (char *)&in; 46 p = (char *)&in;
61#define UC(b) (((int)b)&0xff) 47#define UC(b) (((int)b)&0xff)
62 (void)snprintf(b, sizeof(b), 48 (void)snprintf(b, sizeof(b),
63 "%d.%d.%d.%d", UC(p[0]), UC(p[1]), UC(p[2]), UC(p[3])); 49 "%u.%u.%u.%u", UC(p[0]), UC(p[1]), UC(p[2]), UC(p[3]));
64 return (b); 50 return (b);
65} 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..9deb352e24
--- /dev/null
+++ b/src/lib/libc/net/inet_ntop.c
@@ -0,0 +1,195 @@
1/* $OpenBSD: inet_ntop.c,v 1.8 2008/12/09 19:38:38 otto 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, socklen_t size)
47{
48 switch (af) {
49 case AF_INET:
50 return (inet_ntop4(src, dst, (size_t)size));
51 case AF_INET6:
52 return (inet_ntop6(src, dst, (size_t)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..7e521c3286
--- /dev/null
+++ b/src/lib/libc/net/inet_pton.c
@@ -0,0 +1,213 @@
1/* $OpenBSD: inet_pton.c,v 1.8 2010/05/06 15:47:14 claudio 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 * does not touch `dst' unless it's returning 1.
118 * credit:
119 * inspired by Mark Andrews.
120 * author:
121 * Paul Vixie, 1996.
122 */
123static int
124inet_pton6(const char *src, u_char *dst)
125{
126 static const char xdigits_l[] = "0123456789abcdef",
127 xdigits_u[] = "0123456789ABCDEF";
128 u_char tmp[IN6ADDRSZ], *tp, *endp, *colonp;
129 const char *xdigits, *curtok;
130 int ch, saw_xdigit, count_xdigit;
131 u_int val;
132
133 memset((tp = tmp), '\0', IN6ADDRSZ);
134 endp = tp + IN6ADDRSZ;
135 colonp = NULL;
136 /* Leading :: requires some special handling. */
137 if (*src == ':')
138 if (*++src != ':')
139 return (0);
140 curtok = src;
141 saw_xdigit = count_xdigit = 0;
142 val = 0;
143 while ((ch = *src++) != '\0') {
144 const char *pch;
145
146 if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
147 pch = strchr((xdigits = xdigits_u), ch);
148 if (pch != NULL) {
149 if (count_xdigit >= 4)
150 return (0);
151 val <<= 4;
152 val |= (pch - xdigits);
153 if (val > 0xffff)
154 return (0);
155 saw_xdigit = 1;
156 count_xdigit++;
157 continue;
158 }
159 if (ch == ':') {
160 curtok = src;
161 if (!saw_xdigit) {
162 if (colonp)
163 return (0);
164 colonp = tp;
165 continue;
166 } else if (*src == '\0') {
167 return (0);
168 }
169 if (tp + INT16SZ > endp)
170 return (0);
171 *tp++ = (u_char) (val >> 8) & 0xff;
172 *tp++ = (u_char) val & 0xff;
173 saw_xdigit = 0;
174 count_xdigit = 0;
175 val = 0;
176 continue;
177 }
178 if (ch == '.' && ((tp + INADDRSZ) <= endp) &&
179 inet_pton4(curtok, tp) > 0) {
180 tp += INADDRSZ;
181 saw_xdigit = 0;
182 count_xdigit = 0;
183 break; /* '\0' was seen by inet_pton4(). */
184 }
185 return (0);
186 }
187 if (saw_xdigit) {
188 if (tp + INT16SZ > endp)
189 return (0);
190 *tp++ = (u_char) (val >> 8) & 0xff;
191 *tp++ = (u_char) val & 0xff;
192 }
193 if (colonp != NULL) {
194 /*
195 * Since some memmove()'s erroneously fail to handle
196 * overlapping regions, we'll do the shift by hand.
197 */
198 const int n = tp - colonp;
199 int i;
200
201 if (tp == endp)
202 return (0);
203 for (i = 1; i <= n; i++) {
204 endp[- i] = colonp[n - i];
205 colonp[n - i] = 0;
206 }
207 tp = endp;
208 }
209 if (tp != endp)
210 return (0);
211 memcpy(dst, tmp, IN6ADDRSZ);
212 return (1);
213}
diff --git a/src/lib/libc/net/ip6opt.c b/src/lib/libc/net/ip6opt.c
new file mode 100644
index 0000000000..b215f9ac3e
--- /dev/null
+++ b/src/lib/libc/net/ip6opt.c
@@ -0,0 +1,596 @@
1/* $OpenBSD: ip6opt.c,v 1.4 2006/12/09 01:12:28 itojun Exp $ */
2/* $KAME: ip6opt.c,v 1.18 2005/06/15 07:11:35 keiichi 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#include <sys/param.h>
34#include <sys/types.h>
35#include <sys/socket.h>
36
37#include <netinet/in.h>
38#include <netinet/ip6.h>
39
40#include <string.h>
41#include <stdio.h>
42
43static int ip6optlen(u_int8_t *opt, u_int8_t *lim);
44static void inet6_insert_padopt(u_char *p, int len);
45
46/*
47 * This function returns the number of bytes required to hold an option
48 * when it is stored as ancillary data, including the cmsghdr structure
49 * at the beginning, and any padding at the end (to make its size a
50 * multiple of 8 bytes). The argument is the size of the structure
51 * defining the option, which must include any pad bytes at the
52 * beginning (the value y in the alignment term "xn + y"), the type
53 * byte, the length byte, and the option data.
54 */
55int
56inet6_option_space(int nbytes)
57{
58 nbytes += 2; /* we need space for nxt-hdr and length fields */
59 return (CMSG_SPACE((nbytes + 7) & ~7));
60}
61
62/*
63 * This function is called once per ancillary data object that will
64 * contain either Hop-by-Hop or Destination options. It returns 0 on
65 * success or -1 on an error.
66 */
67int
68inet6_option_init(void *bp, struct cmsghdr **cmsgp, int type)
69{
70 struct cmsghdr *ch = (struct cmsghdr *)bp;
71
72 /* argument validation */
73 if (type != IPV6_HOPOPTS && type != IPV6_DSTOPTS)
74 return (-1);
75
76 ch->cmsg_level = IPPROTO_IPV6;
77 ch->cmsg_type = type;
78 ch->cmsg_len = CMSG_LEN(0);
79
80 *cmsgp = ch;
81 return (0);
82}
83
84/*
85 * This function appends a Hop-by-Hop option or a Destination option
86 * into an ancillary data object that has been initialized by
87 * inet6_option_init(). This function returns 0 if it succeeds or -1 on
88 * an error.
89 * multx is the value x in the alignment term "xn + y" described
90 * earlier. It must have a value of 1, 2, 4, or 8.
91 * plusy is the value y in the alignment term "xn + y" described
92 * earlier. It must have a value between 0 and 7, inclusive.
93 */
94int
95inet6_option_append(struct cmsghdr *cmsg, const u_int8_t *typep, int multx,
96 int plusy)
97{
98 int padlen, optlen, off;
99 u_char *bp = (u_char *)cmsg + cmsg->cmsg_len;
100 struct ip6_ext *eh = (struct ip6_ext *)CMSG_DATA(cmsg);
101
102 /* argument validation */
103 if (multx != 1 && multx != 2 && multx != 4 && multx != 8)
104 return (-1);
105 if (plusy < 0 || plusy > 7)
106 return (-1);
107#if 0
108 if (typep[0] > 255)
109 return (-1);
110#endif
111
112 /*
113 * If this is the first option, allocate space for the
114 * first 2 bytes(for next header and length fields) of
115 * the option header.
116 */
117 if (bp == (u_char *)eh) {
118 bp += 2;
119 cmsg->cmsg_len += 2;
120 }
121
122 /* calculate pad length before the option. */
123 off = bp - (u_char *)eh;
124 padlen = (((off % multx) + (multx - 1)) & ~(multx - 1)) -
125 (off % multx);
126 padlen += plusy;
127 padlen %= multx; /* keep the pad as short as possible */
128 /* insert padding */
129 inet6_insert_padopt(bp, padlen);
130 cmsg->cmsg_len += padlen;
131 bp += padlen;
132
133 /* copy the option */
134 if (typep[0] == IP6OPT_PAD1)
135 optlen = 1;
136 else
137 optlen = typep[1] + 2;
138 memcpy(bp, typep, optlen);
139 bp += optlen;
140 cmsg->cmsg_len += optlen;
141
142 /* calculate pad length after the option and insert the padding */
143 off = bp - (u_char *)eh;
144 padlen = ((off + 7) & ~7) - off;
145 inet6_insert_padopt(bp, padlen);
146 bp += padlen;
147 cmsg->cmsg_len += padlen;
148
149 /* update the length field of the ip6 option header */
150 eh->ip6e_len = ((bp - (u_char *)eh) >> 3) - 1;
151
152 return (0);
153}
154
155/*
156 * This function appends a Hop-by-Hop option or a Destination option
157 * into an ancillary data object that has been initialized by
158 * inet6_option_init(). This function returns a pointer to the 8-bit
159 * option type field that starts the option on success, or NULL on an
160 * error.
161 * The difference between this function and inet6_option_append() is
162 * that the latter copies the contents of a previously built option into
163 * the ancillary data object while the current function returns a
164 * pointer to the space in the data object where the option's TLV must
165 * then be built by the caller.
166 *
167 */
168u_int8_t *
169inet6_option_alloc(struct cmsghdr *cmsg, int datalen, int multx, int plusy)
170{
171 int padlen, off;
172 u_int8_t *bp = (u_char *)cmsg + cmsg->cmsg_len;
173 u_int8_t *retval;
174 struct ip6_ext *eh = (struct ip6_ext *)CMSG_DATA(cmsg);
175
176 /* argument validation */
177 if (multx != 1 && multx != 2 && multx != 4 && multx != 8)
178 return (NULL);
179 if (plusy < 0 || plusy > 7)
180 return (NULL);
181
182 /*
183 * If this is the first option, allocate space for the
184 * first 2 bytes(for next header and length fields) of
185 * the option header.
186 */
187 if (bp == (u_char *)eh) {
188 bp += 2;
189 cmsg->cmsg_len += 2;
190 }
191
192 /* calculate pad length before the option. */
193 off = bp - (u_char *)eh;
194 padlen = (((off % multx) + (multx - 1)) & ~(multx - 1)) -
195 (off % multx);
196 padlen += plusy;
197 padlen %= multx; /* keep the pad as short as possible */
198 /* insert padding */
199 inet6_insert_padopt(bp, padlen);
200 cmsg->cmsg_len += padlen;
201 bp += padlen;
202
203 /* keep space to store specified length of data */
204 retval = bp;
205 bp += datalen;
206 cmsg->cmsg_len += datalen;
207
208 /* calculate pad length after the option and insert the padding */
209 off = bp - (u_char *)eh;
210 padlen = ((off + 7) & ~7) - off;
211 inet6_insert_padopt(bp, padlen);
212 bp += padlen;
213 cmsg->cmsg_len += padlen;
214
215 /* update the length field of the ip6 option header */
216 eh->ip6e_len = ((bp - (u_char *)eh) >> 3) - 1;
217
218 return (retval);
219}
220
221/*
222 * This function processes the next Hop-by-Hop option or Destination
223 * option in an ancillary data object. If another option remains to be
224 * processed, the return value of the function is 0 and *tptrp points to
225 * the 8-bit option type field (which is followed by the 8-bit option
226 * data length, followed by the option data). If no more options remain
227 * to be processed, the return value is -1 and *tptrp is NULL. If an
228 * error occurs, the return value is -1 and *tptrp is not NULL.
229 * (RFC 2292, 6.3.5)
230 */
231int
232inet6_option_next(const struct cmsghdr *cmsg, u_int8_t **tptrp)
233{
234 struct ip6_ext *ip6e;
235 int hdrlen, optlen;
236 u_int8_t *lim;
237
238 if (cmsg->cmsg_level != IPPROTO_IPV6 ||
239 (cmsg->cmsg_type != IPV6_HOPOPTS &&
240 cmsg->cmsg_type != IPV6_DSTOPTS))
241 return (-1);
242
243 /* message length validation */
244 if (cmsg->cmsg_len < CMSG_SPACE(sizeof(struct ip6_ext)))
245 return (-1);
246 ip6e = (struct ip6_ext *)CMSG_DATA(cmsg);
247 hdrlen = (ip6e->ip6e_len + 1) << 3;
248 if (cmsg->cmsg_len < CMSG_SPACE(hdrlen))
249 return (-1);
250
251 /*
252 * If the caller does not specify the starting point,
253 * simply return the 1st option.
254 * Otherwise, search the option list for the next option.
255 */
256 lim = (u_int8_t *)ip6e + hdrlen;
257 if (*tptrp == NULL)
258 *tptrp = (u_int8_t *)(ip6e + 1);
259 else {
260 if ((optlen = ip6optlen(*tptrp, lim)) == 0)
261 return (-1);
262
263 *tptrp = *tptrp + optlen;
264 }
265 if (*tptrp >= lim) { /* there is no option */
266 *tptrp = NULL;
267 return (-1);
268 }
269 /*
270 * Finally, checks if the next option is safely stored in the
271 * cmsg data.
272 */
273 if (ip6optlen(*tptrp, lim) == 0)
274 return (-1);
275 else
276 return (0);
277}
278
279/*
280 * This function is similar to the inet6_option_next() function,
281 * except this function lets the caller specify the option type to be
282 * searched for, instead of always returning the next option in the
283 * ancillary data object.
284 * Note: RFC 2292 says the type of tptrp is u_int8_t *, but we think
285 * it's a typo. The variable should be type of u_int8_t **.
286 */
287int
288inet6_option_find(const struct cmsghdr *cmsg, u_int8_t **tptrp, int type)
289{
290 struct ip6_ext *ip6e;
291 int hdrlen, optlen;
292 u_int8_t *optp, *lim;
293
294 if (cmsg->cmsg_level != IPPROTO_IPV6 ||
295 (cmsg->cmsg_type != IPV6_HOPOPTS &&
296 cmsg->cmsg_type != IPV6_DSTOPTS))
297 return (-1);
298
299 /* message length validation */
300 if (cmsg->cmsg_len < CMSG_SPACE(sizeof(struct ip6_ext)))
301 return (-1);
302 ip6e = (struct ip6_ext *)CMSG_DATA(cmsg);
303 hdrlen = (ip6e->ip6e_len + 1) << 3;
304 if (cmsg->cmsg_len < CMSG_SPACE(hdrlen))
305 return (-1);
306
307 /*
308 * If the caller does not specify the starting point,
309 * search from the beginning of the option list.
310 * Otherwise, search from *the next option* of the specified point.
311 */
312 lim = (u_int8_t *)ip6e + hdrlen;
313 if (*tptrp == NULL)
314 *tptrp = (u_int8_t *)(ip6e + 1);
315 else {
316 if ((optlen = ip6optlen(*tptrp, lim)) == 0)
317 return (-1);
318
319 *tptrp = *tptrp + optlen;
320 }
321 for (optp = *tptrp; optp < lim; optp += optlen) {
322 if (*optp == type) {
323 *tptrp = optp;
324 return (0);
325 }
326 if ((optlen = ip6optlen(optp, lim)) == 0)
327 return (-1);
328 }
329
330 /* search failed */
331 *tptrp = NULL;
332 return (-1);
333}
334
335/*
336 * Calculate the length of a given IPv6 option. Also checks
337 * if the option is safely stored in user's buffer according to the
338 * calculated length and the limitation of the buffer.
339 */
340static int
341ip6optlen(u_int8_t *opt, u_int8_t *lim)
342{
343 int optlen;
344
345 if (*opt == IP6OPT_PAD1)
346 optlen = 1;
347 else {
348 /* is there enough space to store type and len? */
349 if (opt + 2 > lim)
350 return (0);
351 optlen = *(opt + 1) + 2;
352 }
353 if (opt + optlen <= lim)
354 return (optlen);
355
356 return (0);
357}
358
359static void
360inet6_insert_padopt(u_char *p, int len)
361{
362 switch(len) {
363 case 0:
364 return;
365 case 1:
366 p[0] = IP6OPT_PAD1;
367 return;
368 default:
369 p[0] = IP6OPT_PADN;
370 p[1] = len - 2;
371 memset(&p[2], 0, len - 2);
372 return;
373 }
374}
375
376/*
377 * The following functions are defined in RFC3542, which is a successor
378 * of RFC2292.
379 */
380
381int
382inet6_opt_init(void *extbuf, socklen_t extlen)
383{
384 struct ip6_ext *ext = (struct ip6_ext *)extbuf;
385
386 if (extlen < 0 || (extlen % 8))
387 return (-1);
388
389 if (ext) {
390 if (extlen == 0)
391 return (-1);
392 ext->ip6e_len = (extlen >> 3) - 1;
393 }
394
395 return (2); /* sizeof the next and the length fields */
396}
397
398int
399inet6_opt_append(void *extbuf, socklen_t extlen, int offset, u_int8_t type,
400 socklen_t len, u_int8_t align, void **databufp)
401{
402 int currentlen = offset, padlen = 0;
403
404 /*
405 * The option type must have a value from 2 to 255, inclusive.
406 * (0 and 1 are reserved for the Pad1 and PadN options, respectively.)
407 */
408#if 0 /* always false */
409 if (type < 2 || type > 255)
410#else
411 if (type < 2)
412#endif
413 return (-1);
414
415 /*
416 * The option data length must have a value between 0 and 255,
417 * inclusive, and is the length of the option data that follows.
418 */
419 if (len < 0 || len > 255)
420 return (-1);
421
422 /*
423 * The align parameter must have a value of 1, 2, 4, or 8.
424 * The align value can not exceed the value of len.
425 */
426 if (align != 1 && align != 2 && align != 4 && align != 8)
427 return (-1);
428 if (align > len)
429 return (-1);
430
431 /* Calculate the padding length. */
432 currentlen += 2 + len; /* 2 means "type + len" */
433 if (currentlen % align)
434 padlen = align - (currentlen % align);
435
436 /* The option must fit in the extension header buffer. */
437 currentlen += padlen;
438 if (extlen && /* XXX: right? */
439 currentlen > extlen)
440 return (-1);
441
442 if (extbuf) {
443 u_int8_t *optp = (u_int8_t *)extbuf + offset;
444
445 if (padlen == 1) {
446 /* insert a Pad1 option */
447 *optp = IP6OPT_PAD1;
448 optp++;
449 } else if (padlen > 0) {
450 /* insert a PadN option for alignment */
451 *optp++ = IP6OPT_PADN;
452 *optp++ = padlen - 2;
453 memset(optp, 0, padlen - 2);
454 optp += (padlen - 2);
455 }
456
457 *optp++ = type;
458 *optp++ = len;
459
460 *databufp = optp;
461 }
462
463 return (currentlen);
464}
465
466int
467inet6_opt_finish(void *extbuf, socklen_t extlen, int offset)
468{
469 int updatelen = offset > 0 ? (1 + ((offset - 1) | 7)) : 0;;
470
471 if (extbuf) {
472 u_int8_t *padp;
473 int padlen = updatelen - offset;
474
475 if (updatelen > extlen)
476 return (-1);
477
478 padp = (u_int8_t *)extbuf + offset;
479 if (padlen == 1)
480 *padp = IP6OPT_PAD1;
481 else if (padlen > 0) {
482 *padp++ = IP6OPT_PADN;
483 *padp++ = (padlen - 2);
484 memset(padp, 0, padlen - 2);
485 }
486 }
487
488 return (updatelen);
489}
490
491int
492inet6_opt_set_val(void *databuf, int offset, void *val, socklen_t vallen)
493{
494
495 memcpy((u_int8_t *)databuf + offset, val, vallen);
496 return (offset + vallen);
497}
498
499int
500inet6_opt_next(void *extbuf, socklen_t extlen, int offset, u_int8_t *typep,
501 socklen_t *lenp, void **databufp)
502{
503 u_int8_t *optp, *lim;
504 int optlen;
505
506 /* Validate extlen. XXX: is the variable really necessary?? */
507 if (extlen == 0 || (extlen % 8))
508 return (-1);
509 lim = (u_int8_t *)extbuf + extlen;
510
511 /*
512 * If this is the first time this function called for this options
513 * header, simply return the 1st option.
514 * Otherwise, search the option list for the next option.
515 */
516 if (offset == 0)
517 optp = (u_int8_t *)((struct ip6_hbh *)extbuf + 1);
518 else
519 optp = (u_int8_t *)extbuf + offset;
520
521 /* Find the next option skipping any padding options. */
522 while (optp < lim) {
523 switch(*optp) {
524 case IP6OPT_PAD1:
525 optp++;
526 break;
527 case IP6OPT_PADN:
528 if ((optlen = ip6optlen(optp, lim)) == 0)
529 goto optend;
530 optp += optlen;
531 break;
532 default: /* found */
533 if ((optlen = ip6optlen(optp, lim)) == 0)
534 goto optend;
535 *typep = *optp;
536 *lenp = optlen - 2;
537 *databufp = optp + 2;
538 return (optp + optlen - (u_int8_t *)extbuf);
539 }
540 }
541
542 optend:
543 *databufp = NULL; /* for safety */
544 return (-1);
545}
546
547int
548inet6_opt_find(void *extbuf, socklen_t extlen, int offset, u_int8_t type,
549 socklen_t *lenp, void **databufp)
550{
551 u_int8_t *optp, *lim;
552 int optlen;
553
554 /* Validate extlen. XXX: is the variable really necessary?? */
555 if (extlen == 0 || (extlen % 8))
556 return (-1);
557 lim = (u_int8_t *)extbuf + extlen;
558
559 /*
560 * If this is the first time this function called for this options
561 * header, simply return the 1st option.
562 * Otherwise, search the option list for the next option.
563 */
564 if (offset == 0)
565 optp = (u_int8_t *)((struct ip6_hbh *)extbuf + 1);
566 else
567 optp = (u_int8_t *)extbuf + offset;
568
569 /* Find the specified option */
570 while (optp < lim) {
571 if ((optlen = ip6optlen(optp, lim)) == 0)
572 goto optend;
573
574 if (*optp == type) { /* found */
575 *lenp = optlen - 2;
576 *databufp = optp + 2;
577 return (optp + optlen - (u_int8_t *)extbuf);
578 }
579
580 optp += optlen;
581 }
582
583 optend:
584 *databufp = NULL; /* for safety */
585 return (-1);
586}
587
588int
589inet6_opt_get_val(void *databuf, int offset, void *val, socklen_t vallen)
590{
591
592 /* we can't assume alignment here */
593 memcpy(val, (u_int8_t *)databuf + offset, vallen);
594
595 return (offset + vallen);
596}
diff --git a/src/lib/libc/net/iso_addr.3 b/src/lib/libc/net/iso_addr.3
deleted file mode 100644
index 95c136e5fc..0000000000
--- a/src/lib/libc/net/iso_addr.3
+++ /dev/null
@@ -1,112 +0,0 @@
1.\" $NetBSD: iso_addr.3,v 1.2 1995/02/25 06:20:46 cgd Exp $
2.\"
3.\" Copyright (c) 1993
4.\" The Regents of the University of California. All rights reserved.
5.\"
6.\" Redistribution and use in source and binary forms, with or without
7.\" modification, are permitted provided that the following conditions
8.\" are met:
9.\" 1. Redistributions of source code must retain the above copyright
10.\" notice, this list of conditions and the following disclaimer.
11.\" 2. Redistributions in binary form must reproduce the above copyright
12.\" notice, this list of conditions and the following disclaimer in the
13.\" documentation and/or other materials provided with the distribution.
14.\" 3. All advertising materials mentioning features or use of this software
15.\" must display the following acknowledgement:
16.\" This product includes software developed by the University of
17.\" California, Berkeley and its contributors.
18.\" 4. Neither the name of the University nor the names of its contributors
19.\" may be used to endorse or promote products derived from this software
20.\" without specific prior written permission.
21.\"
22.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32.\" SUCH DAMAGE.
33.\"
34.\" @(#)iso_addr.3 8.1 (Berkeley) 6/4/93
35.\"
36.Dd June 4, 1993
37.Dt ISO_ADDR 3
38.Os
39.Sh NAME
40.Nm iso_addr ,
41.Nm iso_ntoa
42.Nd "elementary network address conversion routines for Open System Interconnection
43.Sh SYNOPSIS
44.Fd #include <sys/types.h>
45.Fd #include <netiso/iso.h>
46.Ft struct iso_addr *
47.Fn iso_addr "char *cp"
48.Ft char *
49.Fn iso_ntoa "struct iso_addr *isoa"
50.Sh DESCRIPTION
51The routine
52.Fn iso_addr
53interprets character strings representing
54.Tn OSI
55addresses, returning binary information suitable
56for use in system calls.
57The routine
58.Fn iso_ntoa
59takes
60.Tn OSI
61addresses and returns
62.Tn ASCII
63strings representing NSAPs (network service
64access points) in a
65notation inverse to that accepted by
66.Fn iso_addr .
67.Pp
68Unfortunately, no universal standard exists for representing
69.Tn OSI
70network addresses.
71.Pp
72The format employed by
73.Fn iso_addr
74is a sequence of hexadecimal
75.Dq digits
76(optionally separated by periods),
77of the form:
78.Bd -filled -offset indent
79<hex digits>.<hex digits>.<hex digits>
80.Ed
81.Pp
82Each pair of hexadecimal digits represents a byte
83with the leading digit indicating the higher-ordered bits.
84A period following an even number of bytes has no
85effect (but may be used to increase legibility).
86A period following an odd number of bytes has the
87effect of causing the byte of address being translated
88to have its higher order bits filled with zeros.
89.Sh RETURN VALUES
90.Fn iso_ntoa
91always returns a null terminated string.
92.Fn iso_addr
93always returns a pointer to a struct iso_addr.
94(See
95.Sx BUGS . )
96.Sh SEE ALSO
97.Xr iso 4
98.Sh HISTORY
99The
100.Fn iso_addr
101and
102.Fn iso_ntoa
103functions appeared in
104.Bx 4.3 Reno .
105.Sh BUGS
106The returned values
107reside in a static memory area.
108.Pp
109The function
110.Fn iso_addr
111should diagnose improperly formed input, and there should be an unambiguous
112way to recognize this.
diff --git a/src/lib/libc/net/iso_addr.c b/src/lib/libc/net/iso_addr.c
deleted file mode 100644
index c26ec1a64a..0000000000
--- a/src/lib/libc/net/iso_addr.c
+++ /dev/null
@@ -1,125 +0,0 @@
1/* $NetBSD: iso_addr.c,v 1.4 1995/02/25 06:20:47 cgd Exp $ */
2
3/*
4 * Copyright (c) 1989, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36#if defined(LIBC_SCCS) && !defined(lint)
37#if 0
38static char sccsid[] = "@(#)iso_addr.c 8.1 (Berkeley) 6/4/93";
39#else
40static char rcsid[] = "$NetBSD: iso_addr.c,v 1.4 1995/02/25 06:20:47 cgd Exp $";
41#endif
42#endif /* LIBC_SCCS and not lint */
43
44#include <sys/types.h>
45#include <netiso/iso.h>
46#include <string.h>
47
48/* States*/
49#define VIRGIN 0
50#define GOTONE 1
51#define GOTTWO 2
52/* Inputs */
53#define DIGIT (4*0)
54#define END (4*1)
55#define DELIM (4*2)
56
57struct iso_addr *
58iso_addr(addr)
59 register const char *addr;
60{
61 static struct iso_addr out_addr;
62 register char *cp = out_addr.isoa_genaddr;
63 char *cplim = cp + sizeof(out_addr.isoa_genaddr);
64 register int byte = 0, state = VIRGIN, new;
65
66 bzero((char *)&out_addr, sizeof(out_addr));
67 do {
68 if ((*addr >= '0') && (*addr <= '9')) {
69 new = *addr - '0';
70 } else if ((*addr >= 'a') && (*addr <= 'f')) {
71 new = *addr - 'a' + 10;
72 } else if ((*addr >= 'A') && (*addr <= 'F')) {
73 new = *addr - 'A' + 10;
74 } else if (*addr == 0)
75 state |= END;
76 else
77 state |= DELIM;
78 addr++;
79 switch (state /* | INPUT */) {
80 case GOTTWO | DIGIT:
81 *cp++ = byte; /*FALLTHROUGH*/
82 case VIRGIN | DIGIT:
83 state = GOTONE; byte = new; continue;
84 case GOTONE | DIGIT:
85 state = GOTTWO; byte = new + (byte << 4); continue;
86 default: /* | DELIM */
87 state = VIRGIN; *cp++ = byte; byte = 0; continue;
88 case GOTONE | END:
89 case GOTTWO | END:
90 *cp++ = byte; /* FALLTHROUGH */
91 case VIRGIN | END:
92 break;
93 }
94 break;
95 } while (cp < cplim);
96 out_addr.isoa_len = cp - out_addr.isoa_genaddr;
97 return (&out_addr);
98}
99static char hexlist[] = "0123456789abcdef";
100
101char *
102iso_ntoa(isoa)
103 const struct iso_addr *isoa;
104{
105 static char obuf[64];
106 register char *out = obuf;
107 register int i;
108 register u_char *in = (u_char *)isoa->isoa_genaddr;
109 u_char *inlim = in + isoa->isoa_len;
110
111 out[1] = 0;
112 while (in < inlim) {
113 i = *in++;
114 *out++ = '.';
115 if (i > 0xf) {
116 out[1] = hexlist[i & 0xf];
117 i >>= 4;
118 out[0] = hexlist[i];
119 out += 2;
120 } else
121 *out++ = hexlist[i];
122 }
123 *out = 0;
124 return(obuf + 1);
125}
diff --git a/src/lib/libc/net/linkaddr.3 b/src/lib/libc/net/link_addr.3
index 1a2af9b30d..e6210ef2d0 100644
--- a/src/lib/libc/net/linkaddr.3
+++ b/src/lib/libc/net/link_addr.3
@@ -1,4 +1,4 @@
1.\" $NetBSD: linkaddr.3,v 1.2 1995/02/25 06:20:48 cgd Exp $ 1.\" $OpenBSD: link_addr.3,v 1.12 2007/05/31 19:19:30 jmc Exp $
2.\" 2.\"
3.\" Copyright (c) 1993 3.\" Copyright (c) 1993
4.\" The Regents of the University of California. All rights reserved. 4.\" The Regents of the University of California. All rights reserved.
@@ -14,11 +14,7 @@
14.\" 2. Redistributions in binary form must reproduce the above copyright 14.\" 2. Redistributions in binary form must reproduce the above copyright
15.\" notice, this list of conditions and the following disclaimer in the 15.\" notice, this list of conditions and the following disclaimer in the
16.\" documentation and/or other materials provided with the distribution. 16.\" documentation and/or other materials provided with the distribution.
17.\" 3. All advertising materials mentioning features or use of this software 17.\" 3. Neither the name of the University nor the names of its contributors
18.\" must display the following acknowledgement:
19.\" This product includes software developed by the University of
20.\" California, Berkeley and its contributors.
21.\" 4. Neither the name of the University nor the names of its contributors
22.\" may be used to endorse or promote products derived from this software 18.\" may be used to endorse or promote products derived from this software
23.\" without specific prior written permission. 19.\" without specific prior written permission.
24.\" 20.\"
@@ -34,11 +30,9 @@
34.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35.\" SUCH DAMAGE. 31.\" SUCH DAMAGE.
36.\" 32.\"
37.\" @(#)linkaddr.3 8.1 (Berkeley) 7/28/93 33.Dd $Mdocdate: May 31 2007 $
38.\"
39.Dd July 28, 1993
40.Dt LINK_ADDR 3 34.Dt LINK_ADDR 3
41.Os BSD 4.4 35.Os
42.Sh NAME 36.Sh NAME
43.Nm link_addr , 37.Nm link_addr ,
44.Nm link_ntoa 38.Nm link_ntoa
@@ -52,12 +46,11 @@
52.Ft char * 46.Ft char *
53.Fn link_ntoa "const struct sockaddr_dl *sdl" 47.Fn link_ntoa "const struct sockaddr_dl *sdl"
54.Sh DESCRIPTION 48.Sh DESCRIPTION
55The routine 49The
56.Fn link_addr 50.Fn link_addr
57interprets character strings representing 51function interprets character strings representing
58link-level addresses, returning binary information suitable 52link-level addresses, returning binary information suitable
59for use in system calls. 53for use in system calls.
60The routine
61.Fn link_ntoa 54.Fn link_ntoa
62takes 55takes
63a link-level 56a link-level
@@ -75,9 +68,9 @@ the string
75.Fa addr 68.Fa addr
76may contain 69may contain
77an optional network interface identifier of the form 70an optional network interface identifier of the form
78.Dq "name unit-number" , 71.Dq name unit-number ,
79suitable for the first argument to 72suitable for the first argument to
80.Xr ifconfig 4 , 73.Xr ifconfig 8 ,
81followed in all cases by a colon and 74followed in all cases by a colon and
82an interface address in the form of 75an interface address in the form of
83groups of hexadecimal digits 76groups of hexadecimal digits
@@ -93,26 +86,27 @@ low order bytes through high order bytes.
93.\" .Pp 86.\" .Pp
94Thus 87Thus
95.Li le0:8.0.9.13.d.30 88.Li le0:8.0.9.13.d.30
96represents an ethernet address 89represents an Ethernet address
97to be transmitted on the first Lance ethernet interface. 90to be transmitted on the first Lance Ethernet interface.
98.Sh RETURN VALUES 91.Sh RETURN VALUES
99.Fn link_ntoa 92.Fn link_ntoa
100always returns a null terminated string. 93always returns a NUL-terminated string.
101.Fn link_addr 94.Fn link_addr
102has no return value. 95has no return value.
103(See 96(See
104.Sx BUGS . ) 97.Sx BUGS . )
105.Sh SEE ALSO 98.Sh SEE ALSO
106.Xr iso 4 , 99.Xr ifconfig 8
107.Sh HISTORY 100.Sh HISTORY
108The 101The
109.Fn link_addr 102.Fn link_addr
110and 103and
111.Fn link_ntoa 104.Fn link_ntoa
112functions appeared in 105functions appeared in
113.Bx 4.3 Reno . 106.Bx 4.3 Reno .
114.Sh BUGS 107.Sh BUGS
115The returned values for link_ntoa 108The returned values for
109.Fn link_ntoa
116reside in a static memory area. 110reside in a static memory area.
117.Pp 111.Pp
118The function 112The function
@@ -121,7 +115,7 @@ should diagnose improperly formed input, and there should be an unambiguous
121way to recognize this. 115way to recognize this.
122.Pp 116.Pp
123If the 117If the
124.Va sdl_len 118.Fa sdl_len
125field of the link socket address 119field of the link socket address
126.Fa sdl 120.Fa sdl
127is 0, 121is 0,
diff --git a/src/lib/libc/net/linkaddr.c b/src/lib/libc/net/linkaddr.c
index 19a0de3abd..ac96f3acdf 100644
--- a/src/lib/libc/net/linkaddr.c
+++ b/src/lib/libc/net/linkaddr.c
@@ -1,5 +1,4 @@
1/* $NetBSD: linkaddr.c,v 1.5 1995/02/25 06:20:49 cgd Exp $ */ 1/* $OpenBSD: linkaddr.c,v 1.5 2005/08/06 20:30:03 espie Exp $ */
2
3/*- 2/*-
4 * Copyright (c) 1990, 1993 3 * Copyright (c) 1990, 1993
5 * The Regents of the University of California. All rights reserved. 4 * The Regents of the University of California. All rights reserved.
@@ -12,11 +11,7 @@
12 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software 14 * 3. Neither the name of the University nor the names of its contributors
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software 15 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission. 16 * without specific prior written permission.
22 * 17 *
@@ -33,14 +28,6 @@
33 * SUCH DAMAGE. 28 * SUCH DAMAGE.
34 */ 29 */
35 30
36#if defined(LIBC_SCCS) && !defined(lint)
37#if 0
38static char sccsid[] = "@(#)linkaddr.c 8.1 (Berkeley) 6/4/93";
39#else
40static char rcsid[] = "$NetBSD: linkaddr.c,v 1.5 1995/02/25 06:20:49 cgd Exp $";
41#endif
42#endif /* LIBC_SCCS and not lint */
43
44#include <sys/types.h> 31#include <sys/types.h>
45#include <sys/socket.h> 32#include <sys/socket.h>
46#include <net/if_dl.h> 33#include <net/if_dl.h>
@@ -58,13 +45,11 @@ static char rcsid[] = "$NetBSD: linkaddr.c,v 1.5 1995/02/25 06:20:49 cgd Exp $";
58#define LETTER (4*3) 45#define LETTER (4*3)
59 46
60void 47void
61link_addr(addr, sdl) 48link_addr(const char *addr, struct sockaddr_dl *sdl)
62 register const char *addr;
63 register struct sockaddr_dl *sdl;
64{ 49{
65 register char *cp = sdl->sdl_data; 50 char *cp = sdl->sdl_data;
66 char *cplim = sdl->sdl_len + (char *)sdl; 51 char *cplim = sdl->sdl_len + (char *)sdl;
67 register int byte = 0, state = NAMING, new; 52 int byte = 0, state = NAMING, new;
68 53
69 bzero((char *)&sdl->sdl_family, sdl->sdl_len - 1); 54 bzero((char *)&sdl->sdl_family, sdl->sdl_len - 1);
70 sdl->sdl_family = AF_LINK; 55 sdl->sdl_family = AF_LINK;
@@ -129,13 +114,12 @@ link_addr(addr, sdl)
129static char hexlist[] = "0123456789abcdef"; 114static char hexlist[] = "0123456789abcdef";
130 115
131char * 116char *
132link_ntoa(sdl) 117link_ntoa(const struct sockaddr_dl *sdl)
133 register const struct sockaddr_dl *sdl;
134{ 118{
135 static char obuf[64]; 119 static char obuf[64];
136 register char *out = obuf; 120 char *out = obuf;
137 register int i; 121 int i;
138 register u_char *in = (u_char *)LLADDR(sdl); 122 u_char *in = (u_char *)LLADDR(sdl);
139 u_char *inlim = in + sdl->sdl_alen; 123 u_char *inlim = in + sdl->sdl_alen;
140 int firsttime = 1; 124 int firsttime = 1;
141 125
diff --git a/src/lib/libc/net/net_addrcmp.3 b/src/lib/libc/net/net_addrcmp.3
new file mode 100644
index 0000000000..a02e6e2619
--- /dev/null
+++ b/src/lib/libc/net/net_addrcmp.3
@@ -0,0 +1,91 @@
1.\" $OpenBSD: net_addrcmp.3,v 1.4 2007/05/31 19:19:30 jmc 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 $Mdocdate: May 31 2007 $
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/ns.3 b/src/lib/libc/net/ns.3
deleted file mode 100644
index f89b4fe042..0000000000
--- a/src/lib/libc/net/ns.3
+++ /dev/null
@@ -1,132 +0,0 @@
1.\" $NetBSD: ns.3,v 1.3 1995/02/25 06:20:50 cgd Exp $
2.\"
3.\" Copyright (c) 1986, 1991, 1993
4.\" The Regents of the University of California. All rights reserved.
5.\"
6.\" Redistribution and use in source and binary forms, with or without
7.\" modification, are permitted provided that the following conditions
8.\" are met:
9.\" 1. Redistributions of source code must retain the above copyright
10.\" notice, this list of conditions and the following disclaimer.
11.\" 2. Redistributions in binary form must reproduce the above copyright
12.\" notice, this list of conditions and the following disclaimer in the
13.\" documentation and/or other materials provided with the distribution.
14.\" 3. All advertising materials mentioning features or use of this software
15.\" must display the following acknowledgement:
16.\" This product includes software developed by the University of
17.\" California, Berkeley and its contributors.
18.\" 4. Neither the name of the University nor the names of its contributors
19.\" may be used to endorse or promote products derived from this software
20.\" without specific prior written permission.
21.\"
22.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32.\" SUCH DAMAGE.
33.\"
34.\" @(#)ns.3 8.1 (Berkeley) 6/4/93
35.\"
36.Dd June 4, 1993
37.Dt NS 3
38.Os BSD 4.3
39.Sh NAME
40.Nm ns_addr ,
41.Nm ns_ntoa
42.Nd Xerox
43.Tn NS Ns (tm)
44address conversion routines
45.Sh SYNOPSIS
46.Fd #include <sys/types.h>
47.Fd #include <netns/ns.h>
48.Ft struct ns_addr
49.Fn ns_addr "char *cp"
50.Ft char *
51.Fn ns_ntoa "struct ns_addr ns"
52.Sh DESCRIPTION
53The routine
54.Fn ns_addr
55interprets character strings representing
56.Tn XNS
57addresses, returning binary information suitable
58for use in system calls.
59The routine
60.Fn ns_ntoa
61takes
62.Tn XNS
63addresses and returns
64.Tn ASCII
65strings representing the address in a
66notation in common use in the Xerox Development Environment:
67.Bd -filled -offset indent
68<network number>.<host number>.<port number>
69.Ed
70.Pp
71Trailing zero fields are suppressed, and each number is printed in hexadecimal,
72in a format suitable for input to
73.Fn ns_addr .
74Any fields lacking super-decimal digits will have a
75trailing
76.Ql H
77appended.
78.Pp
79Unfortunately, no universal standard exists for representing
80.Tn XNS
81addresses.
82An effort has been made to insure that
83.Fn ns_addr
84be compatible with most formats in common use.
85It will first separate an address into 1 to 3 fields using a single delimiter
86chosen from
87period
88.Ql \&. ,
89colon
90.Ql \&:
91or pound-sign
92.Ql \&# .
93Each field is then examined for byte separators (colon or period).
94If there are byte separators, each subfield separated is taken to be
95a small hexadecimal number, and the entirety is taken as a network-byte-ordered
96quantity to be zero extended in the high-network-order bytes.
97Next, the field is inspected for hyphens, in which case
98the field is assumed to be a number in decimal notation
99with hyphens separating the millenia.
100Next, the field is assumed to be a number:
101It is interpreted
102as hexadecimal if there is a leading
103.Ql 0x
104(as in C),
105a trailing
106.Ql H
107(as in Mesa), or there are any super-decimal digits present.
108It is interpreted as octal is there is a leading
109.Ql 0
110and there are no super-octal digits.
111Otherwise, it is converted as a decimal number.
112.Sh RETURN VALUES
113None. (See
114.Sx BUGS . )
115.Sh SEE ALSO
116.Xr hosts 5 ,
117.Xr networks 5 ,
118.Sh HISTORY
119The
120.Fn ns_addr
121and
122.Fn ns_toa
123functions appeared in
124.Bx 4.3 .
125.Sh BUGS
126The string returned by
127.Fn ns_ntoa
128resides in a static memory area.
129The function
130.Fn ns_addr
131should diagnose improperly formed input, and there should be an unambiguous
132way to recognize this.
diff --git a/src/lib/libc/net/ns_addr.c b/src/lib/libc/net/ns_addr.c
deleted file mode 100644
index f75ddb23b7..0000000000
--- a/src/lib/libc/net/ns_addr.c
+++ /dev/null
@@ -1,233 +0,0 @@
1/* $NetBSD: ns_addr.c,v 1.5 1995/02/25 06:20:51 cgd Exp $ */
2
3/*
4 * Copyright (c) 1986, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * J.Q. Johnson.
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 University of
21 * California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 */
38
39#if defined(LIBC_SCCS) && !defined(lint)
40#if 0
41static char sccsid[] = "@(#)ns_addr.c 8.1 (Berkeley) 6/7/93";
42#else
43static char rcsid[] = "$NetBSD: ns_addr.c,v 1.5 1995/02/25 06:20:51 cgd Exp $";
44#endif
45#endif /* LIBC_SCCS and not lint */
46
47#include <sys/param.h>
48#include <netns/ns.h>
49#include <stdio.h>
50#include <string.h>
51
52static struct ns_addr addr, zero_addr;
53
54static void Field(), cvtbase();
55
56struct ns_addr
57ns_addr(name)
58 const char *name;
59{
60 char separator;
61 char *hostname, *socketname, *cp;
62 char buf[50];
63
64 (void)strncpy(buf, name, sizeof(buf) - 1);
65 buf[sizeof(buf) - 1] = '\0';
66
67 /*
68 * First, figure out what he intends as a field separtor.
69 * Despite the way this routine is written, the prefered
70 * form 2-272.AA001234H.01777, i.e. XDE standard.
71 * Great efforts are made to insure backward compatability.
72 */
73 if (hostname = strchr(buf, '#'))
74 separator = '#';
75 else {
76 hostname = strchr(buf, '.');
77 if ((cp = strchr(buf, ':')) &&
78 ((hostname && cp < hostname) || (hostname == 0))) {
79 hostname = cp;
80 separator = ':';
81 } else
82 separator = '.';
83 }
84 if (hostname)
85 *hostname++ = 0;
86
87 addr = zero_addr;
88 Field(buf, addr.x_net.c_net, 4);
89 if (hostname == 0)
90 return (addr); /* No separator means net only */
91
92 socketname = strchr(hostname, separator);
93 if (socketname) {
94 *socketname++ = 0;
95 Field(socketname, (u_char *)&addr.x_port, 2);
96 }
97
98 Field(hostname, addr.x_host.c_host, 6);
99
100 return (addr);
101}
102
103static void
104Field(buf, out, len)
105 char *buf;
106 u_char *out;
107 int len;
108{
109 register char *bp = buf;
110 int i, ibase, base16 = 0, base10 = 0, clen = 0;
111 int hb[6], *hp;
112 char *fmt;
113
114 /*
115 * first try 2-273#2-852-151-014#socket
116 */
117 if ((*buf != '-') &&
118 (1 < (i = sscanf(buf, "%d-%d-%d-%d-%d",
119 &hb[0], &hb[1], &hb[2], &hb[3], &hb[4])))) {
120 cvtbase(1000L, 256, hb, i, out, len);
121 return;
122 }
123 /*
124 * try form 8E1#0.0.AA.0.5E.E6#socket
125 */
126 if (1 < (i = sscanf(buf,"%x.%x.%x.%x.%x.%x",
127 &hb[0], &hb[1], &hb[2], &hb[3], &hb[4], &hb[5]))) {
128 cvtbase(256L, 256, hb, i, out, len);
129 return;
130 }
131 /*
132 * try form 8E1#0:0:AA:0:5E:E6#socket
133 */
134 if (1 < (i = sscanf(buf,"%x:%x:%x:%x:%x:%x",
135 &hb[0], &hb[1], &hb[2], &hb[3], &hb[4], &hb[5]))) {
136 cvtbase(256L, 256, hb, i, out, len);
137 return;
138 }
139 /*
140 * This is REALLY stretching it but there was a
141 * comma notation separting shorts -- definitely non standard
142 */
143 if (1 < (i = sscanf(buf,"%x,%x,%x",
144 &hb[0], &hb[1], &hb[2]))) {
145 hb[0] = htons(hb[0]); hb[1] = htons(hb[1]);
146 hb[2] = htons(hb[2]);
147 cvtbase(65536L, 256, hb, i, out, len);
148 return;
149 }
150
151 /* Need to decide if base 10, 16 or 8 */
152 while (*bp) switch (*bp++) {
153
154 case '0': case '1': case '2': case '3': case '4': case '5':
155 case '6': case '7': case '-':
156 break;
157
158 case '8': case '9':
159 base10 = 1;
160 break;
161
162 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
163 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
164 base16 = 1;
165 break;
166
167 case 'x': case 'X':
168 *--bp = '0';
169 base16 = 1;
170 break;
171
172 case 'h': case 'H':
173 base16 = 1;
174 /* fall into */
175
176 default:
177 *--bp = 0; /* Ends Loop */
178 }
179 if (base16) {
180 fmt = "%3x";
181 ibase = 4096;
182 } else if (base10 == 0 && *buf == '0') {
183 fmt = "%3o";
184 ibase = 512;
185 } else {
186 fmt = "%3d";
187 ibase = 1000;
188 }
189
190 for (bp = buf; *bp++; ) clen++;
191 if (clen == 0) clen++;
192 if (clen > 18) clen = 18;
193 i = ((clen - 1) / 3) + 1;
194 bp = clen + buf - 3;
195 hp = hb + i - 1;
196
197 while (hp > hb) {
198 (void)sscanf(bp, fmt, hp);
199 bp[0] = 0;
200 hp--;
201 bp -= 3;
202 }
203 (void)sscanf(buf, fmt, hp);
204 cvtbase((long)ibase, 256, hb, i, out, len);
205}
206
207static void
208cvtbase(oldbase,newbase,input,inlen,result,reslen)
209 long oldbase;
210 int newbase;
211 int input[];
212 int inlen;
213 unsigned char result[];
214 int reslen;
215{
216 int d, e;
217 long sum;
218
219 e = 1;
220 while (e > 0 && reslen > 0) {
221 d = 0; e = 0; sum = 0;
222 /* long division: input=input/newbase */
223 while (d < inlen) {
224 sum = sum*oldbase + (long) input[d];
225 e += (sum > 0);
226 input[d++] = sum / newbase;
227 sum %= newbase;
228 }
229 result[--reslen] = sum; /* accumulate remainder */
230 }
231 for (d=0; d < reslen; d++)
232 result[d] = 0;
233}
diff --git a/src/lib/libc/net/ns_ntoa.c b/src/lib/libc/net/ns_ntoa.c
deleted file mode 100644
index ad3265399b..0000000000
--- a/src/lib/libc/net/ns_ntoa.c
+++ /dev/null
@@ -1,106 +0,0 @@
1/* $NetBSD: ns_ntoa.c,v 1.4 1995/02/25 06:20:51 cgd Exp $ */
2
3/*
4 * Copyright (c) 1986, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36#if defined(LIBC_SCCS) && !defined(lint)
37#if 0
38static char sccsid[] = "@(#)ns_ntoa.c 8.1 (Berkeley) 6/4/93";
39#else
40static char rcsid[] = "$NetBSD: ns_ntoa.c,v 1.4 1995/02/25 06:20:51 cgd Exp $";
41#endif
42#endif /* LIBC_SCCS and not lint */
43
44#include <sys/param.h>
45#include <netns/ns.h>
46#include <stdio.h>
47
48char *
49ns_ntoa(addr)
50 struct ns_addr addr;
51{
52 static char obuf[40];
53 union { union ns_net net_e; u_long long_e; } net;
54 u_short port = htons(addr.x_port);
55 register char *cp;
56 char *cp2;
57 register u_char *up = addr.x_host.c_host;
58 u_char *uplim = up + 6;
59 static char *spectHex();
60
61 net.net_e = addr.x_net;
62 sprintf(obuf, "%lx", ntohl(net.long_e));
63 cp = spectHex(obuf);
64 cp2 = cp + 1;
65 while (*up==0 && up < uplim) up++;
66 if (up == uplim) {
67 if (port) {
68 sprintf(cp, ".0");
69 cp += 2;
70 }
71 } else {
72 sprintf(cp, ".%x", *up++);
73 while (up < uplim) {
74 while (*cp) cp++;
75 sprintf(cp, "%02x", *up++);
76 }
77 cp = spectHex(cp2);
78 }
79 if (port) {
80 sprintf(cp, ".%x", port);
81 spectHex(cp + 1);
82 }
83 return (obuf);
84}
85
86static char *
87spectHex(p0)
88 char *p0;
89{
90 int ok = 0;
91 int nonzero = 0;
92 register char *p = p0;
93 for (; *p; p++) switch (*p) {
94
95 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
96 *p += ('A' - 'a');
97 /* fall into . . . */
98 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
99 ok = 1;
100 case '1': case '2': case '3': case '4': case '5':
101 case '6': case '7': case '8': case '9':
102 nonzero = 1;
103 }
104 if (nonzero && !ok) { *p++ = 'H'; *p = 0; }
105 return (p);
106}
diff --git a/src/lib/libc/net/nsap_addr.c b/src/lib/libc/net/nsap_addr.c
new file mode 100644
index 0000000000..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
index 05b7f4c9a3..36414b7a13 100644
--- a/src/lib/libc/net/ntohl.c
+++ b/src/lib/libc/net/ntohl.c
@@ -1,29 +1,21 @@
1/* $NetBSD: ntohl.c,v 1.5 1995/04/28 23:25:21 jtc Exp $ */ 1/* $OpenBSD: ntohl.c,v 1.6 2005/08/06 20:30:03 espie Exp $ */
2
3/* 2/*
4 * Written by J.T. Conklin <jtc@netbsd.org>. 3 * Written by J.T. Conklin <jtc@netbsd.org>.
5 * Public domain. 4 * Public domain.
6 */ 5 */
7 6
8#if defined(LIBC_SCCS) && !defined(lint)
9static char *rcsid = "$NetBSD: ntohl.c,v 1.5 1995/04/28 23:25:21 jtc Exp $";
10#endif
11
12#include <sys/types.h> 7#include <sys/types.h>
13#include <machine/endian.h> 8#include <machine/endian.h>
14 9
15#undef ntohl 10#undef ntohl
16 11
17unsigned long 12u_int32_t
18ntohl(x) 13ntohl(u_int32_t x)
19 unsigned long x;
20{ 14{
21 u_int32_t y = x;
22
23#if BYTE_ORDER == LITTLE_ENDIAN 15#if BYTE_ORDER == LITTLE_ENDIAN
24 u_char *s = (u_char *)&y; 16 u_char *s = (u_char *)&x;
25 return s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3]; 17 return (u_int32_t)(s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3]);
26#else 18#else
27 return y; 19 return x;
28#endif 20#endif
29} 21}
diff --git a/src/lib/libc/net/ntohs.c b/src/lib/libc/net/ntohs.c
index 93ab83ee4d..8f345e84ad 100644
--- a/src/lib/libc/net/ntohs.c
+++ b/src/lib/libc/net/ntohs.c
@@ -1,26 +1,20 @@
1/* $NetBSD: ntohs.c,v 1.5 1995/04/28 23:25:23 jtc Exp $ */ 1/* $OpenBSD: ntohs.c,v 1.8 2005/08/06 20:30:03 espie Exp $ */
2
3/* 2/*
4 * Written by J.T. Conklin <jtc@netbsd.org>. 3 * Written by J.T. Conklin <jtc@netbsd.org>.
5 * Public domain. 4 * Public domain.
6 */ 5 */
7 6
8#if defined(LIBC_SCCS) && !defined(lint)
9static char *rcsid = "$NetBSD: ntohs.c,v 1.5 1995/04/28 23:25:23 jtc Exp $";
10#endif
11
12#include <sys/types.h> 7#include <sys/types.h>
13#include <machine/endian.h> 8#include <machine/endian.h>
14 9
15#undef ntohs 10#undef ntohs
16 11
17unsigned short 12u_int16_t
18ntohs(x) 13ntohs(u_int16_t x)
19 unsigned short x;
20{ 14{
21#if BYTE_ORDER == LITTLE_ENDIAN 15#if BYTE_ORDER == LITTLE_ENDIAN
22 u_char *s = (u_char *) &x; 16 u_char *s = (u_char *) &x;
23 return s[0] << 8 | s[1]; 17 return (u_int16_t)(s[0] << 8 | s[1]);
24#else 18#else
25 return x; 19 return x;
26#endif 20#endif
diff --git a/src/lib/libc/net/rcmd.3 b/src/lib/libc/net/rcmd.3
index 4db847c392..87e9a760a8 100644
--- a/src/lib/libc/net/rcmd.3
+++ b/src/lib/libc/net/rcmd.3
@@ -1,4 +1,4 @@
1.\" $NetBSD: rcmd.3,v 1.8 1995/02/25 06:20:52 cgd Exp $ 1.\" $OpenBSD: rcmd.3,v 1.27 2007/05/31 19:19:30 jmc Exp $
2.\" 2.\"
3.\" Copyright (c) 1983, 1991, 1993 3.\" Copyright (c) 1983, 1991, 1993
4.\" The Regents of the University of California. All rights reserved. 4.\" The Regents of the University of California. All rights reserved.
@@ -11,11 +11,7 @@
11.\" 2. Redistributions in binary form must reproduce the above copyright 11.\" 2. Redistributions in binary form must reproduce the above copyright
12.\" notice, this list of conditions and the following disclaimer in the 12.\" notice, this list of conditions and the following disclaimer in the
13.\" documentation and/or other materials provided with the distribution. 13.\" documentation and/or other materials provided with the distribution.
14.\" 3. All advertising materials mentioning features or use of this software 14.\" 3. Neither the name of the University nor the names of its contributors
15.\" must display the following acknowledgement:
16.\" This product includes software developed by the University of
17.\" California, Berkeley and its contributors.
18.\" 4. Neither the name of the University nor the names of its contributors
19.\" may be used to endorse or promote products derived from this software 15.\" may be used to endorse or promote products derived from this software
20.\" without specific prior written permission. 16.\" without specific prior written permission.
21.\" 17.\"
@@ -31,38 +27,67 @@
31.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32.\" SUCH DAMAGE. 28.\" SUCH DAMAGE.
33.\" 29.\"
34.\" @(#)rcmd.3 8.1 (Berkeley) 6/4/93 30.Dd $Mdocdate: May 31 2007 $
35.\"
36.Dd June 4, 1993
37.Dt RCMD 3 31.Dt RCMD 3
38.Os BSD 4.2 32.Os
39.Sh NAME 33.Sh NAME
40.Nm rcmd , 34.Nm rcmd ,
35.Nm rcmd_af ,
41.Nm rresvport , 36.Nm rresvport ,
37.Nm rresvport_af ,
42.Nm iruserok , 38.Nm iruserok ,
43.Nm ruserok 39.Nm ruserok ,
40.Nm iruserok_sa
44.Nd routines for returning a stream to a remote command 41.Nd routines for returning a stream to a remote command
45.Sh SYNOPSIS 42.Sh SYNOPSIS
46.Fd #include <unistd.h> 43.Fd #include <unistd.h>
47.Ft int 44.Ft int
48.Fn rcmd "char **ahost" "int inport" "const char *locuser" "const char *remuser" "const char *cmd" "int *fd2p" 45.Fn rcmd "char **ahost" "int inport" "const char *locuser" "const char *remuser" "const char *cmd" "int *fd2p"
49.Ft int 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
50.Fn rresvport "int *port" 49.Fn rresvport "int *port"
51.Ft int 50.Ft int
52.Fn iruserok "u_long raddr" "int superuser" "const char *ruser" "const char *luser" 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"
53.Ft int 54.Ft int
54.Fn ruserok "const char *rhost" "int superuser" "const char *ruser" "const char *luser" 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"
55.Sh DESCRIPTION 58.Sh DESCRIPTION
56The 59The
57.Fn rcmd 60.Fn rcmd
58function 61function is used by the superuser to execute a command on a remote
59is used by the super-user to execute a command on 62machine using an authentication scheme based on reserved
60a remote machine using an authentication scheme based 63port numbers.
61on reserved port 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
62The 86The
63.Fn rresvport 87.Fn rresvport
64function 88and
65returns a descriptor to a socket 89.Fn rresvport_af
90functions return a descriptor to a socket
66with an address in the privileged port space. 91with an address in the privileged port space.
67The 92The
68.Fn iruserok 93.Fn iruserok
@@ -75,11 +100,13 @@ All four functions are present in the same file and are used
75by the 100by the
76.Xr rshd 8 101.Xr rshd 8
77server (among others). 102server (among others).
103.Fn iruserok_sa
104is an address family independent variant of
105.Fn iruserok .
78.Pp 106.Pp
79The 107The
80.Fn rcmd 108.Fn rcmd
81function 109function looks up the host
82looks up the host
83.Fa *ahost 110.Fa *ahost
84using 111using
85.Xr gethostbyname 3 , 112.Xr gethostbyname 3 ,
@@ -90,15 +117,15 @@ is set to the standard name of the host
90and a connection is established to a server 117and a connection is established to a server
91residing at the well-known Internet port 118residing at the well-known Internet port
92.Fa inport . 119.Fa inport .
120If the user is not the superuser, the only valid port is
121.Dq shell/tcp
122(usually port 514).
93.Pp 123.Pp
94If the connection succeeds, 124If the connection succeeds,
95a socket in the Internet domain of type 125a socket in the Internet domain of type
96.Dv SOCK_STREAM 126.Dv SOCK_STREAM
97is returned to the caller, and given to the remote 127is returned to the caller, and given to the remote
98command as 128command as stdin and stdout.
99.Em stdin
100and
101.Em stdout .
102If 129If
103.Fa fd2p 130.Fa fd2p
104is non-zero, then an auxiliary channel to a control 131is non-zero, then an auxiliary channel to a control
@@ -113,27 +140,46 @@ signal numbers, to be
113forwarded to the process group of the command. 140forwarded to the process group of the command.
114If 141If
115.Fa fd2p 142.Fa fd2p
116is 0, then the 143is
117.Em stderr 144.Va NULL ,
118(unit 2 of the remote 145then the standard error (unit 2 of the remote command) will be made
119command) will be made the same as the 146the same as the standard output and no provision is made for sending
120.Em stdout 147arbitrary signals to the remote process, although you may be able to
121and no 148get its attention by using out-of-band data.
122provision is made for sending arbitrary signals to the remote process, 149Note that if the user is not the superuser,
123although you may be able to get its attention by using out-of-band data. 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.
124.Pp 161.Pp
125The protocol is described in detail in 162The protocol is described in detail in
126.Xr rshd 8 . 163.Xr rshd 8 .
127.Pp 164.Pp
128The 165The
129.Fn rresvport 166.Fn rresvport
130function is used to obtain a socket with a privileged 167and
131address bound to it. This socket is suitable for use 168.Fn rresvport_af
132by 169functions are used to obtain a socket with a privileged
170address bound to it.
171This socket is suitable for use by
133.Fn rcmd 172.Fn rcmd
134and several other functions. Privileged Internet ports are those 173and several other functions.
135in the range 0 to 1023. Only the super-user 174Privileged Internet ports are those in the range 0 to
136is allowed to bind an address of this sort to a socket. 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.
137.Pp 183.Pp
138The 184The
139.Fn iruserok 185.Fn iruserok
@@ -141,10 +187,10 @@ and
141.Fn ruserok 187.Fn ruserok
142functions take a remote host's IP address or name, respectively, 188functions take a remote host's IP address or name, respectively,
143two user names and a flag indicating whether the local user's 189two user names and a flag indicating whether the local user's
144name is that of the super-user. 190name is that of the superuser.
145Then, if the user is 191Then, if the user is
146.Em NOT 192.Em not
147the super-user, it checks the 193the superuser, it checks the
148.Pa /etc/hosts.equiv 194.Pa /etc/hosts.equiv
149file. 195file.
150If that lookup is not done, or is unsuccessful, the 196If that lookup is not done, or is unsuccessful, the
@@ -153,19 +199,19 @@ in the local user's home directory is checked to see if the request for
153service is allowed. 199service is allowed.
154.Pp 200.Pp
155If this file does not exist, is not a regular file, is owned by anyone 201If this file does not exist, is not a regular file, is owned by anyone
156other than the user or the super-user, or is writeable by anyone other 202other than the user or the superuser, or is writeable by anyone other
157than the owner, the check automatically fails. 203than the owner, the check automatically fails.
158Zero is returned if the machine name is listed in the 204Zero is returned if the machine name is listed in the
159.Dq Pa hosts.equiv 205.Pa hosts.equiv
160file, or the host and remote user name are found in the 206file, or the host and remote user name are found in the
161.Dq Pa .rhosts 207.Pa .rhosts
162file; otherwise 208file; otherwise
163.Fn iruserok 209.Fn iruserok
164and 210and
165.Fn ruserok 211.Fn ruserok
166return \-1. 212return \-1.
167If the local domain (as obtained from 213If the local domain (as obtained from
168.Xr gethostname 2 ) 214.Xr gethostname 3 )
169is the same as the remote domain, only the machine name need be specified. 215is the same as the remote domain, only the machine name need be specified.
170.Pp 216.Pp
171If the IP address of the remote host is known, 217If the IP address of the remote host is known,
@@ -173,32 +219,48 @@ If the IP address of the remote host is known,
173should be used in preference to 219should be used in preference to
174.Fn ruserok , 220.Fn ruserok ,
175as it does not require trusting the DNS server for the remote host's domain. 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 .
176.Sh DIAGNOSTICS 238.Sh DIAGNOSTICS
177The 239The
178.Fn rcmd 240.Fn rcmd
179function 241function returns a valid socket descriptor on success.
180returns a valid socket descriptor on success.
181It returns \-1 on error and prints a diagnostic message on the standard error. 242It returns \-1 on error and prints a diagnostic message on the standard error.
182.Pp 243.Pp
183The 244The
184.Fn rresvport 245.Fn rresvport
185function 246and
186returns a valid, bound socket descriptor on success. 247.Fn rresvport_af
248functions return a valid, bound socket descriptor on success.
187It returns \-1 on error with the global value 249It returns \-1 on error with the global value
188.Va errno 250.Va errno
189set according to the reason for failure. 251set according to the reason for failure.
190The error code 252The error code
191.Dv EAGAIN 253.Er EAGAIN
192is overloaded to mean ``All network ports in use.'' 254is overloaded to mean
255.Dq all network ports in use .
193.Sh SEE ALSO 256.Sh SEE ALSO
194.Xr rlogin 1 ,
195.Xr rsh 1 , 257.Xr rsh 1 ,
196.Xr intro 2 , 258.Xr intro 2 ,
197.Xr rexec 3 , 259.Xr bindresvport 3 ,
198.Xr rexecd 8 , 260.Xr bindresvport_sa 3 ,
199.Xr rlogind 8 , 261.Xr rcmdsh 3 ,
200.Xr rshd 8 262.Xr rshd 8
201.Sh HISTORY 263.Sh HISTORY
202These 264These
203functions appeared in 265functions appeared in
204.Bx 4.2 . 266.Bx 4.2 .
diff --git a/src/lib/libc/net/rcmd.c b/src/lib/libc/net/rcmd.c
index e0310031b0..d566e0ca4c 100644
--- a/src/lib/libc/net/rcmd.c
+++ b/src/lib/libc/net/rcmd.c
@@ -1,6 +1,5 @@
1/* $NetBSD: rcmd.c,v 1.12 1995/06/03 22:33:34 mycroft Exp $ */
2
3/* 1/*
2 * Copyright (c) 1995, 1996, 1998 Theo de Raadt. All rights reserved.
4 * Copyright (c) 1983, 1993, 1994 3 * Copyright (c) 1983, 1993, 1994
5 * The Regents of the University of California. All rights reserved. 4 * The Regents of the University of California. All rights reserved.
6 * 5 *
@@ -12,11 +11,7 @@
12 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software 14 * 3. Neither the name of the University nor the names of its contributors
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software 15 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission. 16 * without specific prior written permission.
22 * 17 *
@@ -33,14 +28,6 @@
33 * SUCH DAMAGE. 28 * SUCH DAMAGE.
34 */ 29 */
35 30
36#if defined(LIBC_SCCS) && !defined(lint)
37#if 0
38static char sccsid[] = "@(#)rcmd.c 8.3 (Berkeley) 3/26/94";
39#else
40static char *rcsid = "$NetBSD: rcmd.c,v 1.12 1995/06/03 22:33:34 mycroft Exp $";
41#endif
42#endif /* LIBC_SCCS and not lint */
43
44#include <sys/param.h> 31#include <sys/param.h>
45#include <sys/socket.h> 32#include <sys/socket.h>
46#include <sys/stat.h> 33#include <sys/stat.h>
@@ -57,35 +44,77 @@ static char *rcsid = "$NetBSD: rcmd.c,v 1.12 1995/06/03 22:33:34 mycroft Exp $";
57#include <stdio.h> 44#include <stdio.h>
58#include <ctype.h> 45#include <ctype.h>
59#include <string.h> 46#include <string.h>
47#include <syslog.h>
48#include <stdlib.h>
60 49
61int __ivaliduser __P((FILE *, u_long, const char *, const char *)); 50int
62static int __icheckhost __P((u_long, const char *)); 51rcmd(char **ahost, int rport, const char *locuser, const char *remuser,
52 const char *cmd, int *fd2p)
53{
54 return rcmd_af(ahost, rport, locuser, remuser, cmd, fd2p, AF_INET);
55}
63 56
64int 57int
65rcmd(ahost, rport, locuser, remuser, cmd, fd2p) 58rcmd_af(char **ahost, int porta, const char *locuser, const char *remuser,
66 char **ahost; 59 const char *cmd, int *fd2p, int af)
67 u_short rport;
68 const char *locuser, *remuser, *cmd;
69 int *fd2p;
70{ 60{
71 struct hostent *hp; 61 static char hbuf[MAXHOSTNAMELEN];
72 struct sockaddr_in sin, from; 62 char pbuf[NI_MAXSERV];
73 fd_set reads; 63 struct addrinfo hints, *res, *r;
74 long oldmask; 64 int error;
65 struct sockaddr_storage from;
66 fd_set *readsp = NULL;
67 sigset_t oldmask, mask;
75 pid_t pid; 68 pid_t pid;
76 int s, lport, timo; 69 int s, lport, timo;
77 char c; 70 char c, *p;
71 int refused;
72 in_port_t rport = porta;
73
74 /* call rcmdsh() with specified remote shell if appropriate. */
75 if (!issetugid() && (p = getenv("RSH")) && *p) {
76 struct servent *sp = getservbyname("shell", "tcp");
77
78 if (sp && sp->s_port == rport)
79 return (rcmdsh(ahost, rport, locuser, remuser,
80 cmd, p));
81 }
82
83 /* use rsh(1) if non-root and remote port is shell. */
84 if (geteuid()) {
85 struct servent *sp = getservbyname("shell", "tcp");
86
87 if (sp && sp->s_port == rport)
88 return (rcmdsh(ahost, rport, locuser, remuser,
89 cmd, NULL));
90 }
78 91
79 pid = getpid(); 92 pid = getpid();
80 hp = gethostbyname(*ahost); 93 snprintf(pbuf, sizeof(pbuf), "%u", ntohs(rport));
81 if (hp == NULL) { 94 memset(&hints, 0, sizeof(hints));
82 herror(*ahost); 95 hints.ai_family = af;
96 hints.ai_socktype = SOCK_STREAM;
97 hints.ai_flags = AI_CANONNAME;
98 error = getaddrinfo(*ahost, pbuf, &hints, &res);
99 if (error) {
100#if 0
101 warnx("%s: %s", *ahost, gai_strerror(error));
102#endif
83 return (-1); 103 return (-1);
84 } 104 }
85 *ahost = hp->h_name; 105 if (res->ai_canonname) {
86 oldmask = sigblock(sigmask(SIGURG)); 106 strlcpy(hbuf, res->ai_canonname, sizeof(hbuf));
107 *ahost = hbuf;
108 } else
109 ; /*XXX*/
110
111 r = res;
112 refused = 0;
113 sigemptyset(&mask);
114 sigaddset(&mask, SIGURG);
115 sigprocmask(SIG_BLOCK, &mask, &oldmask);
87 for (timo = 1, lport = IPPORT_RESERVED - 1;;) { 116 for (timo = 1, lport = IPPORT_RESERVED - 1;;) {
88 s = rresvport(&lport); 117 s = rresvport_af(&lport, r->ai_family);
89 if (s < 0) { 118 if (s < 0) {
90 if (errno == EAGAIN) 119 if (errno == EAGAIN)
91 (void)fprintf(stderr, 120 (void)fprintf(stderr,
@@ -93,54 +122,84 @@ rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
93 else 122 else
94 (void)fprintf(stderr, "rcmd: socket: %s\n", 123 (void)fprintf(stderr, "rcmd: socket: %s\n",
95 strerror(errno)); 124 strerror(errno));
96 sigsetmask(oldmask); 125 if (r->ai_next) {
97 return (-1); 126 r = r->ai_next;
127 continue;
128 } else {
129 sigprocmask(SIG_SETMASK, &oldmask, NULL);
130 freeaddrinfo(res);
131 return (-1);
132 }
98 } 133 }
99 fcntl(s, F_SETOWN, pid); 134 fcntl(s, F_SETOWN, pid);
100 sin.sin_len = sizeof(struct sockaddr_in); 135 if (connect(s, r->ai_addr, r->ai_addrlen) >= 0)
101 sin.sin_family = hp->h_addrtype;
102 sin.sin_port = rport;
103 bcopy(hp->h_addr_list[0], &sin.sin_addr, hp->h_length);
104 if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0)
105 break; 136 break;
106 (void)close(s); 137 (void)close(s);
107 if (errno == EADDRINUSE) { 138 if (errno == EADDRINUSE) {
108 lport--; 139 lport--;
109 continue; 140 continue;
110 } 141 }
111 if (errno == ECONNREFUSED && timo <= 16) { 142 if (errno == ECONNREFUSED)
112 (void)sleep(timo); 143 refused++;
113 timo *= 2; 144 if (r->ai_next) {
114 continue;
115 }
116 if (hp->h_addr_list[1] != NULL) {
117 int oerrno = errno; 145 int oerrno = errno;
118 146 char hbuf[NI_MAXHOST];
119 (void)fprintf(stderr, "connect to address %s: ", 147 const int niflags = NI_NUMERICHOST;
120 inet_ntoa(sin.sin_addr)); 148
149 hbuf[0] = '\0';
150 if (getnameinfo(r->ai_addr, r->ai_addrlen,
151 hbuf, sizeof(hbuf), NULL, 0, niflags) != 0)
152 strlcpy(hbuf, "(invalid)", sizeof hbuf);
153 (void)fprintf(stderr, "connect to address %s: ", hbuf);
121 errno = oerrno; 154 errno = oerrno;
122 perror(0); 155 perror(0);
123 hp->h_addr_list++; 156 r = r->ai_next;
124 bcopy(hp->h_addr_list[0], &sin.sin_addr, hp->h_length); 157 hbuf[0] = '\0';
125 (void)fprintf(stderr, "Trying %s...\n", 158 if (getnameinfo(r->ai_addr, r->ai_addrlen,
126 inet_ntoa(sin.sin_addr)); 159 hbuf, sizeof(hbuf), NULL, 0, niflags) != 0)
160 strlcpy(hbuf, "(invalid)", sizeof hbuf);
161 (void)fprintf(stderr, "Trying %s...\n", hbuf);
127 continue; 162 continue;
128 } 163 }
129 (void)fprintf(stderr, "%s: %s\n", hp->h_name, strerror(errno)); 164 if (refused && timo <= 16) {
130 sigsetmask(oldmask); 165 (void)sleep(timo);
166 timo *= 2;
167 r = res;
168 refused = 0;
169 continue;
170 }
171 (void)fprintf(stderr, "%s: %s\n", res->ai_canonname,
172 strerror(errno));
173 sigprocmask(SIG_SETMASK, &oldmask, NULL);
174 freeaddrinfo(res);
131 return (-1); 175 return (-1);
132 } 176 }
177 /* given "af" can be PF_UNSPEC, we need the real af for "s" */
178 af = r->ai_family;
179 freeaddrinfo(res);
180#if 0
181 /*
182 * try to rresvport() to the same port. This will make rresvport()
183 * fail it's first bind, resulting in it choosing a random port.
184 */
133 lport--; 185 lport--;
186#endif
134 if (fd2p == 0) { 187 if (fd2p == 0) {
135 write(s, "", 1); 188 write(s, "", 1);
136 lport = 0; 189 lport = 0;
137 } else { 190 } else {
138 char num[8]; 191 char num[8];
139 int s2 = rresvport(&lport), s3; 192 int s2 = rresvport_af(&lport, af), s3;
140 int len = sizeof(from); 193 socklen_t len = sizeof(from);
194 int fdssize = howmany(MAX(s, s2)+1, NFDBITS) * sizeof(fd_mask);
141 195
142 if (s2 < 0) 196 if (s2 < 0)
143 goto bad; 197 goto bad;
198 readsp = (fd_set *)malloc(fdssize);
199 if (readsp == NULL) {
200 close(s2);
201 goto bad;
202 }
144 listen(s2, 1); 203 listen(s2, 1);
145 (void)snprintf(num, sizeof(num), "%d", lport); 204 (void)snprintf(num, sizeof(num), "%d", lport);
146 if (write(s, num, strlen(num)+1) != strlen(num)+1) { 205 if (write(s, num, strlen(num)+1) != strlen(num)+1) {
@@ -150,12 +209,13 @@ rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
150 (void)close(s2); 209 (void)close(s2);
151 goto bad; 210 goto bad;
152 } 211 }
153 FD_ZERO(&reads); 212again:
154 FD_SET(s, &reads); 213 bzero(readsp, fdssize);
155 FD_SET(s2, &reads); 214 FD_SET(s, readsp);
215 FD_SET(s2, readsp);
156 errno = 0; 216 errno = 0;
157 if (select(MAX(s, s2) + 1, &reads, 0, 0, 0) < 1 || 217 if (select(MAX(s, s2) + 1, readsp, 0, 0, 0) < 1 ||
158 !FD_ISSET(s2, &reads)) { 218 !FD_ISSET(s2, readsp)) {
159 if (errno != 0) 219 if (errno != 0)
160 (void)fprintf(stderr, 220 (void)fprintf(stderr,
161 "rcmd: select (setting up stderr): %s\n", 221 "rcmd: select (setting up stderr): %s\n",
@@ -167,21 +227,48 @@ rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
167 goto bad; 227 goto bad;
168 } 228 }
169 s3 = accept(s2, (struct sockaddr *)&from, &len); 229 s3 = accept(s2, (struct sockaddr *)&from, &len);
170 (void)close(s2);
171 if (s3 < 0) { 230 if (s3 < 0) {
172 (void)fprintf(stderr, 231 (void)fprintf(stderr,
173 "rcmd: accept: %s\n", strerror(errno)); 232 "rcmd: accept: %s\n", strerror(errno));
174 lport = 0; 233 lport = 0;
234 close(s2);
175 goto bad; 235 goto bad;
176 } 236 }
237
238 /*
239 * XXX careful for ftp bounce attacks. If discovered, shut them
240 * down and check for the real auxiliary channel to connect.
241 */
242 switch (from.ss_family) {
243 case AF_INET:
244 case AF_INET6:
245 if (getnameinfo((struct sockaddr *)&from, len,
246 NULL, 0, num, sizeof(num), NI_NUMERICSERV) == 0 &&
247 atoi(num) != 20) {
248 break;
249 }
250 close(s3);
251 goto again;
252 default:
253 break;
254 }
255 (void)close(s2);
256
177 *fd2p = s3; 257 *fd2p = s3;
178 from.sin_port = ntohs(from.sin_port); 258 switch (from.ss_family) {
179 if (from.sin_family != AF_INET || 259 case AF_INET:
180 from.sin_port >= IPPORT_RESERVED || 260 case AF_INET6:
181 from.sin_port < IPPORT_RESERVED / 2) { 261 if (getnameinfo((struct sockaddr *)&from, len,
182 (void)fprintf(stderr, 262 NULL, 0, num, sizeof(num), NI_NUMERICSERV) != 0 ||
183 "socket: protocol failure in circuit setup.\n"); 263 (atoi(num) >= IPPORT_RESERVED ||
184 goto bad2; 264 atoi(num) < IPPORT_RESERVED / 2)) {
265 (void)fprintf(stderr,
266 "socket: protocol failure in circuit setup.\n");
267 goto bad2;
268 }
269 break;
270 default:
271 break;
185 } 272 }
186 } 273 }
187 (void)write(s, locuser, strlen(locuser)+1); 274 (void)write(s, locuser, strlen(locuser)+1);
@@ -200,318 +287,17 @@ rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
200 } 287 }
201 goto bad2; 288 goto bad2;
202 } 289 }
203 sigsetmask(oldmask); 290 sigprocmask(SIG_SETMASK, &oldmask, NULL);
291 free(readsp);
204 return (s); 292 return (s);
205bad2: 293bad2:
206 if (lport) 294 if (lport)
207 (void)close(*fd2p); 295 (void)close(*fd2p);
208bad: 296bad:
297 if (readsp)
298 free(readsp);
209 (void)close(s); 299 (void)close(s);
210 sigsetmask(oldmask); 300 sigprocmask(SIG_SETMASK, &oldmask, NULL);
211 return (-1);
212}
213
214int
215rresvport(alport)
216 int *alport;
217{
218 struct sockaddr_in sin;
219 int s;
220
221 sin.sin_len = sizeof(struct sockaddr_in);
222 sin.sin_family = AF_INET;
223 sin.sin_addr.s_addr = INADDR_ANY;
224 s = socket(AF_INET, SOCK_STREAM, 0);
225 if (s < 0)
226 return (-1);
227 for (;;) {
228 sin.sin_port = htons((u_short)*alport);
229 if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0)
230 return (s);
231 if (errno != EADDRINUSE) {
232 (void)close(s);
233 return (-1);
234 }
235 (*alport)--;
236 if (*alport == IPPORT_RESERVED/2) {
237 (void)close(s);
238 errno = EAGAIN; /* close */
239 return (-1);
240 }
241 }
242}
243
244int __check_rhosts_file = 1;
245char *__rcmd_errstr;
246
247int
248ruserok(rhost, superuser, ruser, luser)
249 const char *rhost, *ruser, *luser;
250 int superuser;
251{
252 struct hostent *hp;
253 char **ap;
254 int i;
255#define MAXADDRS 35
256 u_long addrs[MAXADDRS + 1];
257
258 if ((hp = gethostbyname(rhost)) == NULL)
259 return (-1);
260 for (i = 0, ap = hp->h_addr_list; *ap && i < MAXADDRS; ++ap, ++i)
261 bcopy(*ap, &addrs[i], sizeof(addrs[i]));
262 addrs[i] = 0;
263
264 for (i = 0; i < MAXADDRS && addrs[i]; i++)
265 if (iruserok(addrs[i], superuser, ruser, luser) == 0)
266 return (0);
267 return (-1);
268}
269
270/*
271 * New .rhosts strategy: We are passed an ip address. We spin through
272 * hosts.equiv and .rhosts looking for a match. When the .rhosts only
273 * has ip addresses, we don't have to trust a nameserver. When it
274 * contains hostnames, we spin through the list of addresses the nameserver
275 * gives us and look for a match.
276 *
277 * Returns 0 if ok, -1 if not ok.
278 */
279int
280iruserok(raddr, superuser, ruser, luser)
281 u_long raddr;
282 int superuser;
283 const char *ruser, *luser;
284{
285 register char *cp;
286 struct stat sbuf;
287 struct passwd *pwd;
288 FILE *hostf;
289 uid_t uid;
290 int first;
291 char pbuf[MAXPATHLEN];
292
293 first = 1;
294 hostf = superuser ? NULL : fopen(_PATH_HEQUIV, "r");
295again:
296 if (hostf) {
297 if (__ivaliduser(hostf, raddr, luser, ruser) == 0) {
298 (void)fclose(hostf);
299 return (0);
300 }
301 (void)fclose(hostf);
302 }
303 if (first == 1 && (__check_rhosts_file || superuser)) {
304 first = 0;
305 if ((pwd = getpwnam(luser)) == NULL)
306 return (-1);
307 (void)strcpy(pbuf, pwd->pw_dir);
308 (void)strcat(pbuf, "/.rhosts");
309
310 /*
311 * Change effective uid while opening .rhosts. If root and
312 * reading an NFS mounted file system, can't read files that
313 * are protected read/write owner only.
314 */
315 uid = geteuid();
316 (void)seteuid(pwd->pw_uid);
317 hostf = fopen(pbuf, "r");
318 (void)seteuid(uid);
319
320 if (hostf == NULL)
321 return (-1);
322 /*
323 * If not a regular file, or is owned by someone other than
324 * user or root or if writeable by anyone but the owner, quit.
325 */
326 cp = NULL;
327 if (lstat(pbuf, &sbuf) < 0)
328 cp = ".rhosts lstat failed";
329 else if (!S_ISREG(sbuf.st_mode))
330 cp = ".rhosts not regular file";
331 else if (fstat(fileno(hostf), &sbuf) < 0)
332 cp = ".rhosts fstat failed";
333 else if (sbuf.st_uid && sbuf.st_uid != pwd->pw_uid)
334 cp = "bad .rhosts owner";
335 else if (sbuf.st_mode & (S_IWGRP|S_IWOTH))
336 cp = ".rhosts writeable by other than owner";
337 /* If there were any problems, quit. */
338 if (cp) {
339 __rcmd_errstr = cp;
340 (void)fclose(hostf);
341 return (-1);
342 }
343 goto again;
344 }
345 return (-1); 301 return (-1);
346} 302}
347 303
348/*
349 * XXX
350 * Don't make static, used by lpd(8).
351 *
352 * Returns 0 if ok, -1 if not ok.
353 */
354int
355__ivaliduser(hostf, raddr, luser, ruser)
356 FILE *hostf;
357 u_long raddr;
358 const char *luser, *ruser;
359{
360 register char *user, *p;
361 int ch;
362 char buf[MAXHOSTNAMELEN + 128]; /* host + login */
363 const char *auser, *ahost;
364 int hostok, userok;
365 char rhost[MAXHOSTNAMELEN];
366 struct hostent *hp;
367 char domain[MAXHOSTNAMELEN];
368
369 getdomainname(domain, sizeof(domain));
370
371 while (fgets(buf, sizeof(buf), hostf)) {
372 p = buf;
373 /* Skip lines that are too long. */
374 if (strchr(p, '\n') == NULL) {
375 while ((ch = getc(hostf)) != '\n' && ch != EOF);
376 continue;
377 }
378 while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') {
379 *p = isupper(*p) ? tolower(*p) : *p;
380 p++;
381 }
382 if (*p == ' ' || *p == '\t') {
383 *p++ = '\0';
384 while (*p == ' ' || *p == '\t')
385 p++;
386 user = p;
387 while (*p != '\n' && *p != ' ' &&
388 *p != '\t' && *p != '\0')
389 p++;
390 } else
391 user = p;
392 *p = '\0';
393
394 if (p == buf)
395 continue;
396
397 auser = *user ? user : luser;
398 ahost = buf;
399
400 if ((hp = gethostbyaddr((char *) &raddr,
401 sizeof(raddr), AF_INET)) == NULL) {
402 abort();
403 return -1;
404 }
405 (void) strncpy(rhost, hp->h_name, sizeof(rhost));
406 rhost[sizeof(rhost) - 1] = '\0';
407
408 if (ahost[0] == '+')
409 switch (ahost[1]) {
410 case '\0':
411 hostok = 1;
412 break;
413
414 case '@':
415 hostok = innetgr(&ahost[2], rhost, NULL,
416 domain);
417 break;
418
419 default:
420 hostok = __icheckhost(raddr, &ahost[1]);
421 break;
422 }
423 else if (ahost[0] == '-')
424 switch (ahost[1]) {
425 case '\0':
426 hostok = -1;
427 break;
428
429 case '@':
430 hostok = -innetgr(&ahost[2], rhost, NULL,
431 domain);
432 break;
433
434 default:
435 hostok = -__icheckhost(raddr, &ahost[1]);
436 break;
437 }
438 else
439 hostok = __icheckhost(raddr, ahost);
440
441
442 if (auser[0] == '+')
443 switch (auser[1]) {
444 case '\0':
445 userok = 1;
446 break;
447
448 case '@':
449 userok = innetgr(&auser[2], NULL, ruser,
450 domain);
451 break;
452
453 default:
454 userok = strcmp(ruser, &auser[1]) == 0;
455 break;
456 }
457 else if (auser[0] == '-')
458 switch (auser[1]) {
459 case '\0':
460 userok = -1;
461 break;
462
463 case '@':
464 userok = -innetgr(&auser[2], NULL, ruser,
465 domain);
466 break;
467
468 default:
469 userok = -(strcmp(ruser, &auser[1]) == 0);
470 break;
471 }
472 else
473 userok = strcmp(ruser, auser) == 0;
474
475 /* Check if one component did not match */
476 if (hostok == 0 || userok == 0)
477 continue;
478
479 /* Check if we got a forbidden pair */
480 if (userok == -1 || hostok == -1)
481 return -1;
482
483 /* Check if we got a valid pair */
484 if (hostok == 1 && userok == 1)
485 return 0;
486 }
487 return -1;
488}
489
490/*
491 * Returns "true" if match, 0 if no match.
492 */
493static int
494__icheckhost(raddr, lhost)
495 u_long raddr;
496 const char *lhost;
497{
498 register struct hostent *hp;
499 register u_long laddr;
500 register char **pp;
501
502 /* Try for raw ip address first. */
503 if (isdigit(*lhost) && (long)(laddr = inet_addr(lhost)) != -1)
504 return (raddr == laddr);
505
506 /* Better be a hostname. */
507 if ((hp = gethostbyname(lhost)) == NULL)
508 return (0);
509
510 /* Spin through ip addresses. */
511 for (pp = hp->h_addr_list; *pp; ++pp)
512 if (!bcmp(&raddr, *pp, sizeof(u_long)))
513 return (1);
514
515 /* No match. */
516 return (0);
517}
diff --git a/src/lib/libc/net/rcmdsh.3 b/src/lib/libc/net/rcmdsh.3
new file mode 100644
index 0000000000..f7de0808f5
--- /dev/null
+++ b/src/lib/libc/net/rcmdsh.3
@@ -0,0 +1,96 @@
1.\" $OpenBSD: rcmdsh.3,v 1.13 2009/12/29 10:25:43 sobrado 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 $Mdocdate: December 29 2009 $
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.Ux Ns -domain
74of 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..a472162711
--- /dev/null
+++ b/src/lib/libc/net/rcmdsh.c
@@ -0,0 +1,186 @@
1/* $OpenBSD: rcmdsh.c,v 1.12 2007/09/02 15:19:17 deraadt 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 = calloc(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
index 44296378cb..6241cc6b12 100644
--- a/src/lib/libc/net/recv.c
+++ b/src/lib/libc/net/recv.c
@@ -1,5 +1,4 @@
1/* $NetBSD: recv.c,v 1.6 1995/02/25 06:20:54 cgd Exp $ */ 1/* $OpenBSD: recv.c,v 1.5 2005/08/06 20:30:03 espie Exp $ */
2
3/* 2/*
4 * Copyright (c) 1988, 1993 3 * Copyright (c) 1988, 1993
5 * The Regents of the University of California. All rights reserved. 4 * The Regents of the University of California. All rights reserved.
@@ -12,11 +11,7 @@
12 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software 14 * 3. Neither the name of the University nor the names of its contributors
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software 15 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission. 16 * without specific prior written permission.
22 * 17 *
@@ -33,24 +28,13 @@
33 * SUCH DAMAGE. 28 * SUCH DAMAGE.
34 */ 29 */
35 30
36#if defined(LIBC_SCCS) && !defined(lint)
37#if 0
38static char sccsid[] = "@(#)recv.c 8.2 (Berkeley) 2/21/94";
39#else
40static char rcsid[] = "$NetBSD: recv.c,v 1.6 1995/02/25 06:20:54 cgd Exp $";
41#endif
42#endif /* LIBC_SCCS and not lint */
43
44#include <sys/types.h> 31#include <sys/types.h>
45#include <sys/socket.h> 32#include <sys/socket.h>
46 33
47#include <stddef.h> 34#include <stddef.h>
48 35
49ssize_t 36ssize_t
50recv(s, buf, len, flags) 37recv(int s, void *buf, size_t len, int flags)
51 int s, flags;
52 size_t len;
53 void *buf;
54{ 38{
55 return (recvfrom(s, buf, len, flags, NULL, 0)); 39 return (recvfrom(s, buf, len, flags, NULL, 0));
56} 40}
diff --git a/src/lib/libc/net/res_comp.c b/src/lib/libc/net/res_comp.c
index 9d7bbecdda..69a6ce0abb 100644
--- a/src/lib/libc/net/res_comp.c
+++ b/src/lib/libc/net/res_comp.c
@@ -1,9 +1,11 @@
1/* $NetBSD: res_comp.c,v 1.6 1995/02/25 06:20:55 cgd Exp $ */ 1/* $OpenBSD: res_comp.c,v 1.14 2008/04/16 22:35:23 deraadt Exp $ */
2 2
3/*- 3/*
4 * ++Copyright++ 1985, 1993
5 * -
4 * Copyright (c) 1985, 1993 6 * Copyright (c) 1985, 1993
5 * The Regents of the University of California. All rights reserved. 7 * The Regents of the University of California. All rights reserved.
6 * 8 *
7 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
9 * are met: 11 * are met:
@@ -12,14 +14,10 @@
12 * 2. Redistributions in binary form must reproduce the above copyright 14 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 15 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 16 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software 17 * 3. Neither the name of the University nor the names of its contributors
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software 18 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission. 19 * without specific prior written permission.
22 * 20 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -53,22 +51,19 @@
53 * --Copyright-- 51 * --Copyright--
54 */ 52 */
55 53
56#if defined(LIBC_SCCS) && !defined(lint) 54#include <sys/types.h>
57#if 0
58static char sccsid[] = "@(#)res_comp.c 8.1 (Berkeley) 6/4/93";
59static char rcsid[] = "$Id: res_comp.c,v 4.9.1.1 1993/05/02 22:43:03 vixie Rel ";
60#else
61static char rcsid[] = "$NetBSD: res_comp.c,v 1.6 1995/02/25 06:20:55 cgd Exp $";
62#endif
63#endif /* LIBC_SCCS and not lint */
64
65#include <sys/param.h> 55#include <sys/param.h>
66#include <arpa/nameser.h>
67#include <netinet/in.h> 56#include <netinet/in.h>
68#include <resolv.h> 57#include <arpa/nameser.h>
58
69#include <stdio.h> 59#include <stdio.h>
60#include <resolv.h>
61#include <ctype.h>
62
63#include <unistd.h>
64#include <string.h>
70 65
71static int dn_find(); 66static int dn_find(u_char *, u_char *, u_char **, u_char **);
72 67
73/* 68/*
74 * Expand compressed domain name 'comp_dn' to full domain name. 69 * Expand compressed domain name 'comp_dn' to full domain name.
@@ -77,23 +72,25 @@ static int dn_find();
77 * 'exp_dn' is a pointer to a buffer of size 'length' for the result. 72 * 'exp_dn' is a pointer to a buffer of size 'length' for the result.
78 * Return size of compressed name or -1 if there was an error. 73 * Return size of compressed name or -1 if there was an error.
79 */ 74 */
80dn_expand(msg, eomorig, comp_dn, exp_dn, length) 75int
81 const u_char *msg, *eomorig, *comp_dn; 76dn_expand(const u_char *msg, const u_char *eomorig, const u_char *comp_dn,
82 u_char *exp_dn; 77 char *exp_dn, int length)
83 int length;
84{ 78{
85 register u_char *cp, *dn; 79 const u_char *cp;
86 register int n, c; 80 char *dn;
87 u_char *eom; 81 int n, c;
82 char *eom;
88 int len = -1, checked = 0; 83 int len = -1, checked = 0;
89 84
90 dn = exp_dn; 85 dn = exp_dn;
91 cp = (u_char *)comp_dn; 86 cp = comp_dn;
87 if (length > MAXHOSTNAMELEN-1)
88 length = MAXHOSTNAMELEN-1;
92 eom = exp_dn + length; 89 eom = exp_dn + length;
93 /* 90 /*
94 * fetch next label in domain name 91 * fetch next label in domain name
95 */ 92 */
96 while (n = *cp++) { 93 while ((n = *cp++)) {
97 /* 94 /*
98 * Check for indirection 95 * Check for indirection
99 */ 96 */
@@ -108,23 +105,23 @@ dn_expand(msg, eomorig, comp_dn, exp_dn, length)
108 return (-1); 105 return (-1);
109 checked += n + 1; 106 checked += n + 1;
110 while (--n >= 0) { 107 while (--n >= 0) {
111 if ((c = *cp++) == '.') { 108 if (((c = *cp++) == '.') || (c == '\\')) {
112 if (dn + n + 2 >= eom) 109 if (dn + n + 2 >= eom)
113 return (-1); 110 return (-1);
114 *dn++ = '\\'; 111 *dn++ = '\\';
115 } 112 }
116 *dn++ = c; 113 *dn++ = c;
117 if (cp >= eomorig) /* out of range */ 114 if (cp >= eomorig) /* out of range */
118 return(-1); 115 return (-1);
119 } 116 }
120 break; 117 break;
121 118
122 case INDIR_MASK: 119 case INDIR_MASK:
123 if (len < 0) 120 if (len < 0)
124 len = cp - comp_dn + 1; 121 len = cp - comp_dn + 1;
125 cp = (u_char *)msg + (((n & 0x3f) << 8) | (*cp & 0xff)); 122 cp = msg + (((n & 0x3f) << 8) | (*cp & 0xff));
126 if (cp < msg || cp >= eomorig) /* out of range */ 123 if (cp < msg || cp >= eomorig) /* out of range */
127 return(-1); 124 return (-1);
128 checked += 2; 125 checked += 2;
129 /* 126 /*
130 * Check for loops in the compressed name; 127 * Check for loops in the compressed name;
@@ -157,19 +154,19 @@ dn_expand(msg, eomorig, comp_dn, exp_dn, length)
157 * If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr' 154 * If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr'
158 * is NULL, we don't update the list. 155 * is NULL, we don't update the list.
159 */ 156 */
160dn_comp(exp_dn, comp_dn, length, dnptrs, lastdnptr) 157int
161 const u_char *exp_dn; 158dn_comp(const char *exp_dn, u_char *comp_dn, int length, u_char **dnptrs,
162 u_char *comp_dn, **dnptrs, **lastdnptr; 159 u_char **lastdnptr)
163 int length;
164{ 160{
165 register u_char *cp, *dn; 161 u_char *cp, *dn;
166 register int c, l; 162 int c, l;
167 u_char **cpp, **lpp, *sp, *eob; 163 u_char **cpp, **lpp, *sp, *eob;
168 u_char *msg; 164 u_char *msg;
169 165
170 dn = (u_char *)exp_dn; 166 dn = (u_char *)exp_dn;
171 cp = comp_dn; 167 cp = comp_dn;
172 eob = cp + length; 168 eob = cp + length;
169 lpp = cpp = NULL;
173 if (dnptrs != NULL) { 170 if (dnptrs != NULL) {
174 if ((msg = *dnptrs++) != NULL) { 171 if ((msg = *dnptrs++) != NULL) {
175 for (cpp = dnptrs; *cpp != NULL; cpp++) 172 for (cpp = dnptrs; *cpp != NULL; cpp++)
@@ -235,13 +232,13 @@ dn_comp(exp_dn, comp_dn, length, dnptrs, lastdnptr)
235/* 232/*
236 * Skip over a compressed domain name. Return the size or -1. 233 * Skip over a compressed domain name. Return the size or -1.
237 */ 234 */
238__dn_skipname(comp_dn, eom) 235int
239 const u_char *comp_dn, *eom; 236__dn_skipname(const u_char *comp_dn, const u_char *eom)
240{ 237{
241 register u_char *cp; 238 const u_char *cp;
242 register int n; 239 int n;
243 240
244 cp = (u_char *)comp_dn; 241 cp = comp_dn;
245 while (cp < eom && (n = *cp++)) { 242 while (cp < eom && (n = *cp++)) {
246 /* 243 /*
247 * check for indirection 244 * check for indirection
@@ -259,10 +256,18 @@ __dn_skipname(comp_dn, eom)
259 break; 256 break;
260 } 257 }
261 if (cp > eom) 258 if (cp > eom)
262 return -1; 259 return (-1);
263 return (cp - comp_dn); 260 return (cp - comp_dn);
264} 261}
265 262
263static int
264mklower(int ch)
265{
266 if (isascii(ch) && isupper(ch))
267 return (tolower(ch));
268 return (ch);
269}
270
266/* 271/*
267 * Search for expanded name from a list of previously compressed names. 272 * Search for expanded name from a list of previously compressed names.
268 * Return the offset from msg if found or -1. 273 * Return the offset from msg if found or -1.
@@ -270,18 +275,16 @@ __dn_skipname(comp_dn, eom)
270 * not the pointer to the start of the message. 275 * not the pointer to the start of the message.
271 */ 276 */
272static int 277static int
273dn_find(exp_dn, msg, dnptrs, lastdnptr) 278dn_find(u_char *exp_dn, u_char *msg, u_char **dnptrs, u_char **lastdnptr)
274 u_char *exp_dn, *msg;
275 u_char **dnptrs, **lastdnptr;
276{ 279{
277 register u_char *dn, *cp, **cpp; 280 u_char *dn, *cp, **cpp;
278 register int n; 281 int n;
279 u_char *sp; 282 u_char *sp;
280 283
281 for (cpp = dnptrs; cpp < lastdnptr; cpp++) { 284 for (cpp = dnptrs; cpp < lastdnptr; cpp++) {
282 dn = exp_dn; 285 dn = exp_dn;
283 sp = cp = *cpp; 286 sp = cp = *cpp;
284 while (n = *cp++) { 287 while ((n = *cp++)) {
285 /* 288 /*
286 * check for indirection 289 * check for indirection
287 */ 290 */
@@ -292,7 +295,7 @@ dn_find(exp_dn, msg, dnptrs, lastdnptr)
292 goto next; 295 goto next;
293 if (*dn == '\\') 296 if (*dn == '\\')
294 dn++; 297 dn++;
295 if (*dn++ != *cp++) 298 if (mklower(*dn++) != mklower(*cp++))
296 goto next; 299 goto next;
297 } 300 }
298 if ((n = *dn++) == '\0' && *cp == '\0') 301 if ((n = *dn++) == '\0' && *cp == '\0')
@@ -301,11 +304,12 @@ dn_find(exp_dn, msg, dnptrs, lastdnptr)
301 continue; 304 continue;
302 goto next; 305 goto next;
303 306
304 default: /* illegal type */
305 return (-1);
306
307 case INDIR_MASK: /* indirection */ 307 case INDIR_MASK: /* indirection */
308 cp = msg + (((n & 0x3f) << 8) | *cp); 308 cp = msg + (((n & 0x3f) << 8) | *cp);
309 break;
310
311 default: /* illegal type */
312 return (-1);
309 } 313 }
310 } 314 }
311 if (*dn == '\0') 315 if (*dn == '\0')
@@ -316,49 +320,156 @@ dn_find(exp_dn, msg, dnptrs, lastdnptr)
316} 320}
317 321
318/* 322/*
319 * Routines to insert/extract short/long's. Must account for byte 323 * Verify that a domain name uses an acceptable character set.
320 * order and non-alignment problems. This code at least has the 324 */
321 * advantage of being portable. 325
322 * 326/*
323 * used by sendmail. 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 underscorechar(c) ((c) == 0x5f)
336#define periodchar(c) ((c) == PERIOD)
337#define asterchar(c) ((c) == 0x2a)
338#define alphachar(c) (((c) >= 0x41 && (c) <= 0x5a) \
339 || ((c) >= 0x61 && (c) <= 0x7a))
340#define digitchar(c) ((c) >= 0x30 && (c) <= 0x39)
341
342#define borderchar(c) (alphachar(c) || digitchar(c))
343#define middlechar(c) (borderchar(c) || hyphenchar(c) || underscorechar(c))
344#define domainchar(c) ((c) > 0x20 && (c) < 0x7f)
345
346int
347res_hnok(const char *dn)
348{
349 int pch = PERIOD, ch = *dn++;
350
351 while (ch != '\0') {
352 int nch = *dn++;
353
354 if (periodchar(ch)) {
355 ;
356 } else if (periodchar(pch)) {
357 if (!borderchar(ch))
358 return (0);
359 } else if (periodchar(nch) || nch == '\0') {
360 if (!borderchar(ch))
361 return (0);
362 } else {
363 if (!middlechar(ch))
364 return (0);
365 }
366 pch = ch, ch = nch;
367 }
368 return (1);
369}
370
371/*
372 * hostname-like (A, MX, WKS) owners can have "*" as their first label
373 * but must otherwise be as a host name.
324 */ 374 */
375int
376res_ownok(const char *dn)
377{
378 if (asterchar(dn[0])) {
379 if (periodchar(dn[1]))
380 return (res_hnok(dn+2));
381 if (dn[1] == '\0')
382 return (1);
383 }
384 return (res_hnok(dn));
385}
325 386
326u_short 387/*
327_getshort(msgp) 388 * SOA RNAMEs and RP RNAMEs can have any printable character in their first
328 register u_char *msgp; 389 * label, but the rest of the name has to look like a host name.
390 */
391int
392res_mailok(const char *dn)
329{ 393{
330 register u_int16_t u; 394 int ch, escaped = 0;
395
396 /* "." is a valid missing representation */
397 if (*dn == '\0')
398 return(1);
399
400 /* otherwise <label>.<hostname> */
401 while ((ch = *dn++) != '\0') {
402 if (!domainchar(ch))
403 return (0);
404 if (!escaped && periodchar(ch))
405 break;
406 if (escaped)
407 escaped = 0;
408 else if (bslashchar(ch))
409 escaped = 1;
410 }
411 if (periodchar(ch))
412 return (res_hnok(dn));
413 return(0);
414}
415
416/*
417 * This function is quite liberal, since RFC 1034's character sets are only
418 * recommendations.
419 */
420int
421res_dnok(const char *dn)
422{
423 int ch;
424
425 while ((ch = *dn++) != '\0')
426 if (!domainchar(ch))
427 return (0);
428 return (1);
429}
430
431/*
432 * Routines to insert/extract short/long's.
433 */
434
435u_int16_t
436_getshort(const u_char *msgp)
437{
438 u_int16_t u;
331 439
332 GETSHORT(u, msgp); 440 GETSHORT(u, msgp);
333 return (u); 441 return (u);
334} 442}
335 443
444#ifdef NeXT
445/*
446 * nExt machines have some funky library conventions, which we must maintain.
447 */
448u_int16_t
449res_getshort(msgp)
450 const u_char *msgp;
451{
452 return (_getshort(msgp));
453}
454#endif
455
336u_int32_t 456u_int32_t
337_getlong(msgp) 457_getlong(const u_char *msgp)
338 register u_char *msgp;
339{ 458{
340 register u_int32_t u; 459 u_int32_t u;
341 460
342 GETLONG(u, msgp); 461 GETLONG(u, msgp);
343 return (u); 462 return (u);
344} 463}
345 464
346void 465void
347#if defined(__STDC__) || defined(__cplusplus) 466__putshort(u_int16_t s, u_char *msgp)
348__putshort(register u_int16_t s, register u_char *msgp)
349#else
350__putshort(s, msgp)
351 register u_int16_t s;
352 register u_char *msgp;
353#endif
354{ 467{
355 PUTSHORT(s, msgp); 468 PUTSHORT(s, msgp);
356} 469}
357 470
358void 471void
359__putlong(l, msgp) 472__putlong(u_int32_t l, u_char *msgp)
360 register u_int32_t l;
361 register u_char *msgp;
362{ 473{
363 PUTLONG(l, msgp); 474 PUTLONG(l, msgp);
364} 475}
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
index d841293f18..246fefef3c 100644
--- a/src/lib/libc/net/res_debug.c
+++ b/src/lib/libc/net/res_debug.c
@@ -1,9 +1,11 @@
1/* $NetBSD: res_debug.c,v 1.7 1995/02/25 06:20:56 cgd Exp $ */ 1/* $OpenBSD: res_debug.c,v 1.22 2007/10/11 18:36:41 jakob Exp $ */
2 2
3/*- 3/*
4 * ++Copyright++ 1985, 1990, 1993
5 * -
4 * Copyright (c) 1985, 1990, 1993 6 * Copyright (c) 1985, 1990, 1993
5 * The Regents of the University of California. All rights reserved. 7 * The Regents of the University of California. All rights reserved.
6 * 8 *
7 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
9 * are met: 11 * are met:
@@ -12,11 +14,7 @@
12 * 2. Redistributions in binary form must reproduce the above copyright 14 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 15 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 16 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software 17 * 3. Neither the name of the University nor the names of its contributors
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software 18 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission. 19 * without specific prior written permission.
22 * 20 *
@@ -50,174 +48,179 @@
50 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 48 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
51 * SOFTWARE. 49 * SOFTWARE.
52 * - 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.
53 * --Copyright-- 73 * --Copyright--
54 */ 74 */
55 75
56#if defined(LIBC_SCCS) && !defined(lint)
57#if 0
58static char sccsid[] = "@(#)res_debug.c 8.1 (Berkeley) 6/4/93";
59#else
60static char rcsid[] = "$NetBSD: res_debug.c,v 1.7 1995/02/25 06:20:56 cgd Exp $";
61#endif
62#endif /* LIBC_SCCS and not lint */
63
64#include <sys/param.h> 76#include <sys/param.h>
77#include <sys/types.h>
78#include <sys/socket.h>
65#include <netinet/in.h> 79#include <netinet/in.h>
66#include <arpa/inet.h> 80#include <arpa/inet.h>
67#include <arpa/nameser.h> 81#include <arpa/nameser.h>
82
83#include <ctype.h>
84#include <netdb.h>
68#include <resolv.h> 85#include <resolv.h>
69#include <stdio.h> 86#include <stdio.h>
87#include <time.h>
88
89#include <stdlib.h>
70#include <string.h> 90#include <string.h>
71 91
72void __fp_query(); 92#include "thread_private.h"
73char *__p_class(), *__p_time(), *__p_type(); 93
74char *p_cdname(), *p_fqname(), *p_rr(); 94extern const char *_res_opcodes[];
75static char *p_option __P((u_int32_t)); 95extern const char *_res_resultcodes[];
76 96
77char *_res_opcodes[] = { 97static const char *loc_ntoal(const u_char *binary, char *ascii, int ascii_len);
78 "QUERY", 98
79 "IQUERY", 99/* XXX: we should use getservbyport() instead. */
80 "CQUERYM", 100static const char *
81 "CQUERYU", 101dewks(int wks)
82 "4",
83 "5",
84 "6",
85 "7",
86 "8",
87 "UPDATEA",
88 "UPDATED",
89 "UPDATEDA",
90 "UPDATEM",
91 "UPDATEMA",
92 "ZONEINIT",
93 "ZONEREF",
94};
95
96char *_res_resultcodes[] = {
97 "NOERROR",
98 "FORMERR",
99 "SERVFAIL",
100 "NXDOMAIN",
101 "NOTIMP",
102 "REFUSED",
103 "6",
104 "7",
105 "8",
106 "9",
107 "10",
108 "11",
109 "12",
110 "13",
111 "14",
112 "NOCHANGE",
113};
114
115static char retbuf[16];
116
117static char *
118dewks(wks)
119 int wks;
120{ 102{
103 static char nbuf[20];
104
121 switch (wks) { 105 switch (wks) {
122 case 5: return("rje"); 106 case 5: return "rje";
123 case 7: return("echo"); 107 case 7: return "echo";
124 case 9: return("discard"); 108 case 9: return "discard";
125 case 11: return("systat"); 109 case 11: return "systat";
126 case 13: return("daytime"); 110 case 13: return "daytime";
127 case 15: return("netstat"); 111 case 15: return "netstat";
128 case 17: return("qotd"); 112 case 17: return "qotd";
129 case 19: return("chargen"); 113 case 19: return "chargen";
130 case 20: return("ftp-data"); 114 case 20: return "ftp-data";
131 case 21: return("ftp"); 115 case 21: return "ftp";
132 case 23: return("telnet"); 116 case 23: return "telnet";
133 case 25: return("smtp"); 117 case 25: return "smtp";
134 case 37: return("time"); 118 case 37: return "time";
135 case 39: return("rlp"); 119 case 39: return "rlp";
136 case 42: return("name"); 120 case 42: return "name";
137 case 43: return("whois"); 121 case 43: return "whois";
138 case 53: return("domain"); 122 case 53: return "domain";
139 case 57: return("apts"); 123 case 57: return "apts";
140 case 59: return("apfs"); 124 case 59: return "apfs";
141 case 67: return("bootps"); 125 case 67: return "bootps";
142 case 68: return("bootpc"); 126 case 68: return "bootpc";
143 case 69: return("tftp"); 127 case 69: return "tftp";
144 case 77: return("rje"); 128 case 77: return "rje";
145 case 79: return("finger"); 129 case 79: return "finger";
146 case 87: return("link"); 130 case 87: return "link";
147 case 95: return("supdup"); 131 case 95: return "supdup";
148 case 100: return("newacct"); 132 case 100: return "newacct";
149 case 101: return("hostnames"); 133 case 101: return "hostnames";
150 case 102: return("iso-tsap"); 134 case 102: return "iso-tsap";
151 case 103: return("x400"); 135 case 103: return "x400";
152 case 104: return("x400-snd"); 136 case 104: return "x400-snd";
153 case 105: return("csnet-ns"); 137 case 105: return "csnet-ns";
154 case 109: return("pop-2"); 138 case 109: return "pop-2";
155 case 111: return("sunrpc"); 139 case 111: return "sunrpc";
156 case 113: return("auth"); 140 case 113: return "auth";
157 case 115: return("sftp"); 141 case 115: return "sftp";
158 case 117: return("uucp-path"); 142 case 117: return "uucp-path";
159 case 119: return("nntp"); 143 case 119: return "nntp";
160 case 121: return("erpc"); 144 case 121: return "erpc";
161 case 123: return("ntp"); 145 case 123: return "ntp";
162 case 133: return("statsrv"); 146 case 133: return "statsrv";
163 case 136: return("profile"); 147 case 136: return "profile";
164 case 144: return("NeWS"); 148 case 144: return "NeWS";
165 case 161: return("snmp"); 149 case 161: return "snmp";
166 case 162: return("snmp-trap"); 150 case 162: return "snmp-trap";
167 case 170: return("print-srv"); 151 case 170: return "print-srv";
168 default: (void) sprintf(retbuf, "%d", wks); return(retbuf); 152 default:
153 (void) snprintf(nbuf, sizeof nbuf, "%d", wks);
154 return (nbuf);
169 } 155 }
170} 156}
171 157
172static char * 158/* XXX: we should use getprotobynumber() instead. */
173deproto(protonum) 159static const char *
174 int protonum; 160deproto(int protonum)
175{ 161{
162 static char nbuf[20];
163
176 switch (protonum) { 164 switch (protonum) {
177 case 1: return("icmp"); 165 case 1: return "icmp";
178 case 2: return("igmp"); 166 case 2: return "igmp";
179 case 3: return("ggp"); 167 case 3: return "ggp";
180 case 5: return("st"); 168 case 5: return "st";
181 case 6: return("tcp"); 169 case 6: return "tcp";
182 case 7: return("ucl"); 170 case 7: return "ucl";
183 case 8: return("egp"); 171 case 8: return "egp";
184 case 9: return("igp"); 172 case 9: return "igp";
185 case 11: return("nvp-II"); 173 case 11: return "nvp-II";
186 case 12: return("pup"); 174 case 12: return "pup";
187 case 16: return("chaos"); 175 case 16: return "chaos";
188 case 17: return("udp"); 176 case 17: return "udp";
189 default: (void) sprintf(retbuf, "%d", protonum); return(retbuf); 177 default:
178 (void) snprintf(nbuf, sizeof nbuf, "%d", protonum);
179 return (nbuf);
190 } 180 }
191} 181}
192 182
193static char * 183static const u_char *
194do_rrset(msg, cp, cnt, pflag, file, hs) 184do_rrset(const u_char *msg, int len, const u_char *cp, int cnt, int pflag,
195 int cnt, pflag; 185 FILE *file, const char *hs)
196 char *cp,*msg, *hs;
197 FILE *file;
198{ 186{
187 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
199 int n; 188 int n;
200 int sflag; 189 int sflag;
190
201 /* 191 /*
202 * Print answer records 192 * Print answer records.
203 */ 193 */
204 sflag = (_res.pfcode & pflag); 194 sflag = (_resp->pfcode & pflag);
205 if (n = ntohs(cnt)) { 195 if ((n = ntohs(cnt))) {
206 if ((!_res.pfcode) || ((sflag) && (_res.pfcode & RES_PRF_HEAD1))) 196 if ((!_resp->pfcode) ||
207 fprintf(file, hs); 197 ((sflag) && (_resp->pfcode & RES_PRF_HEAD1)))
198 fprintf(file, "%s", hs);
208 while (--n >= 0) { 199 while (--n >= 0) {
209 cp = p_rr(cp, msg, file); 200 if ((!_resp->pfcode) || sflag) {
210 if ((cp-msg) > PACKETSZ) 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)
211 return (NULL); 213 return (NULL);
212 } 214 }
213 if ((!_res.pfcode) || ((sflag) && (_res.pfcode & RES_PRF_HEAD1))) 215 if ((!_resp->pfcode) ||
216 ((sflag) && (_resp->pfcode & RES_PRF_HEAD1)))
214 putc('\n', file); 217 putc('\n', file);
215 } 218 }
216 return(cp); 219 return (cp);
217} 220}
218 221
219__p_query(msg) 222void
220 char *msg; 223__p_query(const u_char *msg)
221{ 224{
222 __fp_query(msg, stdout); 225 __fp_query(msg, stdout);
223} 226}
@@ -227,19 +230,16 @@ __p_query(msg)
227 * This is intended to be primarily a debugging routine. 230 * This is intended to be primarily a debugging routine.
228 */ 231 */
229void 232void
230__fp_resstat(statp, file) 233__fp_resstat(struct __res_state *statp, FILE *file)
231 struct __res_state *statp;
232 FILE *file;
233{ 234{
234 int bit; 235 u_long mask;
235 236
236 fprintf(file, ";; res options:"); 237 fprintf(file, ";; res options:");
237 if (!statp) 238 if (!statp)
238 statp = &_res; 239 statp = &_res;
239 for (bit = 0; bit < 32; bit++) { /* XXX 32 - bad assumption! */ 240 for (mask = 1; mask != 0; mask <<= 1)
240 if (statp->options & (1<<bit)) 241 if (statp->options & mask)
241 fprintf(file, " %s", p_option(1<<bit)); 242 fprintf(file, " %s", p_option(mask));
242 }
243 putc('\n', file); 243 putc('\n', file);
244} 244}
245 245
@@ -248,109 +248,144 @@ __fp_resstat(statp, file)
248 * This is intended to be primarily a debugging routine. 248 * This is intended to be primarily a debugging routine.
249 */ 249 */
250void 250void
251__fp_query(msg,file) 251__fp_nquery(const u_char *msg, int len, FILE *file)
252 char *msg;
253 FILE *file;
254{ 252{
255 register char *cp; 253 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
256 register HEADER *hp; 254 const u_char *cp, *endMark;
257 register int n; 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
258 263
259 /* 264 /*
260 * Print header fields. 265 * Print header fields.
261 */ 266 */
262 hp = (HEADER *)msg; 267 hp = (HEADER *)msg;
263 cp = msg + sizeof(HEADER); 268 cp = msg + HFIXEDSZ;
264 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEADX) || hp->rcode) { 269 endMark = msg + len;
265 fprintf(file,";; ->>HEADER<<- opcode: %s, status: %s, id: %d", 270 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_HEADX) || hp->rcode) {
271 fprintf(file, ";; ->>HEADER<<- opcode: %s, status: %s, id: %u",
266 _res_opcodes[hp->opcode], 272 _res_opcodes[hp->opcode],
267 _res_resultcodes[hp->rcode], 273 _res_resultcodes[hp->rcode],
268 ntohs(hp->id)); 274 ntohs(hp->id));
269 putc('\n', file); 275 putc('\n', file);
270 } 276 }
271 putc(';', file); 277 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_HEADX))
272 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD2)) { 278 putc(';', file);
273 fprintf(file,"; flags:"); 279 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_HEAD2)) {
280 fprintf(file, "; flags:");
274 if (hp->qr) 281 if (hp->qr)
275 fprintf(file," qr"); 282 fprintf(file, " qr");
276 if (hp->aa) 283 if (hp->aa)
277 fprintf(file," aa"); 284 fprintf(file, " aa");
278 if (hp->tc) 285 if (hp->tc)
279 fprintf(file," tc"); 286 fprintf(file, " tc");
280 if (hp->rd) 287 if (hp->rd)
281 fprintf(file," rd"); 288 fprintf(file, " rd");
282 if (hp->ra) 289 if (hp->ra)
283 fprintf(file," ra"); 290 fprintf(file, " ra");
284 if (hp->pr) 291 if (hp->unused)
285 fprintf(file," pr"); 292 fprintf(file, " UNUSED-BIT-ON");
293 if (hp->ad)
294 fprintf(file, " ad");
295 if (hp->cd)
296 fprintf(file, " cd");
286 } 297 }
287 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD1)) { 298 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_HEAD1)) {
288 fprintf(file,"; Ques: %d", ntohs(hp->qdcount)); 299 fprintf(file, "; Ques: %u", ntohs(hp->qdcount));
289 fprintf(file,", Ans: %d", ntohs(hp->ancount)); 300 fprintf(file, ", Ans: %u", ntohs(hp->ancount));
290 fprintf(file,", Auth: %d", ntohs(hp->nscount)); 301 fprintf(file, ", Auth: %u", ntohs(hp->nscount));
291 fprintf(file,", Addit: %d\n", ntohs(hp->arcount)); 302 fprintf(file, ", Addit: %u", ntohs(hp->arcount));
292 } 303 }
293#if 0 304 if ((!_resp->pfcode) || (_resp->pfcode &
294 if (_res.pfcode & (RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1)) { 305 (RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1))) {
295 putc('\n',file); 306 putc('\n',file);
296 } 307 }
297#endif
298 /* 308 /*
299 * Print question records. 309 * Print question records.
300 */ 310 */
301 if (n = ntohs(hp->qdcount)) { 311 if ((n = ntohs(hp->qdcount))) {
302 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES)) 312 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_QUES))
303 fprintf(file,";; QUESTIONS:\n"); 313 fprintf(file, ";; QUESTIONS:\n");
304 while (--n >= 0) { 314 while (--n >= 0) {
305 fprintf(file,";;\t"); 315 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_QUES))
306 cp = p_cdname(cp, msg, file); 316 fprintf(file, ";;\t");
307 if (cp == NULL) 317 TruncTest(cp);
308 return; 318 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_QUES))
309 if ((!_res.pfcode) || (_res.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))
310 fprintf(file, ", type = %s", 333 fprintf(file, ", type = %s",
311 __p_type(_getshort(cp))); 334 __p_type(_getshort((u_char*)cp)));
312 cp += sizeof(u_int16_t); 335 cp += INT16SZ;
313 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES)) 336 TruncTest(cp);
314 fprintf(file, ", class = %s\n\n", 337 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_QUES))
315 __p_class(_getshort(cp))); 338 fprintf(file, ", class = %s\n",
316 cp += sizeof(u_int16_t); 339 __p_class(_getshort((u_char*)cp)));
340 cp += INT16SZ;
341 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_QUES))
342 putc('\n', file);
317 } 343 }
318 } 344 }
319 /* 345 /*
320 * Print authoritative answer records 346 * Print authoritative answer records
321 */ 347 */
322 cp = do_rrset(msg, cp, hp->ancount, RES_PRF_ANS, file, 348 TruncTest(cp);
349 cp = do_rrset(msg, len, cp, hp->ancount, RES_PRF_ANS, file,
323 ";; ANSWERS:\n"); 350 ";; ANSWERS:\n");
324 if (cp == NULL) 351 ErrorTest(cp);
325 return;
326 352
327 /* 353 /*
328 * print name server records 354 * print name server records
329 */ 355 */
330 cp = do_rrset(msg, cp, hp->nscount, RES_PRF_AUTH, file, 356 TruncTest(cp);
357 cp = do_rrset(msg, len, cp, hp->nscount, RES_PRF_AUTH, file,
331 ";; AUTHORITY RECORDS:\n"); 358 ";; AUTHORITY RECORDS:\n");
332 if (!cp) 359 ErrorTest(cp);
333 return;
334 360
361 TruncTest(cp);
335 /* 362 /*
336 * print additional records 363 * print additional records
337 */ 364 */
338 cp = do_rrset(msg, cp, hp->arcount, RES_PRF_ADD, file, 365 cp = do_rrset(msg, len, cp, hp->arcount, RES_PRF_ADD, file,
339 ";; ADDITIONAL RECORDS:\n"); 366 ";; ADDITIONAL RECORDS:\n");
340 if (!cp) 367 ErrorTest(cp);
341 return; 368 return;
369 trunc:
370 fprintf(file, "\n;; ...truncated\n");
371 return;
372 error:
373 fprintf(file, "\n;; ...malformed\n");
342} 374}
343 375
344char * 376void
345p_cdname(cp, msg, file) 377__fp_query(const u_char *msg, FILE *file)
346 char *cp, *msg; 378{
347 FILE *file; 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)
348{ 384{
349 char name[MAXDNAME]; 385 char name[MAXDNAME];
350 int n; 386 int n;
351 387
352 if ((n = dn_expand((u_char *)msg, (u_char *)cp + MAXCDNAME, 388 if ((n = dn_expand(msg, msg + len, cp, name, sizeof name)) < 0)
353 (u_char *)cp, (u_char *)name, sizeof(name))) < 0)
354 return (NULL); 389 return (NULL);
355 if (name[0] == '\0') 390 if (name[0] == '\0')
356 putc('.', file); 391 putc('.', file);
@@ -359,55 +394,86 @@ p_cdname(cp, msg, file)
359 return (cp + n); 394 return (cp + n);
360} 395}
361 396
362char * 397const u_char *
363p_fqname(cp, msg, file) 398__p_cdname(const u_char *cp, const u_char *msg, FILE *file)
364 char *cp, *msg;
365 FILE *file;
366{ 399{
367 char name[MAXDNAME]; 400 return (p_cdnname(cp, msg, PACKETSZ, file));
368 int n, len; 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;
369 411
370 if ((n = dn_expand((u_char *)msg, (u_char *)cp + MAXCDNAME, 412 if ((n = dn_expand(msg, cp + msglen, cp, name, namelen)) < 0)
371 (u_char *)cp, (u_char *)name, sizeof(name))) < 0)
372 return (NULL); 413 return (NULL);
373 if (name[0] == '\0') { 414 newlen = strlen(name);
374 putc('.', file); 415 if (newlen == 0 || name[newlen - 1] != '.') {
375 } else { 416 if (newlen + 1 >= namelen) /* Lack space for final dot */
376 fputs(name, file); 417 return (NULL);
377 if (name[strlen(name) - 1] != '.') 418 else
378 putc('.', file); 419 strlcpy(name + newlen, ".", namelen - newlen);
379 } 420 }
380 return (cp + n); 421 return (cp + n);
381} 422}
382 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
383/* 440/*
384 * Print resource record fields in human readable form. 441 * Print resource record fields in human readable form.
385 */ 442 */
386char * 443const u_char *
387p_rr(cp, msg, file) 444__p_rr(const u_char *cp, const u_char *msg, FILE *file)
388 char *cp, *msg;
389 FILE *file;
390{ 445{
446 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
391 int type, class, dlen, n, c; 447 int type, class, dlen, n, c;
392 struct in_addr inaddr; 448 struct in_addr inaddr;
393 char *cp1, *cp2; 449 const u_char *cp1, *cp2;
394 u_int32_t tmpttl, t; 450 u_int32_t tmpttl, t;
395 int lcnt; 451 int lcnt;
452 u_int16_t keyflags;
453 char rrname[MAXDNAME]; /* The fqdn of this RR */
454 char base64_key[MAX_KEY_BASE64];
396 455
397 if ((cp = p_fqname(cp, msg, file)) == NULL) 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)
398 return (NULL); /* compression error */ 462 return (NULL); /* compression error */
399 type = _getshort(cp); 463 fputs(rrname, file);
400 cp += sizeof(u_int16_t); 464
401 class = _getshort(cp); 465 type = _getshort((u_char*)cp);
402 cp += sizeof(u_int16_t); 466 cp += INT16SZ;
403 tmpttl = _getlong(cp); 467 class = _getshort((u_char*)cp);
404 cp += sizeof(u_int32_t); 468 cp += INT16SZ;
405 dlen = _getshort(cp); 469 tmpttl = _getlong((u_char*)cp);
406 cp += sizeof(u_int16_t); 470 cp += INT32SZ;
471 dlen = _getshort((u_char*)cp);
472 cp += INT16SZ;
407 cp1 = cp; 473 cp1 = cp;
408 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_TTLID)) 474 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_TTLID))
409 fprintf(file, "\t%lu", tmpttl); 475 fprintf(file, "\t%lu", (u_long)tmpttl);
410 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_CLASS)) 476 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_CLASS))
411 fprintf(file, "\t%s", __p_class(class)); 477 fprintf(file, "\t%s", __p_class(class));
412 fprintf(file, "\t%s", __p_type(type)); 478 fprintf(file, "\t%s", __p_type(type));
413 /* 479 /*
@@ -418,22 +484,22 @@ p_rr(cp, msg, file)
418 switch (class) { 484 switch (class) {
419 case C_IN: 485 case C_IN:
420 case C_HS: 486 case C_HS:
421 bcopy(cp, (char *)&inaddr, sizeof(inaddr)); 487 bcopy(cp, (char *)&inaddr, INADDRSZ);
422 if (dlen == 4) { 488 if (dlen == 4) {
423 fprintf(file,"\t%s", inet_ntoa(inaddr)); 489 fprintf(file, "\t%s", inet_ntoa(inaddr));
424 cp += dlen; 490 cp += dlen;
425 } else if (dlen == 7) { 491 } else if (dlen == 7) {
426 char *address; 492 char *address;
427 u_char protocol; 493 u_char protocol;
428 u_short port; 494 in_port_t port;
429 495
430 address = inet_ntoa(inaddr); 496 address = inet_ntoa(inaddr);
431 cp += sizeof(inaddr); 497 cp += INADDRSZ;
432 protocol = *(u_char*)cp; 498 protocol = *(u_char*)cp;
433 cp += sizeof(u_char); 499 cp += sizeof (u_char);
434 port = _getshort(cp); 500 port = _getshort((u_char*)cp);
435 cp += sizeof(u_int16_t); 501 cp += INT16SZ;
436 fprintf(file, "\t%s\t; proto %d, port %d", 502 fprintf(file, "\t%s\t; proto %u, port %u",
437 address, protocol, port); 503 address, protocol, port);
438 } 504 }
439 break; 505 break;
@@ -448,98 +514,205 @@ p_rr(cp, msg, file)
448 case T_NS: 514 case T_NS:
449 case T_PTR: 515 case T_PTR:
450 putc('\t', file); 516 putc('\t', file);
451 cp = p_fqname(cp, msg, file); 517 if ((cp = p_fqname(cp, msg, file)) == NULL)
518 return (NULL);
452 break; 519 break;
453 520
454 case T_HINFO: 521 case T_HINFO:
455 if (n = *cp++) { 522 case T_ISDN:
456 fprintf(file,"\t%.*s", n, cp); 523 cp2 = cp + dlen;
457 cp += n; 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 }
458 } 531 }
459 if (n = *cp++) { 532 putc('"', file);
460 fprintf(file,"\t%.*s", n, cp); 533 if (cp < cp2 && (n = (unsigned char) *cp++) != 0) {
461 cp += n; 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");
462 } 544 }
463 break; 545 break;
464 546
465 case T_SOA: 547 case T_SOA:
466 putc('\t', file); 548 putc('\t', file);
467 cp = p_fqname(cp, msg, file); /* origin */ 549 if ((cp = p_fqname(cp, msg, file)) == NULL)
550 return (NULL);
468 putc(' ', file); 551 putc(' ', file);
469 cp = p_fqname(cp, msg, file); /* mail addr */ 552 if ((cp = p_fqname(cp, msg, file)) == NULL)
553 return (NULL);
470 fputs(" (\n", file); 554 fputs(" (\n", file);
471 t = _getlong(cp); cp += sizeof(u_int32_t); 555 t = _getlong((u_char*)cp); cp += INT32SZ;
472 fprintf(file,"\t\t\t%lu\t; serial\n", t); 556 fprintf(file, "\t\t\t%lu\t; serial\n", (u_long)t);
473 t = _getlong(cp); cp += sizeof(u_int32_t); 557 t = _getlong((u_char*)cp); cp += INT32SZ;
474 fprintf(file,"\t\t\t%lu\t; refresh (%s)\n", t, __p_time(t)); 558 fprintf(file, "\t\t\t%lu\t; refresh (%s)\n",
475 t = _getlong(cp); cp += sizeof(u_int32_t); 559 (u_long)t, __p_time(t));
476 fprintf(file,"\t\t\t%lu\t; retry (%s)\n", t, __p_time(t)); 560 t = _getlong((u_char*)cp); cp += INT32SZ;
477 t = _getlong(cp); cp += sizeof(u_int32_t); 561 fprintf(file, "\t\t\t%lu\t; retry (%s)\n",
478 fprintf(file,"\t\t\t%lu\t; expire (%s)\n", t, __p_time(t)); 562 (u_long)t, __p_time(t));
479 t = _getlong(cp); cp += sizeof(u_int32_t); 563 t = _getlong((u_char*)cp); cp += INT32SZ;
480 fprintf(file,"\t\t\t%lu )\t; minimum (%s)", t, __p_time(t)); 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));
481 break; 569 break;
482 570
483 case T_MX: 571 case T_MX:
484 case T_AFSDB: 572 case T_AFSDB:
485 fprintf(file,"\t%d ", _getshort(cp)); 573 case T_RT:
486 cp += sizeof(u_int16_t); 574 fprintf(file, "\t%u ", _getshort((u_char*)cp));
487 cp = p_fqname(cp, msg, file); 575 cp += INT16SZ;
576 if ((cp = p_fqname(cp, msg, file)) == NULL)
577 return (NULL);
488 break; 578 break;
489 579
490 case T_TXT: 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;
491 (void) fputs("\t\"", file); 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);
492 cp2 = cp1 + dlen; 605 cp2 = cp1 + dlen;
493 while (cp < cp2) { 606 while (cp < cp2) {
494 if (n = (unsigned char) *cp++) { 607 putc('"', file);
495 for (c = n; c > 0 && cp < cp2; c--) 608 if ((n = (unsigned char) *cp++)) {
496 if (*cp == '\n') { 609 for (c = n; c > 0 && cp < cp2; c--) {
497 (void) putc('\\', file); 610 if (strchr("\n\"\\", *cp))
498 (void) putc(*cp++, file); 611 (void) putc('\\', file);
499 } else 612 (void) putc(*cp++, file);
500 (void) putc(*cp++, file); 613 }
501 } 614 }
615 putc('"', file);
616 if (cp < cp2)
617 putc(' ', file);
502 } 618 }
503 putc('"', file); 619 break;
504 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 }
505 676
506 case T_MINFO: 677 case T_MINFO:
507 case T_RP: 678 case T_RP:
508 putc('\t', file); 679 putc('\t', file);
509 cp = p_fqname(cp, msg, file); 680 if ((cp = p_fqname(cp, msg, file)) == NULL)
681 return (NULL);
510 putc(' ', file); 682 putc(' ', file);
511 cp = p_fqname(cp, msg, file); 683 if ((cp = p_fqname(cp, msg, file)) == NULL)
684 return (NULL);
512 break; 685 break;
513 686
514 case T_UINFO: 687 case T_UINFO:
515 putc('\t', file); 688 putc('\t', file);
516 fputs(cp, file); 689 fputs((char *)cp, file);
517 cp += dlen; 690 cp += dlen;
518 break; 691 break;
519 692
520 case T_UID: 693 case T_UID:
521 case T_GID: 694 case T_GID:
522 if (dlen == 4) { 695 if (dlen == 4) {
523 fprintf(file,"\t%u", _getlong(cp)); 696 fprintf(file, "\t%u", _getlong((u_char*)cp));
524 cp += sizeof(int32_t); 697 cp += INT32SZ;
525 } 698 }
526 break; 699 break;
527 700
528 case T_WKS: 701 case T_WKS:
529 if (dlen < sizeof(u_int32_t) + 1) 702 if (dlen < INT32SZ + 1)
530 break; 703 break;
531 bcopy(cp, (char *)&inaddr, sizeof(inaddr)); 704 bcopy(cp, (char *)&inaddr, INADDRSZ);
532 cp += sizeof(u_int32_t); 705 cp += INT32SZ;
533 fprintf(file, "\t%s %s ( ", 706 fprintf(file, "\t%s %s ( ",
534 inet_ntoa(inaddr), 707 inet_ntoa(inaddr),
535 deproto((int) *cp)); 708 deproto((int) *cp));
536 cp += sizeof(u_char); 709 cp += sizeof (u_char);
537 n = 0; 710 n = 0;
538 lcnt = 0; 711 lcnt = 0;
539 while (cp < cp1 + dlen) { 712 while (cp < cp1 + dlen) {
540 c = *cp++; 713 c = *cp++;
541 do { 714 do {
542 if (c & 0200) { 715 if (c & 0200) {
543 if (lcnt == 0) { 716 if (lcnt == 0) {
544 fputs("\n\t\t\t", file); 717 fputs("\n\t\t\t", file);
545 lcnt = 5; 718 lcnt = 5;
@@ -548,17 +721,84 @@ p_rr(cp, msg, file)
548 putc(' ', file); 721 putc(' ', file);
549 lcnt--; 722 lcnt--;
550 } 723 }
551 c <<= 1; 724 c <<= 1;
552 } while (++n & 07); 725 } while (++n & 07);
553 } 726 }
554 putc(')', file); 727 putc(')', file);
555 break; 728 break;
556 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 case T_RRSIG:
755 type = _getshort((u_char*)cp);
756 cp += INT16SZ;
757 fprintf(file, " %s", p_type(type));
758 fprintf(file, "\t%u", *cp++); /* algorithm */
759 /* Check label value and print error if wrong. */
760 n = *cp++;
761 c = dn_count_labels (rrname);
762 if (n != c)
763 fprintf(file, "\t; LABELS WRONG (%d should be %d)\n\t",
764 n, c);
765 /* orig ttl */
766 n = _getlong((u_char*)cp);
767 if (n != tmpttl)
768 fprintf(file, " %u", n);
769 cp += INT32SZ;
770 /* sig expire */
771 fprintf(file, " (\n\t%s",
772 __p_secstodate(_getlong((u_char*)cp)));
773 cp += INT32SZ;
774 /* time signed */
775 fprintf(file, " %s", __p_secstodate(_getlong((u_char*)cp)));
776 cp += INT32SZ;
777 /* sig footprint */
778 fprintf(file," %u ", _getshort((u_char*)cp));
779 cp += INT16SZ;
780 /* signer's name */
781 cp = p_fqname(cp, msg, file);
782 n = b64_ntop(cp, (cp1 + dlen) - cp,
783 base64_key, sizeof base64_key);
784 for (c = 0; c < n; c++) {
785 if (0 == (c & 0x3F))
786 fprintf (file, "\n\t");
787 putc(base64_key[c], file); /* signature */
788 }
789 /* Clean up... */
790 fprintf(file, " )");
791 if (n < 0)
792 fprintf(file, "\t; BAD BASE64");
793 fflush(file);
794 cp = cp1+dlen;
795 break;
796
557#ifdef ALLOW_T_UNSPEC 797#ifdef ALLOW_T_UNSPEC
558 case T_UNSPEC: 798 case T_UNSPEC:
559 { 799 {
560 int NumBytes = 8; 800 int NumBytes = 8;
561 char *DataPtr; 801 u_char *DataPtr;
562 int i; 802 int i;
563 803
564 if (dlen < NumBytes) NumBytes = dlen; 804 if (dlen < NumBytes) NumBytes = dlen;
@@ -572,7 +812,7 @@ p_rr(cp, msg, file)
572#endif /* ALLOW_T_UNSPEC */ 812#endif /* ALLOW_T_UNSPEC */
573 813
574 default: 814 default:
575 fprintf(file,"\t?%d?", type); 815 fprintf(file, "\t?%d?", type);
576 cp += dlen; 816 cp += dlen;
577 } 817 }
578#if 0 818#if 0
@@ -581,136 +821,91 @@ p_rr(cp, msg, file)
581 putc('\n', file); 821 putc('\n', file);
582#endif 822#endif
583 if (cp - cp1 != dlen) { 823 if (cp - cp1 != dlen) {
584 fprintf(file,";; packet size error (found %d, dlen was %d)\n", 824 fprintf(file, ";; packet size error (found %ld, dlen was %d)\n",
585 cp - cp1, dlen); 825 (long)(cp - cp1), dlen);
586 cp = NULL; 826 cp = NULL;
587 } 827 }
588 return (cp); 828 return (cp);
589} 829}
590 830
591static char nbuf[40]; 831int
592 832__sym_ston(const struct res_sym *syms, char *name, int *success)
593/*
594 * Return a string for the type
595 */
596char *
597__p_type(type)
598 int type;
599{ 833{
600 switch (type) { 834 for (; syms->name != 0; syms++) {
601 case T_A: 835 if (strcasecmp (name, syms->name) == 0) {
602 return("A"); 836 if (success)
603 case T_NS: /* authoritative server */ 837 *success = 1;
604 return("NS"); 838 return (syms->number);
605 case T_CNAME: /* canonical name */ 839 }
606 return("CNAME");
607 case T_SOA: /* start of authority zone */
608 return("SOA");
609 case T_MB: /* mailbox domain name */
610 return("MB");
611 case T_MG: /* mail group member */
612 return("MG");
613 case T_MR: /* mail rename name */
614 return("MR");
615 case T_NULL: /* null resource record */
616 return("NULL");
617 case T_WKS: /* well known service */
618 return("WKS");
619 case T_PTR: /* domain name pointer */
620 return("PTR");
621 case T_HINFO: /* host information */
622 return("HINFO");
623 case T_MINFO: /* mailbox information */
624 return("MINFO");
625 case T_MX: /* mail routing info */
626 return("MX");
627 case T_TXT: /* text */
628 return("TXT");
629 case T_RP: /* responsible person */
630 return("RP");
631 case T_AFSDB: /* AFS cell database */
632 return("AFSDB");
633 case T_AXFR: /* zone transfer */
634 return("AXFR");
635 case T_MAILB: /* mail box */
636 return("MAILB");
637 case T_MAILA: /* mail address */
638 return("MAILA");
639 case T_ANY: /* matches any type */
640 return("ANY");
641 case T_UINFO:
642 return("UINFO");
643 case T_UID:
644 return("UID");
645 case T_GID:
646 return("GID");
647#ifdef ALLOW_T_UNSPEC
648 case T_UNSPEC:
649 return("UNSPEC");
650#endif /* ALLOW_T_UNSPEC */
651
652 default:
653 (void)sprintf(nbuf, "%d", type);
654 return(nbuf);
655 } 840 }
841 if (success)
842 *success = 0;
843 return (syms->number); /* The default value. */
656} 844}
657 845
658/* 846
659 * Return a mnemonic for class 847const char *
660 */ 848__sym_ntop(const struct res_sym *syms, int number, int *success)
661char *
662__p_class(class)
663 int class;
664{ 849{
850 static char unname[20];
665 851
666 switch (class) { 852 for (; syms->name != 0; syms++) {
667 case C_IN: /* internet class */ 853 if (number == syms->number) {
668 return("IN"); 854 if (success)
669 case C_HS: /* hesiod class */ 855 *success = 1;
670 return("HS"); 856 return (syms->humanname);
671 case C_ANY: /* matches any class */ 857 }
672 return("ANY");
673 default:
674 (void)sprintf(nbuf, "%d", class);
675 return(nbuf);
676 } 858 }
859 snprintf(unname, sizeof unname, "%d", number);
860 if (success)
861 *success = 0;
862 return (unname);
677} 863}
678 864
679/* 865/*
680 * Return a mnemonic for an option 866 * Return a mnemonic for an option
681 */ 867 */
682static char * 868const char *
683p_option(option) 869__p_option(u_long option)
684 u_int32_t option;
685{ 870{
871 static char nbuf[40];
872
686 switch (option) { 873 switch (option) {
687 case RES_INIT: return "init"; 874 case RES_INIT: return "init";
688 case RES_DEBUG: return "debug"; 875 case RES_DEBUG: return "debug";
689 case RES_AAONLY: return "aaonly"; 876 case RES_AAONLY: return "aaonly(unimpl)";
690 case RES_USEVC: return "usevc"; 877 case RES_USEVC: return "usevc";
691 case RES_PRIMARY: return "primry"; 878 case RES_PRIMARY: return "primry(unimpl)";
692 case RES_IGNTC: return "igntc"; 879 case RES_IGNTC: return "igntc";
693 case RES_RECURSE: return "recurs"; 880 case RES_RECURSE: return "recurs";
694 case RES_DEFNAMES: return "defnam"; 881 case RES_DEFNAMES: return "defnam";
695 case RES_STAYOPEN: return "styopn"; 882 case RES_STAYOPEN: return "styopn";
696 case RES_DNSRCH: return "dnsrch"; 883 case RES_DNSRCH: return "dnsrch";
697 default: sprintf(nbuf, "?0x%x?", option); return nbuf; 884 case RES_INSECURE1: return "insecure1";
885 case RES_INSECURE2: return "insecure2";
886 case RES_USE_INET6: return "inet6";
887 case RES_USE_EDNS0: return "edns0";
888 default:
889 snprintf(nbuf, sizeof nbuf, "?0x%lx?", (u_long)option);
890 return (nbuf);
698 } 891 }
699} 892}
700 893
701/* 894/*
702 * Return a mnemonic for a time to live 895 * Return a mnemonic for a time to live
703 */ 896 */
704char * 897const char *
705__p_time(value) 898p_time(u_int32_t value)
706 u_int32_t value;
707{ 899{
900 static char nbuf[40];
901 char *ebuf;
708 int secs, mins, hours, days; 902 int secs, mins, hours, days;
709 register char *p; 903 char *p;
904 int tmp;
710 905
711 if (value == 0) { 906 if (value == 0) {
712 strcpy(nbuf, "0 secs"); 907 strlcpy(nbuf, "0 secs", sizeof nbuf);
713 return(nbuf); 908 return (nbuf);
714 } 909 }
715 910
716 secs = value % 60; 911 secs = value % 60;
@@ -724,26 +919,477 @@ __p_time(value)
724 919
725#define PLURALIZE(x) x, (x == 1) ? "" : "s" 920#define PLURALIZE(x) x, (x == 1) ? "" : "s"
726 p = nbuf; 921 p = nbuf;
922 ebuf = nbuf + sizeof(nbuf);
727 if (days) { 923 if (days) {
728 (void)sprintf(p, "%d day%s", PLURALIZE(days)); 924 if ((tmp = snprintf(p, ebuf - p, "%d day%s",
729 while (*++p); 925 PLURALIZE(days))) >= ebuf - p || tmp < 0)
926 goto full;
927 p += tmp;
730 } 928 }
731 if (hours) { 929 if (hours) {
732 if (days) 930 if (days)
733 *p++ = ' '; 931 *p++ = ' ';
734 (void)sprintf(p, "%d hour%s", PLURALIZE(hours)); 932 if (p >= ebuf)
735 while (*++p); 933 goto full;
934 if ((tmp = snprintf(p, ebuf - p, "%d hour%s",
935 PLURALIZE(hours))) >= ebuf - p || tmp < 0)
936 goto full;
937 p += tmp;
736 } 938 }
737 if (mins) { 939 if (mins) {
738 if (days || hours) 940 if (days || hours)
739 *p++ = ' '; 941 *p++ = ' ';
740 (void)sprintf(p, "%d min%s", PLURALIZE(mins)); 942 if (p >= ebuf)
741 while (*++p); 943 goto full;
944 if ((tmp = snprintf(p, ebuf - p, "%d min%s",
945 PLURALIZE(mins))) >= ebuf - p || tmp < 0)
946 goto full;
947 p += tmp;
742 } 948 }
743 if (secs || ! (days || hours || mins)) { 949 if (secs || ! (days || hours || mins)) {
744 if (days || hours || mins) 950 if (days || hours || mins)
745 *p++ = ' '; 951 *p++ = ' ';
746 (void)sprintf(p, "%d sec%s", PLURALIZE(secs)); 952 if (p >= ebuf)
953 goto full;
954 if ((tmp = snprintf(p, ebuf - p, "%d sec%s",
955 PLURALIZE(secs))) >= ebuf - p || tmp < 0)
956 goto full;
747 } 957 }
748 return(nbuf); 958 return (nbuf);
959full:
960 p = nbuf + sizeof(nbuf) - 4;
961 *p++ = '.';
962 *p++ = '.';
963 *p++ = '.';
964 *p++ = '\0';
965 return (nbuf);
966}
967
968/*
969 * routines to convert between on-the-wire RR format and zone file format.
970 * Does not contain conversion to/from decimal degrees; divide or multiply
971 * by 60*60*1000 for that.
972 */
973
974static unsigned int poweroften[10] = {1, 10, 100, 1000, 10000, 100000,
975 1000000,10000000,100000000,1000000000};
976
977/* takes an XeY precision/size value, returns a string representation. */
978static const char *
979precsize_ntoa(u_int8_t prec)
980{
981 static char retbuf[sizeof "90000000.00"];
982 unsigned long val;
983 int mantissa, exponent;
984
985 mantissa = (int)((prec >> 4) & 0x0f) % 10;
986 exponent = (int)((prec >> 0) & 0x0f) % 10;
987
988 val = mantissa * poweroften[exponent];
989
990 (void) snprintf(retbuf, sizeof retbuf, "%ld.%.2ld", val/100, val%100);
991 return (retbuf);
992}
993
994/* converts ascii size/precision X * 10**Y(cm) to 0xXY. moves pointer. */
995static u_int8_t
996precsize_aton(char **strptr)
997{
998 unsigned int mval = 0, cmval = 0;
999 u_int8_t retval = 0;
1000 char *cp;
1001 int exponent;
1002 int mantissa;
1003
1004 cp = *strptr;
1005
1006 while (isdigit(*cp))
1007 mval = mval * 10 + (*cp++ - '0');
1008
1009 if (*cp == '.') { /* centimeters */
1010 cp++;
1011 if (isdigit(*cp)) {
1012 cmval = (*cp++ - '0') * 10;
1013 if (isdigit(*cp)) {
1014 cmval += (*cp++ - '0');
1015 }
1016 }
1017 }
1018 cmval = (mval * 100) + cmval;
1019
1020 for (exponent = 0; exponent < 9; exponent++)
1021 if (cmval < poweroften[exponent+1])
1022 break;
1023
1024 mantissa = cmval / poweroften[exponent];
1025 if (mantissa > 9)
1026 mantissa = 9;
1027
1028 retval = (mantissa << 4) | exponent;
1029
1030 *strptr = cp;
1031
1032 return (retval);
1033}
1034
1035/* converts ascii lat/lon to unsigned encoded 32-bit number. moves pointer. */
1036static u_int32_t
1037latlon2ul(char **latlonstrptr, int *which)
1038{
1039 char *cp;
1040 u_int32_t retval;
1041 int deg = 0, min = 0, secs = 0, secsfrac = 0;
1042
1043 cp = *latlonstrptr;
1044
1045 while (isdigit(*cp))
1046 deg = deg * 10 + (*cp++ - '0');
1047
1048 while (isspace(*cp))
1049 cp++;
1050
1051 if (!(isdigit(*cp)))
1052 goto fndhemi;
1053
1054 while (isdigit(*cp))
1055 min = min * 10 + (*cp++ - '0');
1056
1057 while (isspace(*cp))
1058 cp++;
1059
1060 if (!(isdigit(*cp)))
1061 goto fndhemi;
1062
1063 while (isdigit(*cp))
1064 secs = secs * 10 + (*cp++ - '0');
1065
1066 if (*cp == '.') { /* decimal seconds */
1067 cp++;
1068 if (isdigit(*cp)) {
1069 secsfrac = (*cp++ - '0') * 100;
1070 if (isdigit(*cp)) {
1071 secsfrac += (*cp++ - '0') * 10;
1072 if (isdigit(*cp)) {
1073 secsfrac += (*cp++ - '0');
1074 }
1075 }
1076 }
1077 }
1078
1079 while (!isspace(*cp)) /* if any trailing garbage */
1080 cp++;
1081
1082 while (isspace(*cp))
1083 cp++;
1084
1085 fndhemi:
1086 switch (*cp) {
1087 case 'N': case 'n':
1088 case 'E': case 'e':
1089 retval = ((unsigned)1<<31)
1090 + (((((deg * 60) + min) * 60) + secs) * 1000)
1091 + secsfrac;
1092 break;
1093 case 'S': case 's':
1094 case 'W': case 'w':
1095 retval = ((unsigned)1<<31)
1096 - (((((deg * 60) + min) * 60) + secs) * 1000)
1097 - secsfrac;
1098 break;
1099 default:
1100 retval = 0; /* invalid value -- indicates error */
1101 break;
1102 }
1103
1104 switch (*cp) {
1105 case 'N': case 'n':
1106 case 'S': case 's':
1107 *which = 1; /* latitude */
1108 break;
1109 case 'E': case 'e':
1110 case 'W': case 'w':
1111 *which = 2; /* longitude */
1112 break;
1113 default:
1114 *which = 0; /* error */
1115 break;
1116 }
1117
1118 cp++; /* skip the hemisphere */
1119
1120 while (!isspace(*cp)) /* if any trailing garbage */
1121 cp++;
1122
1123 while (isspace(*cp)) /* move to next field */
1124 cp++;
1125
1126 *latlonstrptr = cp;
1127
1128 return (retval);
1129}
1130
1131/* converts a zone file representation in a string to an RDATA on-the-wire
1132 * representation. */
1133int
1134loc_aton(const char *ascii, u_char *binary)
1135{
1136 const char *maxcp;
1137 u_char *bcp;
1138 char *cp;
1139
1140 u_int32_t latit = 0, longit = 0, alt = 0;
1141 u_int32_t lltemp1 = 0, lltemp2 = 0;
1142 int altmeters = 0, altfrac = 0, altsign = 1;
1143 u_int8_t hp = 0x16; /* default = 1e6 cm = 10000.00m = 10km */
1144 u_int8_t vp = 0x13; /* default = 1e3 cm = 10.00m */
1145 u_int8_t siz = 0x12; /* default = 1e2 cm = 1.00m */
1146 int which1 = 0, which2 = 0;
1147
1148 cp = (char *)ascii;
1149 maxcp = cp + strlen(ascii);
1150
1151 lltemp1 = latlon2ul(&cp, &which1);
1152
1153 lltemp2 = latlon2ul(&cp, &which2);
1154
1155 switch (which1 + which2) {
1156 case 3: /* 1 + 2, the only valid combination */
1157 if ((which1 == 1) && (which2 == 2)) { /* normal case */
1158 latit = lltemp1;
1159 longit = lltemp2;
1160 } else if ((which1 == 2) && (which2 == 1)) { /* reversed */
1161 longit = lltemp1;
1162 latit = lltemp2;
1163 } else { /* some kind of brokenness */
1164 return (0);
1165 }
1166 break;
1167 default: /* we didn't get one of each */
1168 return (0);
1169 }
1170
1171 /* altitude */
1172 if (*cp == '-') {
1173 altsign = -1;
1174 cp++;
1175 }
1176
1177 if (*cp == '+')
1178 cp++;
1179
1180 while (isdigit(*cp))
1181 altmeters = altmeters * 10 + (*cp++ - '0');
1182
1183 if (*cp == '.') { /* decimal meters */
1184 cp++;
1185 if (isdigit(*cp)) {
1186 altfrac = (*cp++ - '0') * 10;
1187 if (isdigit(*cp)) {
1188 altfrac += (*cp++ - '0');
1189 }
1190 }
1191 }
1192
1193 alt = (10000000 + (altsign * (altmeters * 100 + altfrac)));
1194
1195 while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
1196 cp++;
1197
1198 while (isspace(*cp) && (cp < maxcp))
1199 cp++;
1200
1201 if (cp >= maxcp)
1202 goto defaults;
1203
1204 siz = precsize_aton(&cp);
1205
1206 while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
1207 cp++;
1208
1209 while (isspace(*cp) && (cp < maxcp))
1210 cp++;
1211
1212 if (cp >= maxcp)
1213 goto defaults;
1214
1215 hp = precsize_aton(&cp);
1216
1217 while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
1218 cp++;
1219
1220 while (isspace(*cp) && (cp < maxcp))
1221 cp++;
1222
1223 if (cp >= maxcp)
1224 goto defaults;
1225
1226 vp = precsize_aton(&cp);
1227
1228 defaults:
1229
1230 bcp = binary;
1231 *bcp++ = (u_int8_t) 0; /* version byte */
1232 *bcp++ = siz;
1233 *bcp++ = hp;
1234 *bcp++ = vp;
1235 PUTLONG(latit,bcp);
1236 PUTLONG(longit,bcp);
1237 PUTLONG(alt,bcp);
1238
1239 return (16); /* size of RR in octets */
1240}
1241
1242const char *
1243loc_ntoa(const u_char *binary, char *ascii)
1244{
1245 return loc_ntoal(binary, ascii, 255);
1246}
1247
1248/* takes an on-the-wire LOC RR and formats it in a human readable format. */
1249static const char *
1250loc_ntoal(const u_char *binary, char *ascii, int ascii_len)
1251{
1252 static char *error = "?";
1253 const u_char *cp = binary;
1254
1255 int latdeg, latmin, latsec, latsecfrac;
1256 int longdeg, longmin, longsec, longsecfrac;
1257 char northsouth, eastwest;
1258 int altmeters, altfrac, altsign;
1259
1260 const int referencealt = 100000 * 100;
1261
1262 int32_t latval, longval, altval;
1263 u_int32_t templ;
1264 u_int8_t sizeval, hpval, vpval, versionval;
1265
1266 char *sizestr, *hpstr, *vpstr;
1267
1268 versionval = *cp++;
1269
1270 if (versionval) {
1271 snprintf(ascii, ascii_len, "; error: unknown LOC RR version");
1272 return (ascii);
1273 }
1274
1275 sizeval = *cp++;
1276
1277 hpval = *cp++;
1278 vpval = *cp++;
1279
1280 GETLONG(templ, cp);
1281 latval = (templ - ((unsigned)1<<31));
1282
1283 GETLONG(templ, cp);
1284 longval = (templ - ((unsigned)1<<31));
1285
1286 GETLONG(templ, cp);
1287 if (templ < referencealt) { /* below WGS 84 spheroid */
1288 altval = referencealt - templ;
1289 altsign = -1;
1290 } else {
1291 altval = templ - referencealt;
1292 altsign = 1;
1293 }
1294
1295 if (latval < 0) {
1296 northsouth = 'S';
1297 latval = -latval;
1298 } else
1299 northsouth = 'N';
1300
1301 latsecfrac = latval % 1000;
1302 latval = latval / 1000;
1303 latsec = latval % 60;
1304 latval = latval / 60;
1305 latmin = latval % 60;
1306 latval = latval / 60;
1307 latdeg = latval;
1308
1309 if (longval < 0) {
1310 eastwest = 'W';
1311 longval = -longval;
1312 } else
1313 eastwest = 'E';
1314
1315 longsecfrac = longval % 1000;
1316 longval = longval / 1000;
1317 longsec = longval % 60;
1318 longval = longval / 60;
1319 longmin = longval % 60;
1320 longval = longval / 60;
1321 longdeg = longval;
1322
1323 altfrac = altval % 100;
1324 altmeters = (altval / 100) * altsign;
1325
1326 if ((sizestr = strdup(precsize_ntoa(sizeval))) == NULL)
1327 sizestr = error;
1328 if ((hpstr = strdup(precsize_ntoa(hpval))) == NULL)
1329 hpstr = error;
1330 if ((vpstr = strdup(precsize_ntoa(vpval))) == NULL)
1331 vpstr = error;
1332
1333 snprintf(ascii, ascii_len,
1334 "%d %.2d %.2d.%.3d %c %d %.2d %.2d.%.3d %c %d.%.2dm %sm %sm %sm",
1335 latdeg, latmin, latsec, latsecfrac, northsouth,
1336 longdeg, longmin, longsec, longsecfrac, eastwest,
1337 altmeters, altfrac, sizestr, hpstr, vpstr);
1338
1339 if (sizestr != error)
1340 free(sizestr);
1341 if (hpstr != error)
1342 free(hpstr);
1343 if (vpstr != error)
1344 free(vpstr);
1345
1346 return (ascii);
1347}
1348
1349
1350/* Return the number of DNS hierarchy levels in the name. */
1351int
1352__dn_count_labels(char *name)
1353{
1354 int i, len, count;
1355
1356 len = strlen(name);
1357
1358 for(i = 0, count = 0; i < len; i++) {
1359 if (name[i] == '.')
1360 count++;
1361 }
1362
1363 /* don't count initial wildcard */
1364 if (name[0] == '*')
1365 if (count)
1366 count--;
1367
1368 /* don't count the null label for root. */
1369 /* if terminating '.' not found, must adjust */
1370 /* count to include last label */
1371 if (len > 0 && name[len-1] != '.')
1372 count++;
1373 return (count);
1374}
1375
1376
1377/*
1378 * Make dates expressed in seconds-since-Jan-1-1970 easy to read.
1379 * SIG records are required to be printed like this, by the Secure DNS RFC.
1380 */
1381char *
1382__p_secstodate (long unsigned int secs)
1383{
1384 static char output[15]; /* YYYYMMDDHHMMSS and null */
1385 time_t clock = secs;
1386 struct tm *time;
1387
1388 time = gmtime(&clock);
1389 time->tm_year += 1900;
1390 time->tm_mon += 1;
1391 snprintf(output, sizeof output, "%04d%02d%02d%02d%02d%02d",
1392 time->tm_year, time->tm_mon, time->tm_mday,
1393 time->tm_hour, time->tm_min, time->tm_sec);
1394 return (output);
749} 1395}
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
index 33cc8d39f1..18de3550e6 100644
--- a/src/lib/libc/net/res_init.c
+++ b/src/lib/libc/net/res_init.c
@@ -1,9 +1,11 @@
1/* $NetBSD: res_init.c,v 1.8 1995/06/03 22:33:36 mycroft Exp $ */ 1/* $OpenBSD: res_init.c,v 1.40 2009/06/05 09:52:26 pyr Exp $ */
2 2
3/*- 3/*
4 * ++Copyright++ 1985, 1989, 1993
5 * -
4 * Copyright (c) 1985, 1989, 1993 6 * Copyright (c) 1985, 1989, 1993
5 * The Regents of the University of California. All rights reserved. 7 * The Regents of the University of California. All rights reserved.
6 * 8 *
7 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
9 * are met: 11 * are met:
@@ -12,14 +14,10 @@
12 * 2. Redistributions in binary form must reproduce the above copyright 14 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 15 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 16 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software 17 * 3. Neither the name of the University nor the names of its contributors
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software 18 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission. 19 * without specific prior written permission.
22 * 20 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -53,80 +51,200 @@
53 * --Copyright-- 51 * --Copyright--
54 */ 52 */
55 53
56#if defined(LIBC_SCCS) && !defined(lint) 54#ifndef INET6
57#if 0 55#define INET6
58static char sccsid[] = "@(#)res_init.c 8.1 (Berkeley) 6/7/93";
59static char rcsid[] = "$Id: res_init.c,v 4.9.1.1 1993/05/02 22:43:03 vixie Rel ";
60#else
61static char rcsid[] = "$NetBSD: res_init.c,v 1.8 1995/06/03 22:33:36 mycroft Exp $";
62#endif 56#endif
63#endif /* LIBC_SCCS and not lint */
64 57
58#include <sys/types.h>
65#include <sys/param.h> 59#include <sys/param.h>
66#include <sys/socket.h> 60#include <sys/socket.h>
61#include <sys/time.h>
62#include <sys/stat.h>
67#include <netinet/in.h> 63#include <netinet/in.h>
68#include <arpa/inet.h> 64#include <arpa/inet.h>
69#include <arpa/nameser.h> 65#include <arpa/nameser.h>
66
67#include <stdio.h>
68#include <ctype.h>
70#include <resolv.h> 69#include <resolv.h>
71#include <unistd.h> 70#include <unistd.h>
72#include <stdio.h>
73#include <stdlib.h> 71#include <stdlib.h>
74#include <string.h> 72#include <string.h>
73#ifdef INET6
74#include <netdb.h>
75#endif /* INET6 */
75 76
76static void res_setoptions __P((char *, char *)); 77#include "thread_private.h"
77static u_int32_t net_mask __P((struct in_addr)); 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
78 109
79/* 110/*
80 * Resolver state default settings 111 * Resolver state default settings.
81 */ 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);
82 122
83struct __res_state _res = { 123struct __res_state_ext _res_ext;
84 RES_TIMEOUT, /* retransmition time interval */ 124#endif /* INET6 */
85 4, /* number of times to retransmit */ 125
86 RES_DEFAULT, /* options flags */ 126int __res_chktime = 30;
87 1, /* number of name servers */
88};
89 127
90/* 128/*
91 * Set up default settings. If the configuration file exist, the values 129 * Set up default settings. If the configuration file exist, the values
92 * there will have precedence. Otherwise, the server address is set to 130 * there will have precedence. Otherwise, the server address is set to
93 * INADDR_ANY and the default domain name comes from the gethostname(). 131 * INADDR_ANY and the default domain name comes from the gethostname().
94 * 132 *
95 * The configuration file should only be used if you want to redefine your 133 * An interrim version of this code (BIND 4.9, pre-4.4BSD) used 127.0.0.1
96 * domain or run without a server on your machine. 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.
97 * 146 *
98 * Return 0 if completes successfully, -1 on error 147 * Return 0 if completes successfully, -1 on error
99 */ 148 */
100res_init() 149int
150res_init(void)
101{ 151{
102 register FILE *fp; 152
103 register char *cp, **pp, *net; 153 return (_res_init(1));
104 register int n; 154}
105 char buf[BUFSIZ], buf2[BUFSIZ]; 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 int findex;
169 char buf[BUFSIZ];
106 int nserv = 0; /* number of nameserver records read from file */ 170 int nserv = 0; /* number of nameserver records read from file */
107 int haveenv = 0; 171 int haveenv = 0;
108 int havesearch = 0; 172 int havesearch = 0;
173 size_t len;
174#ifdef RESOLVSORT
109 int nsort = 0; 175 int nsort = 0;
110 u_long mask; 176 char *net;
177#endif
178#ifndef RFC1535
179 int dots;
180#endif
181
182 if (!usercall && _resp->options & RES_INIT &&
183 _resp->reschktime >= time(NULL))
184 return (0);
185 _resp->reschktime = time(NULL) + __res_chktime;
186 if (stat(_PATH_RESCONF, &sb) != -1) {
187 if (!usercall && timespeccmp(&sb.st_mtimespec,
188 &_resp->restimespec, ==))
189 return (0);
190 else
191 _resp->restimespec = sb.st_mtimespec;
192 } else {
193 /*
194 * Lost the file, in chroot?
195 * Don't trash settings
196 */
197 if (!usercall && timespecisset(&_resp->restimespec))
198 return (0);
199 }
200
201
202 /*
203 * These three fields used to be statically initialized. This made
204 * it hard to use this code in a shared library. It is necessary,
205 * now that we're doing dynamic initialization here, that we preserve
206 * the old semantics: if an application modifies one of these three
207 * fields of _res before res_init() is called, res_init() will not
208 * alter them. Of course, if an application is setting them to
209 * _zero_ before calling res_init(), hoping to override what used
210 * to be the static default, we can't detect it and unexpected results
211 * will follow. Zero for any of these fields would make no sense,
212 * so one can safely assume that the applications were already getting
213 * unexpected results.
214 *
215 * _res.options is tricky since some apps were known to diddle the bits
216 * before res_init() was first called. We can't replicate that semantic
217 * with dynamic initialization (they may have turned bits off that are
218 * set in RES_DEFAULT). Our solution is to declare such applications
219 * "broken". They could fool us by setting RES_INIT but none do (yet).
220 */
221 if (!_resp->retrans)
222 _resp->retrans = RES_TIMEOUT;
223 if (!_resp->retry)
224 _resp->retry = 4;
225 if (!(_resp->options & RES_INIT))
226 _resp->options = RES_DEFAULT;
111 227
112 _res.nsaddr.sin_len = sizeof(struct sockaddr_in);
113 _res.nsaddr.sin_family = AF_INET;
114 _res.nsaddr.sin_port = htons(NAMESERVER_PORT);
115#ifdef USELOOPBACK 228#ifdef USELOOPBACK
116 _res.nsaddr.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1); 229 _resp->nsaddr.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1);
117#else 230#else
118 _res.nsaddr.sin_addr.s_addr = INADDR_ANY; 231 _resp->nsaddr.sin_addr.s_addr = INADDR_ANY;
232#endif
233 _resp->nsaddr.sin_family = AF_INET;
234 _resp->nsaddr.sin_port = htons(NAMESERVER_PORT);
235 _resp->nsaddr.sin_len = sizeof(struct sockaddr_in);
236#ifdef INET6
237 if (sizeof(_res_extp->nsaddr) >= _resp->nsaddr.sin_len)
238 memcpy(&_res_extp->nsaddr, &_resp->nsaddr, _resp->nsaddr.sin_len);
119#endif 239#endif
120 _res.nscount = 1; 240 _resp->nscount = 1;
121 _res.ndots = 1; 241 _resp->ndots = 1;
122 _res.pfcode = 0; 242 _resp->pfcode = 0;
123 strncpy(_res.lookups, "f", sizeof _res.lookups); 243 strlcpy(_resp->lookups, "f", sizeof _resp->lookups);
124 244
125 /* Allow user to override the local domain definition */ 245 /* Allow user to override the local domain definition */
126 if ((cp = getenv("LOCALDOMAIN")) != NULL) { 246 if (issetugid() == 0 && (cp = getenv("LOCALDOMAIN")) != NULL) {
127 (void)strncpy(_res.defdname, cp, sizeof(_res.defdname) - 1); 247 strlcpy(_resp->defdname, cp, sizeof(_resp->defdname));
128 if ((cp = strpbrk(_res.defdname, " \t\n")) != NULL)
129 *cp = '\0';
130 haveenv++; 248 haveenv++;
131 249
132 /* 250 /*
@@ -136,11 +254,11 @@ res_init()
136 * one that they want to use as an individual (even more 254 * one that they want to use as an individual (even more
137 * important now that the rfc1535 stuff restricts searches) 255 * important now that the rfc1535 stuff restricts searches)
138 */ 256 */
139 cp = _res.defdname; 257 cp = _resp->defdname;
140 pp = _res.dnsrch; 258 pp = _resp->dnsrch;
141 *pp++ = cp; 259 *pp++ = cp;
142 for (n = 0; *cp && pp < _res.dnsrch + MAXDNSRCH; cp++) { 260 for (n = 0; *cp && pp < _resp->dnsrch + MAXDNSRCH; cp++) {
143 if (*cp == '\n') /* silly backwards compat */ 261 if (*cp == '\n') /* silly backwards compat */
144 break; 262 break;
145 else if (*cp == ' ' || *cp == '\t') { 263 else if (*cp == ' ' || *cp == '\t') {
146 *cp = 0; 264 *cp = 0;
@@ -158,16 +276,67 @@ res_init()
158 *pp++ = 0; 276 *pp++ = 0;
159 } 277 }
160 278
279#define MATCH(line, name) \
280 (!strncmp(line, name, sizeof(name) - 1) && \
281 (line[sizeof(name) - 1] == ' ' || \
282 line[sizeof(name) - 1] == '\t'))
283
284 /* initialize family lookup preference: inet4 first */
285 _resp->family[0] = AF_INET;
286 _resp->family[1] = AF_INET6;
161 if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) { 287 if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) {
162 strncpy(_res.lookups, "bf", sizeof _res.lookups); 288 strlcpy(_resp->lookups, "bf", sizeof _resp->lookups);
163 289
164 /* read the config file */ 290 /* read the config file */
165 while (fgets(buf, sizeof(buf), fp) != NULL) { 291 buf[0] = '\0';
292 while ((cp = fgetln(fp, &len)) != NULL) {
293 /* skip lines that are too long */
294 if (len >= sizeof(buf))
295 continue;
296 (void)memcpy(buf, cp, len);
297 buf[len] = '\0';
166 /* skip comments */ 298 /* skip comments */
167 if ((*buf == ';') || (*buf == '#')) 299 if ((cp = strpbrk(buf, ";#")) != NULL)
300 *cp = '\0';
301 if (buf[0] == '\0')
168 continue; 302 continue;
303 /* set family lookup order */
304 if (MATCH(buf, "family")) {
305 cp = buf + sizeof("family") - 1;
306 cp += strspn(cp, " \t");
307 cp[strcspn(cp, "\n")] = '\0';
308 findex = 0;
309 _resp->family[0] = _resp->family[1] = -1;
310#define INETLEN (sizeof("inetX") - 1)
311 while (*cp != '\0' && findex < 2) {
312 if (!strncmp(cp, "inet6", INETLEN)) {
313 _resp->family[findex] = AF_INET6;
314 cp += INETLEN;
315 } else if (!strncmp(cp, "inet4", INETLEN)) {
316 _resp->family[findex] = AF_INET;
317 cp += INETLEN;
318 } else {
319 _resp->family[0] = -1;
320 break;
321 }
322 if (*cp != ' ' && *cp != '\t' && *cp != '\0') {
323 _resp->family[findex] = -1;
324 break;
325 }
326 findex++;
327 cp += strspn(cp, " \t");
328 }
329
330 if (_resp->family[0] == -1) {
331 /* line contains errors, reset to defaults */
332 _resp->family[0] = AF_INET;
333 _resp->family[1] = AF_INET6;
334 }
335 if (_resp->family[0] == _resp->family[1])
336 _resp->family[1] = -1;
337 }
169 /* read default domain name */ 338 /* read default domain name */
170 if (!strncmp(buf, "domain", sizeof("domain") - 1)) { 339 if (MATCH(buf, "domain")) {
171 if (haveenv) /* skip if have from environ */ 340 if (haveenv) /* skip if have from environ */
172 continue; 341 continue;
173 cp = buf + sizeof("domain") - 1; 342 cp = buf + sizeof("domain") - 1;
@@ -175,18 +344,17 @@ res_init()
175 cp++; 344 cp++;
176 if ((*cp == '\0') || (*cp == '\n')) 345 if ((*cp == '\0') || (*cp == '\n'))
177 continue; 346 continue;
178 (void)strncpy(_res.defdname, cp, 347 strlcpy(_resp->defdname, cp, sizeof(_resp->defdname));
179 sizeof(_res.defdname) - 1); 348 if ((cp = strpbrk(_resp->defdname, " \t\n")) != NULL)
180 if ((cp = strpbrk(_res.defdname, " \t\n")) != NULL)
181 *cp = '\0'; 349 *cp = '\0';
182 havesearch = 0; 350 havesearch = 0;
183 continue; 351 continue;
184 } 352 }
185 /* lookup types */ 353 /* lookup types */
186 if (!strncmp(buf, "lookup", sizeof("lookup") -1)) { 354 if (MATCH(buf, "lookup")) {
187 char *sp = NULL; 355 char *sp = NULL;
188 356
189 bzero(_res.lookups, sizeof _res.lookups); 357 bzero(_resp->lookups, sizeof _resp->lookups);
190 cp = buf + sizeof("lookup") - 1; 358 cp = buf + sizeof("lookup") - 1;
191 for (n = 0;; cp++) { 359 for (n = 0;; cp++) {
192 if (n == MAXDNSLUS) 360 if (n == MAXDNSLUS)
@@ -194,14 +362,14 @@ res_init()
194 if ((*cp == '\0') || (*cp == '\n')) { 362 if ((*cp == '\0') || (*cp == '\n')) {
195 if (sp) { 363 if (sp) {
196 if (*sp=='y' || *sp=='b' || *sp=='f') 364 if (*sp=='y' || *sp=='b' || *sp=='f')
197 _res.lookups[n++] = *sp; 365 _resp->lookups[n++] = *sp;
198 sp = NULL; 366 sp = NULL;
199 } 367 }
200 break; 368 break;
201 } else if ((*cp == ' ') || (*cp == '\t') || (*cp == ',')) { 369 } else if ((*cp == ' ') || (*cp == '\t') || (*cp == ',')) {
202 if (sp) { 370 if (sp) {
203 if (*sp=='y' || *sp=='b' || *sp=='f') 371 if (*sp=='y' || *sp=='b' || *sp=='f')
204 _res.lookups[n++] = *sp; 372 _resp->lookups[n++] = *sp;
205 sp = NULL; 373 sp = NULL;
206 } 374 }
207 } else if (sp == NULL) 375 } else if (sp == NULL)
@@ -210,7 +378,7 @@ res_init()
210 continue; 378 continue;
211 } 379 }
212 /* set search list */ 380 /* set search list */
213 if (!strncmp(buf, "search", sizeof("search") - 1)) { 381 if (MATCH(buf, "search")) {
214 if (haveenv) /* skip if have from environ */ 382 if (haveenv) /* skip if have from environ */
215 continue; 383 continue;
216 cp = buf + sizeof("search") - 1; 384 cp = buf + sizeof("search") - 1;
@@ -218,18 +386,17 @@ res_init()
218 cp++; 386 cp++;
219 if ((*cp == '\0') || (*cp == '\n')) 387 if ((*cp == '\0') || (*cp == '\n'))
220 continue; 388 continue;
221 (void)strncpy(_res.defdname, cp, 389 strlcpy(_resp->defdname, cp, sizeof(_resp->defdname));
222 sizeof(_res.defdname) - 1); 390 if ((cp = strchr(_resp->defdname, '\n')) != NULL)
223 if ((cp = strchr(_res.defdname, '\n')) != NULL)
224 *cp = '\0'; 391 *cp = '\0';
225 /* 392 /*
226 * Set search list to be blank-separated strings 393 * Set search list to be blank-separated strings
227 * on rest of line. 394 * on rest of line.
228 */ 395 */
229 cp = _res.defdname; 396 cp = _resp->defdname;
230 pp = _res.dnsrch; 397 pp = _resp->dnsrch;
231 *pp++ = cp; 398 *pp++ = cp;
232 for (n = 0; *cp && pp < _res.dnsrch + MAXDNSRCH; cp++) { 399 for (n = 0; *cp && pp < _resp->dnsrch + MAXDNSRCH; cp++) {
233 if (*cp == ' ' || *cp == '\t') { 400 if (*cp == ' ' || *cp == '\t') {
234 *cp = 0; 401 *cp = 0;
235 n = 1; 402 n = 1;
@@ -247,130 +414,274 @@ res_init()
247 continue; 414 continue;
248 } 415 }
249 /* read nameservers to query */ 416 /* read nameservers to query */
250 if (!strncmp(buf, "nameserver", sizeof("nameserver") - 1) && 417 if (MATCH(buf, "nameserver") && nserv < MAXNS) {
251 nserv < MAXNS) { 418 char *q;
252 struct in_addr a; 419 struct addrinfo hints, *res;
420 char pbuf[NI_MAXSERV];
253 421
254 cp = buf + sizeof("nameserver") - 1; 422 cp = buf + sizeof("nameserver") - 1;
255 while (*cp == ' ' || *cp == '\t') 423 while (*cp == ' ' || *cp == '\t')
256 cp++; 424 cp++;
257 if ((*cp != '\0') && (*cp != '\n') && inet_aton(cp, &a)) { 425 if ((*cp == '\0') || (*cp == '\n'))
258 _res.nsaddr_list[nserv].sin_len = sizeof(struct sockaddr_in); 426 continue;
259 _res.nsaddr_list[nserv].sin_family = AF_INET; 427 for (q = cp; *q; q++) {
260 _res.nsaddr_list[nserv].sin_port = 428 if (isspace(*q)) {
261 htons(NAMESERVER_PORT); 429 *q = '\0';
262 _res.nsaddr_list[nserv].sin_addr = a; 430 break;
431 }
432 }
433
434 /* Handle addresses enclosed in [] */
435 *pbuf = '\0';
436 if (*cp == '[') {
437 cp++;
438 if ((q = strchr(cp, ']')) == NULL)
439 continue;
440 *q++ = '\0';
441 /* Extract port, if specified */
442 if (*q++ == ':') {
443 if (strlcpy(pbuf, q, sizeof(pbuf)) >= sizeof(pbuf))
444 continue;
445 }
446 }
447 if (*pbuf == '\0')
448 snprintf(pbuf, sizeof(pbuf), "%u", NAMESERVER_PORT);
449
450 memset(&hints, 0, sizeof(hints));
451 hints.ai_flags = AI_NUMERICHOST;
452 hints.ai_socktype = SOCK_DGRAM;
453 res = NULL;
454 if (getaddrinfo(cp, pbuf, &hints, &res) == 0 &&
455 res->ai_next == NULL) {
456 if (res->ai_addrlen <= sizeof(_res_extp->nsaddr_list[nserv])) {
457 memcpy(&_res_extp->nsaddr_list[nserv], res->ai_addr,
458 res->ai_addrlen);
459 } else {
460 memset(&_res_extp->nsaddr_list[nserv], 0,
461 sizeof(_res_extp->nsaddr_list[nserv]));
462 }
463 if (res->ai_addrlen <= sizeof(_resp->nsaddr_list[nserv])) {
464 memcpy(&_resp->nsaddr_list[nserv], res->ai_addr,
465 res->ai_addrlen);
466 } else {
467 memset(&_resp->nsaddr_list[nserv], 0,
468 sizeof(_resp->nsaddr_list[nserv]));
469 }
263 nserv++; 470 nserv++;
264 } 471 }
472 if (res)
473 freeaddrinfo(res);
265 continue; 474 continue;
266 } 475 }
267 if (!strncmp(buf, "sortlist", sizeof("sortlist") - 1)) { 476#ifdef RESOLVSORT
477 if (MATCH(buf, "sortlist")) {
268 struct in_addr a; 478 struct in_addr a;
479#ifdef INET6
480 struct in6_addr a6;
481 int m, i;
482 u_char *u;
483#endif /* INET6 */
269 484
270 cp = buf + sizeof("sortlist") - 1; 485 cp = buf + sizeof("sortlist") - 1;
271 while (*cp == ' ' || *cp == '\t') 486 while (nsort < MAXRESOLVSORT) {
272 cp++; 487 while (*cp == ' ' || *cp == '\t')
273 while (sscanf(cp,"%[0-9./]s", buf2) && nsort < MAXRESOLVSORT) { 488 cp++;
274 if (net = strchr(buf2, '/')) 489 if (*cp == '\0' || *cp == '\n' || *cp == ';')
275 *net = '\0'; 490 break;
276 if (inet_aton(buf2, &a)) { 491 net = cp;
277 _res.sort_list[nsort].addr = a; 492 while (*cp && !ISSORTMASK(*cp) && *cp != ';' &&
278 if (net && inet_aton(net+1, &a)) { 493 isascii(*cp) && !isspace(*cp))
279 _res.sort_list[nsort].mask = a.s_addr; 494 cp++;
495 n = *cp;
496 *cp = 0;
497 if (inet_aton(net, &a)) {
498 _resp->sort_list[nsort].addr = a;
499 if (ISSORTMASK(n)) {
500 *cp++ = n;
501 net = cp;
502 while (*cp && *cp != ';' &&
503 isascii(*cp) && !isspace(*cp))
504 cp++;
505 n = *cp;
506 *cp = 0;
507 if (inet_aton(net, &a)) {
508 _resp->sort_list[nsort].mask = a.s_addr;
509 } else {
510 _resp->sort_list[nsort].mask =
511 net_mask(_resp->sort_list[nsort].addr);
512 }
280 } else { 513 } else {
281 _res.sort_list[nsort].mask = 514 _resp->sort_list[nsort].mask =
282 net_mask(_res.sort_list[nsort].addr); 515 net_mask(_resp->sort_list[nsort].addr);
283 } 516 }
517#ifdef INET6
518 _res_extp->sort_list[nsort].af = AF_INET;
519 _res_extp->sort_list[nsort].addr.ina =
520 _resp->sort_list[nsort].addr;
521 _res_extp->sort_list[nsort].mask.ina.s_addr =
522 _resp->sort_list[nsort].mask;
523#endif /* INET6 */
284 nsort++; 524 nsort++;
285 } 525 }
286 if (net) 526#ifdef INET6
287 *net = '/'; 527 else if (inet_pton(AF_INET6, net, &a6) == 1) {
288 cp += strlen(buf2); 528 _res_extp->sort_list[nsort].af = AF_INET6;
289 while (*cp == ' ' || *cp == '\t') 529 _res_extp->sort_list[nsort].addr.in6a = a6;
290 cp++; 530 u = (u_char *)&_res_extp->sort_list[nsort].mask.in6a;
531 *cp++ = n;
532 net = cp;
533 while (*cp && *cp != ';' &&
534 isascii(*cp) && !isspace(*cp))
535 cp++;
536 m = n;
537 n = *cp;
538 *cp = 0;
539 switch (m) {
540 case '/':
541 m = atoi(net);
542 break;
543 case '&':
544 if (inet_pton(AF_INET6, net, u) == 1) {
545 m = -1;
546 break;
547 }
548 /* FALLTHROUGH */
549 default:
550 m = sizeof(struct in6_addr) * NBBY;
551 break;
552 }
553 if (m >= 0) {
554 for (i = 0; i < sizeof(struct in6_addr); i++) {
555 if (m <= 0) {
556 *u = 0;
557 } else {
558 m -= NBBY;
559 *u = (u_char)~0;
560 if (m < 0)
561 *u <<= -m;
562 }
563 u++;
564 }
565 }
566 nsort++;
567 }
568#endif /* INET6 */
569 *cp = n;
291 } 570 }
292 continue; 571 continue;
293 } 572 }
294 if (!strncmp(buf, "options", sizeof("options") -1)) { 573#endif
574 if (MATCH(buf, "options")) {
295 res_setoptions(buf + sizeof("options") - 1, "conf"); 575 res_setoptions(buf + sizeof("options") - 1, "conf");
296 continue; 576 continue;
297 } 577 }
298 } 578 }
299 if (nserv > 1) 579 if (nserv > 1)
300 _res.nscount = nserv; 580 _resp->nscount = nserv;
301 _res.nsort = nsort; 581#ifdef RESOLVSORT
582 _resp->nsort = nsort;
583#endif
302 (void) fclose(fp); 584 (void) fclose(fp);
303 } 585 }
304 if (_res.defdname[0] == 0) { 586 if (_resp->defdname[0] == 0 &&
305 if (gethostname(buf, sizeof(_res.defdname) - 1) == 0 && 587 gethostname(buf, sizeof(_resp->defdname) - 1) == 0 &&
306 (cp = strchr(buf, '.'))) 588 (cp = strchr(buf, '.')) != NULL)
307 (void)strcpy(_res.defdname, cp + 1); 589 {
590 strlcpy(_resp->defdname, cp + 1,
591 sizeof(_resp->defdname));
308 } 592 }
309 593
310 /* find components of local domain that might be searched */ 594 /* find components of local domain that might be searched */
311 if (havesearch == 0) { 595 if (havesearch == 0) {
312 pp = _res.dnsrch; 596 pp = _resp->dnsrch;
313 *pp++ = _res.defdname; 597 *pp++ = _resp->defdname;
314#ifndef SEARCH_LOCAL_DOMAINS
315 *pp = NULL; 598 *pp = NULL;
316#else 599
317 for (cp = _res.defdname, n = 0; *cp; cp++) 600#ifndef RFC1535
318 if (*cp == '.') 601 dots = 0;
319 n++; 602 for (cp = _resp->defdname; *cp; cp++)
320 cp = _res.defdname; 603 dots += (*cp == '.');
321 for (; n >= LOCALDOMAINPARTS && pp < _res.dnsrch + MAXDFLSRCH; 604
322 n--) { 605 cp = _resp->defdname;
323 cp = strchr(cp, '.'); 606 while (pp < _resp->dnsrch + MAXDFLSRCH) {
324 *pp++ = ++cp; 607 if (dots < LOCALDOMAINPARTS)
608 break;
609 cp = strchr(cp, '.') + 1; /* we know there is one */
610 *pp++ = cp;
611 dots--;
325 } 612 }
326 *pp++ = 0; 613 *pp = NULL;
327#endif 614#ifdef DEBUG
615 if (_resp->options & RES_DEBUG) {
616 printf(";; res_init()... default dnsrch list:\n");
617 for (pp = _resp->dnsrch; *pp; pp++)
618 printf(";;\t%s\n", *pp);
619 printf(";;\t..END..\n");
620 }
621#endif /* DEBUG */
622#endif /* !RFC1535 */
328 } 623 }
329 624
330 if ((cp = getenv("RES_OPTIONS")) != NULL) 625 if (issetugid())
626 _resp->options |= RES_NOALIASES;
627 else if ((cp = getenv("RES_OPTIONS")) != NULL)
331 res_setoptions(cp, "env"); 628 res_setoptions(cp, "env");
332 _res.options |= RES_INIT; 629 _resp->options |= RES_INIT;
333 return (0); 630 return (0);
334} 631}
335 632
633/* ARGSUSED */
336static void 634static void
337res_setoptions(options, source) 635res_setoptions(char *options, char *source)
338 char *options, *source;
339{ 636{
637 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
340 char *cp = options; 638 char *cp = options;
341 int i; 639 char *endp;
640 long l;
342 641
343#ifdef DEBUG 642#ifdef DEBUG
344 if (_res.options & RES_DEBUG) { 643 if (_resp->options & RES_DEBUG)
345 printf(";; res_setoptions(\"%s\", \"%s\")...\n", 644 printf(";; res_setoptions(\"%s\", \"%s\")...\n",
346 options, source); 645 options, source);
347 }
348#endif 646#endif
349 while (*cp) { 647 while (*cp) {
350 /* skip leading and inner runs of spaces */ 648 /* skip leading and inner runs of spaces */
351 while (*cp == ' ' || *cp == '\t') 649 while (*cp == ' ' || *cp == '\t')
352 cp++; 650 cp++;
353 /* search for and process individual options */ 651 /* search for and process individual options */
354 if (!strncmp(cp, "ndots:", sizeof("ndots:")-1)) { 652 if (!strncmp(cp, "ndots:", sizeof("ndots:") - 1)) {
355 i = atoi(cp + sizeof("ndots:") - 1); 653 char *p = cp + sizeof("ndots:") - 1;
356 if (i <= RES_MAXNDOTS) 654 l = strtol(p, &endp, 10);
357 _res.ndots = i; 655 if (l >= 0 && endp != p &&
358 else 656 (*endp = '\0' || isspace(*endp))) {
359 _res.ndots = RES_MAXNDOTS; 657 if (l <= RES_MAXNDOTS)
658 _resp->ndots = l;
659 else
660 _resp->ndots = RES_MAXNDOTS;
360#ifdef DEBUG 661#ifdef DEBUG
361 if (_res.options & RES_DEBUG) { 662 if (_resp->options & RES_DEBUG)
362 printf(";;\tndots=%d\n", _res.ndots); 663 printf(";;\tndots=%u\n", _resp->ndots);
363 }
364#endif 664#endif
365 } else if (!strncmp(cp, "debug", sizeof("debug")-1)) { 665 }
666 } else if (!strncmp(cp, "debug", sizeof("debug") - 1)) {
366#ifdef DEBUG 667#ifdef DEBUG
367 if (!(_res.options & RES_DEBUG)) { 668 if (!(_resp->options & RES_DEBUG)) {
368 printf(";; res_setoptions(\"%s\", \"%s\")..\n", 669 printf(";; res_setoptions(\"%s\", \"%s\")..\n",
369 options, source); 670 options, source);
370 _res.options |= RES_DEBUG; 671 _resp->options |= RES_DEBUG;
371 } 672 }
372 printf(";;\tdebug\n"); 673 printf(";;\tdebug\n");
373#endif 674#endif
675 } else if (!strncmp(cp, "inet6", sizeof("inet6") - 1)) {
676 _resp->options |= RES_USE_INET6;
677 } else if (!strncmp(cp, "insecure1", sizeof("insecure1") - 1)) {
678 _resp->options |= RES_INSECURE1;
679 } else if (!strncmp(cp, "insecure2", sizeof("insecure2") - 1)) {
680 _resp->options |= RES_INSECURE2;
681 } else if (!strncmp(cp, "edns0", sizeof("edns0") - 1)) {
682 _resp->options |= RES_USE_EDNS0;
683 } else if (!strncmp(cp, "tcp", sizeof("tcp") - 1)) {
684 _resp->options |= RES_USEVC;
374 } else { 685 } else {
375 /* XXX - print a warning here? */ 686 /* XXX - print a warning here? */
376 } 687 }
@@ -380,15 +691,17 @@ res_setoptions(options, source)
380 } 691 }
381} 692}
382 693
694#ifdef RESOLVSORT
695/* XXX - should really support CIDR which means explicit masks always. */
383static u_int32_t 696static u_int32_t
384net_mask(in) /* XXX - should really use system's version of this */ 697net_mask(struct in_addr in) /* XXX - should really use system's version of this */
385 struct in_addr in;
386{ 698{
387 register u_int32_t i = ntohl(in.s_addr); 699 u_int32_t i = ntohl(in.s_addr);
388 700
389 if (IN_CLASSA(i)) 701 if (IN_CLASSA(i))
390 return (htonl(IN_CLASSA_NET)); 702 return (htonl(IN_CLASSA_NET));
391 if (IN_CLASSB(i)) 703 else if (IN_CLASSB(i))
392 return (htonl(IN_CLASSB_NET)); 704 return (htonl(IN_CLASSB_NET));
393 return (htonl(IN_CLASSC_NET)); 705 return (htonl(IN_CLASSC_NET));
394} 706}
707#endif
diff --git a/src/lib/libc/net/res_mkquery.c b/src/lib/libc/net/res_mkquery.c
index 25f025e147..5c6b273abe 100644
--- a/src/lib/libc/net/res_mkquery.c
+++ b/src/lib/libc/net/res_mkquery.c
@@ -1,9 +1,11 @@
1/* $NetBSD: res_mkquery.c,v 1.5 1995/02/25 06:20:58 cgd Exp $ */ 1/* $OpenBSD: res_mkquery.c,v 1.17 2005/08/06 20:30:04 espie Exp $ */
2 2
3/*- 3/*
4 * ++Copyright++ 1985, 1993
5 * -
4 * Copyright (c) 1985, 1993 6 * Copyright (c) 1985, 1993
5 * The Regents of the University of California. All rights reserved. 7 * The Regents of the University of California. All rights reserved.
6 * 8 *
7 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
9 * are met: 11 * are met:
@@ -12,14 +14,10 @@
12 * 2. Redistributions in binary form must reproduce the above copyright 14 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 15 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 16 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software 17 * 3. Neither the name of the University nor the names of its contributors
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software 18 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission. 19 * without specific prior written permission.
22 * 20 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -53,101 +51,109 @@
53 * --Copyright-- 51 * --Copyright--
54 */ 52 */
55 53
56#if defined(LIBC_SCCS) && !defined(lint) 54#include <sys/types.h>
57#if 0
58static char sccsid[] = "@(#)res_mkquery.c 8.1 (Berkeley) 6/4/93";
59static char rcsid[] = "$Id: res_mkquery.c,v 4.9.1.2 1993/05/17 10:00:01 vixie Exp ";
60#else
61static char rcsid[] = "$NetBSD: res_mkquery.c,v 1.5 1995/02/25 06:20:58 cgd Exp $";
62#endif
63#endif /* LIBC_SCCS and not lint */
64
65#include <sys/param.h> 55#include <sys/param.h>
66#include <netinet/in.h> 56#include <netinet/in.h>
67#include <arpa/nameser.h> 57#include <arpa/nameser.h>
68#include <resolv.h> 58
69#include <stdio.h> 59#include <stdio.h>
60#include <netdb.h>
61#include <resolv.h>
70#include <string.h> 62#include <string.h>
71 63
64#include "thread_private.h"
65
72/* 66/*
73 * Form all types of queries. 67 * Form all types of queries.
74 * Returns the size of the result or -1. 68 * Returns the size of the result or -1.
75 */ 69 */
76res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen) 70/* ARGSUSED */
77 int op; /* opcode of query */ 71int
78 const char *dname; /* domain name */ 72res_mkquery(int op,
79 int class, type; /* class and type of query */ 73 const char *dname, /* opcode of query */
80 const char *data; /* resource record data */ 74 int class, /* domain name */
81 int datalen; /* length of data */ 75 int type, /* class and type of query */
82 const char *newrr_in; /* new rr for modify or append */ 76 const u_char *data, /* resource record data */
83 char *buf; /* buffer to put query */ 77 int datalen, /* length of data */
84 int buflen; /* size of buffer */ 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 */
85{ 81{
86 register HEADER *hp; 82 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
87 register char *cp; 83 HEADER *hp;
88 register int n; 84 u_char *cp, *ep;
89 struct rrec *newrr = (struct rrec *) newrr_in; 85 int n;
90 char *dnptrs[10], **dpp, **lastdnptr; 86 u_char *dnptrs[20], **dpp, **lastdnptr;
91 87
88 if (_res_init(0) == -1) {
89 h_errno = NETDB_INTERNAL;
90 return (-1);
91 }
92#ifdef DEBUG 92#ifdef DEBUG
93 if (_res.options & RES_DEBUG) 93 if (_resp->options & RES_DEBUG)
94 printf(";; res_mkquery(%d, %s, %d, %d)\n", 94 printf(";; res_mkquery(%d, %s, %d, %d)\n",
95 op, dname, class, type); 95 op, dname, class, type);
96#endif 96#endif
97 /* 97 /*
98 * Initialize header fields. 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.
99 */ 103 */
100 if ((buf == NULL) || (buflen < sizeof(HEADER))) 104
101 return(-1); 105 if ((buf == NULL) || (buflen < HFIXEDSZ))
102 bzero(buf, sizeof(HEADER)); 106 return (-1);
107 bzero(buf, HFIXEDSZ);
103 hp = (HEADER *) buf; 108 hp = (HEADER *) buf;
104 hp->id = htons(++_res.id); 109 _resp->id = res_randomid();
110 hp->id = htons(_resp->id);
105 hp->opcode = op; 111 hp->opcode = op;
106 hp->pr = (_res.options & RES_PRIMARY) != 0; 112 hp->rd = (_resp->options & RES_RECURSE) != 0;
107 hp->rd = (_res.options & RES_RECURSE) != 0;
108 hp->rcode = NOERROR; 113 hp->rcode = NOERROR;
109 cp = buf + sizeof(HEADER); 114 cp = buf + HFIXEDSZ;
110 buflen -= sizeof(HEADER); 115 ep = buf + buflen;
111 dpp = dnptrs; 116 dpp = dnptrs;
112 *dpp++ = buf; 117 *dpp++ = buf;
113 *dpp++ = NULL; 118 *dpp++ = NULL;
114 lastdnptr = dnptrs + sizeof(dnptrs)/sizeof(dnptrs[0]); 119 lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0];
115 /* 120 /*
116 * perform opcode specific processing 121 * perform opcode specific processing
117 */ 122 */
118 switch (op) { 123 switch (op) {
119 case QUERY: 124 case QUERY: /*FALLTHROUGH*/
120 if ((buflen -= QFIXEDSZ) < 0) 125 case NS_NOTIFY_OP:
121 return(-1); 126 if (ep - cp < QFIXEDSZ)
122 if ((n = dn_comp((u_char *)dname, (u_char *)cp, buflen, 127 return (-1);
123 (u_char **)dnptrs, (u_char **)lastdnptr)) < 0) 128 if ((n = dn_comp(dname, cp, ep - cp - QFIXEDSZ, dnptrs,
129 lastdnptr)) < 0)
124 return (-1); 130 return (-1);
125 cp += n; 131 cp += n;
126 buflen -= n; 132 __putshort(type, cp);
127 __putshort(type, (u_char *)cp); 133 cp += INT16SZ;
128 cp += sizeof(u_int16_t); 134 __putshort(class, cp);
129 __putshort(class, (u_char *)cp); 135 cp += INT16SZ;
130 cp += sizeof(u_int16_t);
131 hp->qdcount = htons(1); 136 hp->qdcount = htons(1);
132 if (op == QUERY || data == NULL) 137 if (op == QUERY || data == NULL)
133 break; 138 break;
134 /* 139 /*
135 * Make an additional record for completion domain. 140 * Make an additional record for completion domain.
136 */ 141 */
137 buflen -= RRFIXEDSZ; 142 if (ep - cp < RRFIXEDSZ)
138 if ((n = dn_comp((u_char *)data, (u_char *)cp, buflen, 143 return (-1);
139 (u_char **)dnptrs, (u_char **)lastdnptr)) < 0) 144 n = dn_comp((char *)data, cp, ep - cp - RRFIXEDSZ, dnptrs,
145 lastdnptr);
146 if (n < 0)
140 return (-1); 147 return (-1);
141 cp += n; 148 cp += n;
142 buflen -= n; 149 __putshort(T_NULL, cp);
143 __putshort(T_NULL, (u_char *)cp); 150 cp += INT16SZ;
144 cp += sizeof(u_int16_t); 151 __putshort(class, cp);
145 __putshort(class, (u_char *)cp); 152 cp += INT16SZ;
146 cp += sizeof(u_int16_t); 153 __putlong(0, cp);
147 __putlong(0, (u_char *)cp); 154 cp += INT32SZ;
148 cp += sizeof(u_int32_t); 155 __putshort(0, cp);
149 __putshort(0, (u_char *)cp); 156 cp += INT16SZ;
150 cp += sizeof(u_int16_t);
151 hp->arcount = htons(1); 157 hp->arcount = htons(1);
152 break; 158 break;
153 159
@@ -155,82 +161,72 @@ res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen)
155 /* 161 /*
156 * Initialize answer section 162 * Initialize answer section
157 */ 163 */
158 if (buflen < 1 + RRFIXEDSZ + datalen) 164 if (ep - cp < 1 + RRFIXEDSZ + datalen)
159 return (-1); 165 return (-1);
160 *cp++ = '\0'; /* no domain name */ 166 *cp++ = '\0'; /* no domain name */
161 __putshort(type, (u_char *)cp);
162 cp += sizeof(u_int16_t);
163 __putshort(class, (u_char *)cp);
164 cp += sizeof(u_int16_t);
165 __putlong(0, (u_char *)cp);
166 cp += sizeof(u_int32_t);
167 __putshort(datalen, (u_char *)cp);
168 cp += sizeof(u_int16_t);
169 if (datalen) {
170 bcopy(data, cp, datalen);
171 cp += datalen;
172 }
173 hp->ancount = htons(1);
174 break;
175
176#ifdef ALLOW_UPDATES
177 /*
178 * For UPDATEM/UPDATEMA, do UPDATED/UPDATEDA followed by UPDATEA
179 * (Record to be modified is followed by its replacement in msg.)
180 */
181 case UPDATEM:
182 case UPDATEMA:
183
184 case UPDATED:
185 /*
186 * The res code for UPDATED and UPDATEDA is the same; user
187 * calls them differently: specifies data for UPDATED; server
188 * ignores data if specified for UPDATEDA.
189 */
190 case UPDATEDA:
191 buflen -= RRFIXEDSZ + datalen;
192 if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
193 return (-1);
194 cp += n;
195 __putshort(type, cp); 167 __putshort(type, cp);
196 cp += sizeof(u_int16_t); 168 cp += INT16SZ;
197 __putshort(class, cp); 169 __putshort(class, cp);
198 cp += sizeof(u_int16_t); 170 cp += INT16SZ;
199 __putlong(0, cp); 171 __putlong(0, cp);
200 cp += sizeof(u_int32_t); 172 cp += INT32SZ;
201 __putshort(datalen, cp); 173 __putshort(datalen, cp);
202 cp += sizeof(u_int16_t); 174 cp += INT16SZ;
203 if (datalen) { 175 if (datalen) {
204 bcopy(data, cp, datalen); 176 bcopy(data, cp, datalen);
205 cp += datalen; 177 cp += datalen;
206 } 178 }
207 if ( (op == UPDATED) || (op == UPDATEDA) ) { 179 hp->ancount = htons(1);
208 hp->ancount = htons(0);
209 break;
210 }
211 /* Else UPDATEM/UPDATEMA, so drop into code for UPDATEA */
212
213 case UPDATEA: /* Add new resource record */
214 buflen -= RRFIXEDSZ + datalen;
215 if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
216 return (-1);
217 cp += n;
218 __putshort(newrr->r_type, cp);
219 cp += sizeof(u_int16_t);
220 __putshort(newrr->r_class, cp);
221 cp += sizeof(u_int16_t);
222 __putlong(0, cp);
223 cp += sizeof(u_int32_t);
224 __putshort(newrr->r_size, cp);
225 cp += sizeof(u_int16_t);
226 if (newrr->r_size) {
227 bcopy(newrr->r_data, cp, newrr->r_size);
228 cp += newrr->r_size;
229 }
230 hp->ancount = htons(0);
231 break; 180 break;
232 181
233#endif /* ALLOW_UPDATES */ 182 default:
183 return (-1);
234 } 184 }
235 return (cp - buf); 185 return (cp - buf);
236} 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
index 7649462e56..1485abb2d7 100644
--- a/src/lib/libc/net/res_query.c
+++ b/src/lib/libc/net/res_query.c
@@ -1,9 +1,11 @@
1/* $NetBSD: res_query.c,v 1.9 1995/02/25 06:58:58 cgd Exp $ */ 1/* $OpenBSD: res_query.c,v 1.26 2010/06/29 21:08:54 deraadt Exp $ */
2 2
3/*- 3/*
4 * ++Copyright++ 1988, 1993
5 * -
4 * Copyright (c) 1988, 1993 6 * Copyright (c) 1988, 1993
5 * The Regents of the University of California. All rights reserved. 7 * The Regents of the University of California. All rights reserved.
6 * 8 *
7 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
9 * are met: 11 * are met:
@@ -12,14 +14,10 @@
12 * 2. Redistributions in binary form must reproduce the above copyright 14 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 15 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 16 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software 17 * 3. Neither the name of the University nor the names of its contributors
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software 18 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission. 19 * without specific prior written permission.
22 * 20 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -53,26 +51,22 @@
53 * --Copyright-- 51 * --Copyright--
54 */ 52 */
55 53
56#if defined(LIBC_SCCS) && !defined(lint) 54#include <sys/types.h>
57#if 0
58static char sccsid[] = "@(#)res_query.c 8.1 (Berkeley) 6/4/93";
59static char rcsid[] = "$Id: res_query.c,v 1.1 1993/06/01 09:42:14 vixie Exp vixie ";
60#else
61static char rcsid[] = "$NetBSD: res_query.c,v 1.9 1995/02/25 06:58:58 cgd Exp $";
62#endif
63#endif /* LIBC_SCCS and not lint */
64
65#include <sys/param.h> 55#include <sys/param.h>
66#include <netinet/in.h> 56#include <netinet/in.h>
67#include <arpa/inet.h> 57#include <arpa/inet.h>
68#include <arpa/nameser.h> 58#include <arpa/nameser.h>
59
60#include <stdio.h>
69#include <netdb.h> 61#include <netdb.h>
70#include <resolv.h> 62#include <resolv.h>
71#include <stdio.h>
72#include <ctype.h> 63#include <ctype.h>
73#include <errno.h> 64#include <errno.h>
74#include <stdlib.h> 65#include <stdlib.h>
75#include <string.h> 66#include <string.h>
67#include <unistd.h>
68
69#include "thread_private.h"
76 70
77#if PACKETSZ > 1024 71#if PACKETSZ > 1024
78#define MAXPACKET PACKETSZ 72#define MAXPACKET PACKETSZ
@@ -80,8 +74,9 @@ static char rcsid[] = "$NetBSD: res_query.c,v 1.9 1995/02/25 06:58:58 cgd Exp $"
80#define MAXPACKET 1024 74#define MAXPACKET 1024
81#endif 75#endif
82 76
83char *__hostalias __P((const char *)); 77const char *hostalias(const char *);
84int h_errno; 78int h_errno;
79extern int res_opt(int, u_char *, int, int);
85 80
86/* 81/*
87 * Formulate a normal query, send, and await answer. 82 * Formulate a normal query, send, and await answer.
@@ -90,68 +85,82 @@ int h_errno;
90 * if no error is indicated and the answer count is nonzero. 85 * if no error is indicated and the answer count is nonzero.
91 * Return the size of the response on success, -1 on error. 86 * Return the size of the response on success, -1 on error.
92 * Error number is left in h_errno. 87 * Error number is left in h_errno.
88 *
93 * Caller must parse answer and determine whether it answers the question. 89 * Caller must parse answer and determine whether it answers the question.
94 */ 90 */
95res_query(name, class, type, answer, anslen) 91int
96 char *name; /* domain name */ 92res_query(const char *name,
97 int class, type; /* class and type of query */ 93 int class, /* domain name */
98 u_char *answer; /* buffer to put answer */ 94 int type, /* class and type of query */
99 int anslen; /* size of answer buffer */ 95 u_char *answer, /* buffer to put answer */
96 int anslen) /* size of answer buffer */
100{ 97{
101 char buf[MAXPACKET]; 98 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
102 HEADER *hp; 99 union {
100 HEADER hdr;
101 u_char buf[MAXPACKET];
102 } buf;
103 HEADER *hp = (HEADER *) answer;
103 int n; 104 int n;
104 105
105 if ((_res.options & RES_INIT) == 0 && res_init() == -1) 106 hp->rcode = NOERROR; /* default */
107
108 if (_res_init(0) == -1) {
109 h_errno = NETDB_INTERNAL;
106 return (-1); 110 return (-1);
111 }
107#ifdef DEBUG 112#ifdef DEBUG
108 if (_res.options & RES_DEBUG) 113 if (_resp->options & RES_DEBUG)
109 printf(";; res_query(%s, %d, %d)\n", name, class, type); 114 printf(";; res_query(%s, %d, %d)\n", name, class, type);
110#endif 115#endif
111 n = res_mkquery(QUERY, name, class, type, (char *)NULL, 0, NULL, 116
112 buf, sizeof(buf)); 117 n = res_mkquery(QUERY, name, class, type, NULL, 0, NULL,
118 buf.buf, sizeof(buf.buf));
119 if (n > 0 && ((_resp->options & RES_USE_EDNS0) ||
120 (_resp->options & RES_USE_DNSSEC))) {
121 n = res_opt(n, buf.buf, sizeof(buf.buf), anslen);
122 }
113 123
114 if (n <= 0) { 124 if (n <= 0) {
115#ifdef DEBUG 125#ifdef DEBUG
116 if (_res.options & RES_DEBUG) 126 if (_resp->options & RES_DEBUG)
117 printf(";; res_query: mkquery failed\n"); 127 printf(";; res_query: mkquery failed\n");
118#endif 128#endif
119 h_errno = NO_RECOVERY; 129 h_errno = NO_RECOVERY;
120 return (n); 130 return (n);
121 } 131 }
122 n = res_send(buf, n, (char *)answer, anslen); 132 n = res_send(buf.buf, n, answer, anslen);
123 if (n < 0) { 133 if (n < 0) {
124#ifdef DEBUG 134#ifdef DEBUG
125 if (_res.options & RES_DEBUG) 135 if (_resp->options & RES_DEBUG)
126 printf(";; res_query: send error\n"); 136 printf(";; res_query: send error\n");
127#endif 137#endif
128 h_errno = TRY_AGAIN; 138 h_errno = TRY_AGAIN;
129 return (n); 139 return (n);
130 } 140 }
131 141
132 hp = (HEADER *) answer;
133 if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) { 142 if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
134#ifdef DEBUG 143#ifdef DEBUG
135 if (_res.options & RES_DEBUG) 144 if (_resp->options & RES_DEBUG)
136 printf(";; rcode = %d, ancount=%d\n", hp->rcode, 145 printf(";; rcode = %u, ancount=%u\n", hp->rcode,
137 ntohs(hp->ancount)); 146 ntohs(hp->ancount));
138#endif 147#endif
139 switch (hp->rcode) { 148 switch (hp->rcode) {
140 case NXDOMAIN: 149 case NXDOMAIN:
141 h_errno = HOST_NOT_FOUND; 150 h_errno = HOST_NOT_FOUND;
142 break; 151 break;
143 case SERVFAIL: 152 case SERVFAIL:
144 h_errno = TRY_AGAIN; 153 h_errno = TRY_AGAIN;
145 break; 154 break;
146 case NOERROR: 155 case NOERROR:
147 h_errno = NO_DATA; 156 h_errno = NO_DATA;
148 break; 157 break;
149 case FORMERR: 158 case FORMERR:
150 case NOTIMP: 159 case NOTIMP:
151 case REFUSED: 160 case REFUSED:
152 default: 161 default:
153 h_errno = NO_RECOVERY; 162 h_errno = NO_RECOVERY;
154 break; 163 break;
155 } 164 }
156 return (-1); 165 return (-1);
157 } 166 }
@@ -162,39 +171,39 @@ res_query(name, class, type, answer, anslen)
162 * Formulate a normal query, send, and retrieve answer in supplied buffer. 171 * Formulate a normal query, send, and retrieve answer in supplied buffer.
163 * Return the size of the response on success, -1 on error. 172 * Return the size of the response on success, -1 on error.
164 * If enabled, implement search rules until answer or unrecoverable failure 173 * If enabled, implement search rules until answer or unrecoverable failure
165 * is detected. Error number is left in h_errno. 174 * is detected. Error code, if any, is left in h_errno.
166 * Only useful for queries in the same name hierarchy as the local host
167 * (not, for example, for host address-to-name lookups in domain in-addr.arpa).
168 */ 175 */
169int 176int
170res_search(name, class, type, answer, anslen) 177res_search(const char *name,
171 const char *name; /* domain name */ 178 int class, /* domain name */
172 int class, type; /* class and type of query */ 179 int type, /* class and type of query */
173 u_char *answer; /* buffer to put answer */ 180 u_char *answer, /* buffer to put answer */
174 int anslen; /* size of answer */ 181 int anslen) /* size of answer */
175{ 182{
176 register char *cp, **domain; 183 const char *cp, * const *domain;
177 int dots, trailing_dot, ret, got_nodata, saved_herrno, tried_as_is; 184 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
185 HEADER *hp = (HEADER *) answer;
186 u_int dots;
187 int trailing_dot, ret, saved_herrno;
188 int got_nodata = 0, got_servfail = 0, tried_as_is = 0;
178 189
179 if ((_res.options & RES_INIT) == 0 && res_init() == -1) 190 if (_res_init(0) == -1) {
191 h_errno = NETDB_INTERNAL;
180 return (-1); 192 return (-1);
181 193 }
182 got_nodata = 0;
183 errno = 0; 194 errno = 0;
184 h_errno = HOST_NOT_FOUND; /* default, if we never query */ 195 h_errno = HOST_NOT_FOUND; /* default, if we never query */
185 dots = 0; 196 dots = 0;
186 for (cp = (char *)name; *cp; cp++) { 197 for (cp = name; *cp; cp++)
187 if (*cp == '.') 198 dots += (*cp == '.');
188 dots++;
189 }
190 trailing_dot = 0; 199 trailing_dot = 0;
191 if ((cp > name) && (*--cp == '.')) 200 if (cp > name && *--cp == '.')
192 trailing_dot++; 201 trailing_dot++;
193 202
194 /* 203 /*
195 * if there aren't any dots, it could be a user-level alias 204 * if there aren't any dots, it could be a user-level alias
196 */ 205 */
197 if (!dots && (cp = __hostalias(name))) 206 if (!dots && (cp = __hostalias(name)) != NULL)
198 return (res_query(cp, class, type, answer, anslen)); 207 return (res_query(cp, class, type, answer, anslen));
199 208
200 /* 209 /*
@@ -202,8 +211,7 @@ res_search(name, class, type, answer, anslen)
202 * 'as is'. The threshold can be set with the "ndots" option. 211 * 'as is'. The threshold can be set with the "ndots" option.
203 */ 212 */
204 saved_herrno = -1; 213 saved_herrno = -1;
205 tried_as_is = 0; 214 if (dots >= _resp->ndots) {
206 if (dots >= _res.ndots) {
207 ret = res_querydomain(name, NULL, class, type, answer, anslen); 215 ret = res_querydomain(name, NULL, class, type, answer, anslen);
208 if (ret > 0) 216 if (ret > 0)
209 return (ret); 217 return (ret);
@@ -217,15 +225,19 @@ res_search(name, class, type, answer, anslen)
217 * - there is at least one dot, there is no trailing dot, 225 * - there is at least one dot, there is no trailing dot,
218 * and RES_DNSRCH is set. 226 * and RES_DNSRCH is set.
219 */ 227 */
220 if ((!dots && (_res.options & RES_DEFNAMES)) || 228 if ((!dots && (_resp->options & RES_DEFNAMES)) ||
221 (dots && !trailing_dot && (_res.options & RES_DNSRCH))) { 229 (dots && !trailing_dot && (_resp->options & RES_DNSRCH))) {
222 for (domain = _res.dnsrch; *domain; domain++) { 230 int done = 0;
223 int done = 0; 231
232 for (domain = (const char * const *)_resp->dnsrch;
233 *domain && !done;
234 domain++) {
224 235
225 ret = res_querydomain(name, *domain, class, type, 236 ret = res_querydomain(name, *domain, class, type,
226 answer, anslen); 237 answer, anslen);
227 if (ret > 0) 238 if (ret > 0)
228 return (ret); 239 return (ret);
240
229 /* 241 /*
230 * If no server present, give up. 242 * If no server present, give up.
231 * If name isn't found in this domain, 243 * If name isn't found in this domain,
@@ -251,24 +263,27 @@ res_search(name, class, type, answer, anslen)
251 case HOST_NOT_FOUND: 263 case HOST_NOT_FOUND:
252 /* keep trying */ 264 /* keep trying */
253 break; 265 break;
266 case TRY_AGAIN:
267 if (hp->rcode == SERVFAIL) {
268 /* try next search element, if any */
269 got_servfail++;
270 break;
271 }
272 /* FALLTHROUGH */
254 default: 273 default:
255 /* anything else implies that we're done */ 274 /* anything else implies that we're done */
256 done++; 275 done++;
257 } 276 }
258 /* 277
259 * if we got here for some reason other than DNSRCH, 278 /* if we got here for some reason other than DNSRCH,
260 * we only wanted one iteration of the loop, so stop. 279 * we only wanted one iteration of the loop, so stop.
261 */ 280 */
262 if (!(_res.options & RES_DNSRCH)) 281 if (!(_resp->options & RES_DNSRCH))
263 done++; 282 done++;
264
265 if (done)
266 break;
267 } 283 }
268 } 284 }
269 285
270 /* 286 /* if we have not already tried the name "as is", do that now.
271 * if we have not already tried the name "as is", do that now.
272 * note that we do this regardless of how many dots were in the 287 * note that we do this regardless of how many dots were in the
273 * name or whether it ends with a dot. 288 * name or whether it ends with a dot.
274 */ 289 */
@@ -276,11 +291,9 @@ res_search(name, class, type, answer, anslen)
276 ret = res_querydomain(name, NULL, class, type, answer, anslen); 291 ret = res_querydomain(name, NULL, class, type, answer, anslen);
277 if (ret > 0) 292 if (ret > 0)
278 return (ret); 293 return (ret);
279 saved_herrno = h_errno;
280 } 294 }
281 295
282 /* 296 /* if we got here, we didn't satisfy the search.
283 * if we got here, we didn't satisfy the search.
284 * if we did an initial full query, return that query's h_errno 297 * if we did an initial full query, return that query's h_errno
285 * (note that we wouldn't be here if that query had succeeded). 298 * (note that we wouldn't be here if that query had succeeded).
286 * else if we ever got a nodata, send that back as the reason. 299 * else if we ever got a nodata, send that back as the reason.
@@ -291,6 +304,8 @@ res_search(name, class, type, answer, anslen)
291 h_errno = saved_herrno; 304 h_errno = saved_herrno;
292 else if (got_nodata) 305 else if (got_nodata)
293 h_errno = NO_DATA; 306 h_errno = NO_DATA;
307 else if (got_servfail)
308 h_errno = TRY_AGAIN;
294 return (-1); 309 return (-1);
295} 310}
296 311
@@ -298,20 +313,29 @@ res_search(name, class, type, answer, anslen)
298 * Perform a call on res_query on the concatenation of name and domain, 313 * Perform a call on res_query on the concatenation of name and domain,
299 * removing a trailing dot from name if domain is NULL. 314 * removing a trailing dot from name if domain is NULL.
300 */ 315 */
301res_querydomain(name, domain, class, type, answer, anslen) 316int
302 char *name, *domain; 317res_querydomain(const char *name,
303 int class, type; /* class and type of query */ 318 const char *domain,
304 u_char *answer; /* buffer to put answer */ 319 int class, /* class and type of query */
305 int anslen; /* size of answer */ 320 int type,
321 u_char *answer, /* buffer to put answer */
322 int anslen) /* size of answer */
306{ 323{
307 char nbuf[2*MAXDNAME+2]; 324#ifdef DEBUG
308 char *longname = nbuf; 325 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
326#endif
327 char nbuf[MAXDNAME*2+1+1];
328 const char *longname = nbuf;
309 int n; 329 int n;
310 330
331 if (_res_init(0) == -1) {
332 h_errno = NETDB_INTERNAL;
333 return (-1);
334 }
311#ifdef DEBUG 335#ifdef DEBUG
312 if (_res.options & RES_DEBUG) 336 if (_resp->options & RES_DEBUG)
313 printf(";; res_querydomain(%s, %s, %d, %d)\n", 337 printf(";; res_querydomain(%s, %s, %d, %d)\n",
314 name, domain, class, type); 338 name, domain?domain:"<Nil>", class, type);
315#endif 339#endif
316 if (domain == NULL) { 340 if (domain == NULL) {
317 /* 341 /*
@@ -325,38 +349,51 @@ res_querydomain(name, domain, class, type, answer, anslen)
325 } else 349 } else
326 longname = name; 350 longname = name;
327 } else 351 } else
328 (void)sprintf(nbuf, "%.*s.%.*s", 352 snprintf(nbuf, sizeof nbuf, "%.*s.%.*s",
329 MAXDNAME, name, MAXDNAME, domain); 353 MAXDNAME, name, MAXDNAME, domain);
330 354
331 return (res_query(longname, class, type, answer, anslen)); 355 return (res_query(longname, class, type, answer, anslen));
332} 356}
333 357
334char * 358const char *
335__hostalias(name) 359hostalias(const char *name)
336 register const char *name;
337{ 360{
338 register char *cp1, *cp2; 361 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
362 char *cp1, *cp2;
339 FILE *fp; 363 FILE *fp;
340 char *file, *getenv(), *strcpy(), *strncpy(); 364 char *file;
341 char buf[BUFSIZ]; 365 char buf[BUFSIZ];
342 static char abuf[MAXDNAME]; 366 static char abuf[MAXDNAME];
367 size_t len;
343 368
369 if (_resp->options & RES_NOALIASES)
370 return (NULL);
344 file = getenv("HOSTALIASES"); 371 file = getenv("HOSTALIASES");
345 if (file == NULL || (fp = fopen(file, "r")) == NULL) 372 if (issetugid() != 0 || file == NULL || (fp = fopen(file, "r")) == NULL)
346 return (NULL); 373 return (NULL);
347 buf[sizeof(buf) - 1] = '\0'; 374 setbuf(fp, NULL);
348 while (fgets(buf, sizeof(buf), fp)) { 375 while ((cp1 = fgetln(fp, &len)) != NULL) {
349 for (cp1 = buf; *cp1 && !isspace(*cp1); ++cp1); 376 if (cp1[len-1] == '\n')
377 len--;
378 if (len >= sizeof(buf) || len == 0)
379 continue;
380 (void)memcpy(buf, cp1, len);
381 buf[len] = '\0';
382
383 for (cp1 = buf; *cp1 && !isspace(*cp1); ++cp1)
384 ;
350 if (!*cp1) 385 if (!*cp1)
351 break; 386 break;
352 *cp1 = '\0'; 387 *cp1 = '\0';
353 if (!strcasecmp(buf, name)) { 388 if (!strcasecmp(buf, name)) {
354 while (isspace(*++cp1)); 389 while (isspace(*++cp1))
390 ;
355 if (!*cp1) 391 if (!*cp1)
356 break; 392 break;
357 for (cp2 = cp1 + 1; *cp2 && !isspace(*cp2); ++cp2); 393 for (cp2 = cp1 + 1; *cp2 && !isspace(*cp2); ++cp2)
358 abuf[sizeof(abuf) - 1] = *cp2 = '\0'; 394 ;
359 (void)strncpy(abuf, cp1, sizeof(abuf) - 1); 395 *cp2 = '\0';
396 strlcpy(abuf, cp1, sizeof(abuf));
360 fclose(fp); 397 fclose(fp);
361 return (abuf); 398 return (abuf);
362 } 399 }
diff --git a/src/lib/libc/net/res_random.c b/src/lib/libc/net/res_random.c
new file mode 100644
index 0000000000..f0beb7a573
--- /dev/null
+++ b/src/lib/libc/net/res_random.c
@@ -0,0 +1,264 @@
1/* $OpenBSD: res_random.c,v 1.17 2008/04/13 00:28:35 djm Exp $ */
2
3/*
4 * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de>
5 * Copyright 2008 Damien Miller <djm@openbsd.org>
6 * All rights reserved.
7 *
8 * Theo de Raadt <deraadt@openbsd.org> came up with the idea of using
9 * such a mathematical system to generate more random (yet non-repeating)
10 * ids to solve the resolver/named problem. But Niels designed the
11 * actual system based on the constraints.
12 *
13 * Later modified by Damien Miller to wrap the LCG output in a 15-bit
14 * permutation generator based on a Luby-Rackoff block cipher. This
15 * ensures the output is non-repeating and preserves the MSB twiddle
16 * trick, but makes it more resistant to LCG prediction.
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions
20 * are met:
21 * 1. Redistributions of source code must retain the above copyright
22 * notice, this list of conditions and the following disclaimer.
23 * 2. Redistributions in binary form must reproduce the above copyright
24 * notice, this list of conditions and the following disclaimer in the
25 * documentation and/or other materials provided with the distribution.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
28 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
29 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
30 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
31 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
32 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
36 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 */
38
39/*
40 * seed = random 15bit
41 * n = prime, g0 = generator to n,
42 * j = random so that gcd(j,n-1) == 1
43 * g = g0^j mod n will be a generator again.
44 *
45 * X[0] = random seed.
46 * X[n] = a*X[n-1]+b mod m is a Linear Congruential Generator
47 * with a = 7^(even random) mod m,
48 * b = random with gcd(b,m) == 1
49 * m = 31104 and a maximal period of m-1.
50 *
51 * The transaction id is determined by:
52 * id[n] = seed xor (g^X[n] mod n)
53 *
54 * Effectivly the id is restricted to the lower 15 bits, thus
55 * yielding two different cycles by toggling the msb on and off.
56 * This avoids reuse issues caused by reseeding.
57 *
58 * The output of this generator is then randomly permuted though a
59 * custom 15 bit Luby-Rackoff block cipher.
60 */
61
62#include <sys/types.h>
63#include <netinet/in.h>
64#include <sys/time.h>
65#include <resolv.h>
66
67#include <unistd.h>
68#include <stdlib.h>
69#include <string.h>
70
71#define RU_OUT 180 /* Time after wich will be reseeded */
72#define RU_MAX 30000 /* Uniq cycle, avoid blackjack prediction */
73#define RU_GEN 2 /* Starting generator */
74#define RU_N 32749 /* RU_N-1 = 2*2*3*2729 */
75#define RU_AGEN 7 /* determine ru_a as RU_AGEN^(2*rand) */
76#define RU_M 31104 /* RU_M = 2^7*3^5 - don't change */
77#define RU_ROUNDS 11 /* Number of rounds for permute (odd) */
78
79struct prf_ctx {
80 /* PRF lookup table for odd rounds (7 bits input to 8 bits output) */
81 u_char prf7[(RU_ROUNDS / 2) * (1 << 7)];
82
83 /* PRF lookup table for even rounds (8 bits input to 7 bits output) */
84 u_char prf8[((RU_ROUNDS + 1) / 2) * (1 << 8)];
85};
86
87#define PFAC_N 3
88const static u_int16_t pfacts[PFAC_N] = {
89 2,
90 3,
91 2729
92};
93
94static u_int16_t ru_x;
95static u_int16_t ru_seed, ru_seed2;
96static u_int16_t ru_a, ru_b;
97static u_int16_t ru_g;
98static u_int16_t ru_counter = 0;
99static u_int16_t ru_msb = 0;
100static struct prf_ctx *ru_prf = NULL;
101static long ru_reseed;
102
103static u_int16_t pmod(u_int16_t, u_int16_t, u_int16_t);
104static void res_initid(void);
105
106/*
107 * Do a fast modular exponation, returned value will be in the range
108 * of 0 - (mod-1)
109 */
110static u_int16_t
111pmod(u_int16_t gen, u_int16_t exp, u_int16_t mod)
112{
113 u_int16_t s, t, u;
114
115 s = 1;
116 t = gen;
117 u = exp;
118
119 while (u) {
120 if (u & 1)
121 s = (s * t) % mod;
122 u >>= 1;
123 t = (t * t) % mod;
124 }
125 return (s);
126}
127
128/*
129 * 15-bit permutation based on Luby-Rackoff block cipher
130 */
131u_int
132permute15(u_int in)
133{
134 int i;
135 u_int left, right, tmp;
136
137 if (ru_prf == NULL)
138 return in;
139
140 left = (in >> 8) & 0x7f;
141 right = in & 0xff;
142
143 /*
144 * Each round swaps the width of left and right. Even rounds have
145 * a 7-bit left, odd rounds have an 8-bit left. Since this uses an
146 * odd number of rounds, left is always 8 bits wide at the end.
147 */
148 for (i = 0; i < RU_ROUNDS; i++) {
149 if ((i & 1) == 0)
150 tmp = ru_prf->prf8[(i << (8 - 1)) | right] & 0x7f;
151 else
152 tmp = ru_prf->prf7[((i - 1) << (7 - 1)) | right];
153 tmp ^= left;
154 left = right;
155 right = tmp;
156 }
157
158 return (right << 8) | left;
159}
160
161/*
162 * Initializes the seed and chooses a suitable generator. Also toggles
163 * the msb flag. The msb flag is used to generate two distinct
164 * cycles of random numbers and thus avoiding reuse of ids.
165 *
166 * This function is called from res_randomid() when needed, an
167 * application does not have to worry about it.
168 */
169static void
170res_initid(void)
171{
172 u_int16_t j, i;
173 u_int32_t tmp;
174 int noprime = 1;
175 struct timeval tv;
176
177 ru_x = arc4random_uniform(RU_M);
178
179 /* 15 bits of random seed */
180 tmp = arc4random();
181 ru_seed = (tmp >> 16) & 0x7FFF;
182 ru_seed2 = tmp & 0x7FFF;
183
184 /* Determine the LCG we use */
185 tmp = arc4random();
186 ru_b = (tmp & 0xfffe) | 1;
187 ru_a = pmod(RU_AGEN, (tmp >> 16) & 0xfffe, RU_M);
188 while (ru_b % 3 == 0)
189 ru_b += 2;
190
191 j = arc4random_uniform(RU_N);
192
193 /*
194 * Do a fast gcd(j,RU_N-1), so we can find a j with
195 * gcd(j, RU_N-1) == 1, giving a new generator for
196 * RU_GEN^j mod RU_N
197 */
198
199 while (noprime) {
200 for (i = 0; i < PFAC_N; i++)
201 if (j % pfacts[i] == 0)
202 break;
203
204 if (i >= PFAC_N)
205 noprime = 0;
206 else
207 j = (j + 1) % RU_N;
208 }
209
210 ru_g = pmod(RU_GEN, j, RU_N);
211 ru_counter = 0;
212
213 /* Initialise PRF for Luby-Rackoff permutation */
214 if (ru_prf == NULL)
215 ru_prf = malloc(sizeof(*ru_prf));
216 if (ru_prf != NULL)
217 arc4random_buf(ru_prf, sizeof(*ru_prf));
218
219 gettimeofday(&tv, NULL);
220 ru_reseed = tv.tv_sec + RU_OUT;
221 ru_msb = ru_msb == 0x8000 ? 0 : 0x8000;
222}
223
224u_int
225res_randomid(void)
226{
227 struct timeval tv;
228
229 gettimeofday(&tv, NULL);
230 if (ru_counter >= RU_MAX || tv.tv_sec > ru_reseed)
231 res_initid();
232
233 /* Linear Congruential Generator */
234 ru_x = (ru_a * ru_x + ru_b) % RU_M;
235 ru_counter++;
236
237 return permute15(ru_seed ^ pmod(ru_g, ru_seed2 + ru_x, RU_N)) | ru_msb;
238}
239
240#if 0
241int
242main(int argc, char **argv)
243{
244 int i, n;
245 u_int16_t wert;
246
247 res_initid();
248
249 printf("Generator: %u\n", ru_g);
250 printf("Seed: %u\n", ru_seed);
251 printf("Reseed at %ld\n", ru_reseed);
252 printf("Ru_X: %u\n", ru_x);
253 printf("Ru_A: %u\n", ru_a);
254 printf("Ru_B: %u\n", ru_b);
255
256 n = argc > 1 ? atoi(argv[1]) : 60001;
257 for (i=0;i<n;i++) {
258 wert = res_randomid();
259 printf("%u\n", wert);
260 }
261 return 0;
262}
263#endif
264
diff --git a/src/lib/libc/net/res_send.c b/src/lib/libc/net/res_send.c
index e608358180..09b1385892 100644
--- a/src/lib/libc/net/res_send.c
+++ b/src/lib/libc/net/res_send.c
@@ -1,9 +1,11 @@
1/* $NetBSD: res_send.c,v 1.4 1995/02/25 06:21:01 cgd Exp $ */ 1/* $OpenBSD: res_send.c,v 1.21 2008/05/11 05:03:03 brad Exp $ */
2 2
3/*- 3/*
4 * ++Copyright++ 1985, 1989, 1993
5 * -
4 * Copyright (c) 1985, 1989, 1993 6 * Copyright (c) 1985, 1989, 1993
5 * The Regents of the University of California. All rights reserved. 7 * The Regents of the University of California. All rights reserved.
6 * 8 *
7 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
9 * are met: 11 * are met:
@@ -12,14 +14,10 @@
12 * 2. Redistributions in binary form must reproduce the above copyright 14 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 15 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 16 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software 17 * 3. Neither the name of the University nor the names of its contributors
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software 18 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission. 19 * without specific prior written permission.
22 * 20 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -53,19 +51,22 @@
53 * --Copyright-- 51 * --Copyright--
54 */ 52 */
55 53
56#if defined(LIBC_SCCS) && !defined(lint) 54#ifndef INET6
57#if 0 55#define INET6
58static char sccsid[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93";
59static char rcsid[] = "$Id: res_send.c,v 4.9.1.1 1993/05/02 22:43:03 vixie Rel ";
60#else
61static char rcsid[] = "$NetBSD: res_send.c,v 1.4 1995/02/25 06:21:01 cgd Exp $";
62#endif 56#endif
63#endif /* LIBC_SCCS and not lint */ 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 64
65/* 65/*
66 * Send query to name server and wait for reply. 66 * Send query to name server and wait for reply.
67 */ 67 */
68 68
69#include <sys/types.h>
69#include <sys/param.h> 70#include <sys/param.h>
70#include <sys/time.h> 71#include <sys/time.h>
71#include <sys/socket.h> 72#include <sys/socket.h>
@@ -73,139 +74,401 @@ static char rcsid[] = "$NetBSD: res_send.c,v 1.4 1995/02/25 06:21:01 cgd Exp $";
73#include <netinet/in.h> 74#include <netinet/in.h>
74#include <arpa/nameser.h> 75#include <arpa/nameser.h>
75#include <arpa/inet.h> 76#include <arpa/inet.h>
76#include <stdio.h> 77
77#include <errno.h> 78#include <errno.h>
79#include <netdb.h>
80#include <poll.h>
78#include <resolv.h> 81#include <resolv.h>
79#include <unistd.h> 82#include <stdio.h>
83#include <stdlib.h>
80#include <string.h> 84#include <string.h>
85#include <unistd.h>
86
87#include "thread_private.h"
81 88
82static int s = -1; /* socket used for communications */ 89static int s = -1; /* socket used for communications */
83static struct sockaddr no_addr; 90static int connected = 0; /* is the socket connected */
84 91static int vc = 0; /* is the socket a virtual ciruit? */
85#ifndef FD_SET 92static int af = 0; /* address family of socket */
86#define NFDBITS 32 93
87#define FD_SETSIZE 32 94#define CAN_RECONNECT 1
88#define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS))) 95
89#define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS))) 96#ifndef DEBUG
90#define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS))) 97# define Dprint(cond, args) /*empty*/
91#define FD_ZERO(p) bzero((char *)(p), sizeof(*(p))) 98# define DprintQ(cond, args, query, size) /*empty*/
99# define Aerror(file, string, error, address) /*empty*/
100# define Perror(file, string, error) /*empty*/
101#else
102# define Dprint(cond, args) if (cond) {fprintf args;} else {}
103# define DprintQ(cond, args, query, size) if (cond) {\
104 fprintf args;\
105 __fp_nquery(query, size, stdout);\
106 } else {}
107static char abuf[NI_MAXHOST];
108static char pbuf[NI_MAXSERV];
109static void Aerror(FILE *, char *, int, struct sockaddr *);
110static void Perror(FILE *, char *, int);
111
112 static void
113 Aerror(FILE *file, char *string, int error, struct sockaddr *address)
114 {
115 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
116 int save = errno;
117
118 if (_resp->options & RES_DEBUG) {
119 if (getnameinfo(address, address->sa_len, abuf, sizeof(abuf),
120 pbuf, sizeof(pbuf), NI_NUMERICHOST | NI_NUMERICSERV) != 0) {
121 strlcpy(abuf, "?", sizeof(abuf));
122 strlcpy(pbuf, "?", sizeof(pbuf));
123 }
124 fprintf(file, "res_send: %s ([%s].%s): %s\n",
125 string, abuf, pbuf, strerror(error));
126 }
127 errno = save;
128 }
129 static void
130 Perror(FILE *file, char *string, int error)
131 {
132 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
133 int save = errno;
134
135 if (_resp->options & RES_DEBUG) {
136 fprintf(file, "res_send: %s: %s\n",
137 string, strerror(error));
138 }
139 errno = save;
140 }
92#endif 141#endif
93 142
94res_send(buf, buflen, answer, anslen) 143static res_send_qhook Qhook = NULL;
95 const char *buf; 144static res_send_rhook Rhook = NULL;
96 int buflen; 145
97 char *answer; 146void
98 int anslen; 147res_send_setqhook(res_send_qhook hook)
99{ 148{
100 register int n; 149
101 int try, v_circuit, resplen, ns; 150 Qhook = hook;
102 int gotsomewhere = 0, connected = 0; 151}
103 int connreset = 0; 152
104 u_short id, len; 153void
105 char *cp; 154res_send_setrhook(res_send_rhook hook)
106 fd_set dsmask; 155{
107 struct timeval timeout; 156
108 HEADER *hp = (HEADER *) buf; 157 Rhook = hook;
109 HEADER *anhp = (HEADER *) answer; 158}
110 u_int badns; /* XXX NSMAX can't exceed #/bits per this */ 159
111 struct iovec iov[2]; 160#ifdef INET6
112 int terrno = ETIMEDOUT; 161static struct sockaddr * get_nsaddr(size_t);
113 char junk[512]; 162
114 163/*
115#ifdef DEBUG 164 * pick appropriate nsaddr_list for use. see res_init() for initialization.
116 if ((_res.options & RES_DEBUG) || (_res.pfcode & RES_PRF_QUERY)) { 165 */
117 printf(";; res_send()\n"); 166static struct sockaddr *
118 __p_query(buf); 167get_nsaddr(size_t n)
168{
169 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
170 struct __res_state_ext *_res_extp = _THREAD_PRIVATE(_res_ext, _res_ext,
171 &_res_ext);
172
173 if (!_resp->nsaddr_list[n].sin_family) {
174 /*
175 * - _res_extp->nsaddr_list[n] holds an address that is larger
176 * than struct sockaddr, and
177 * - user code did not update _resp->nsaddr_list[n].
178 */
179 return (struct sockaddr *)&_res_extp->nsaddr_list[n];
180 } else {
181 /*
182 * - user code updated _res.nsaddr_list[n], or
183 * - _resp->nsaddr_list[n] has the same content as
184 * _res_extp->nsaddr_list[n].
185 */
186 return (struct sockaddr *)&_resp->nsaddr_list[n];
119 } 187 }
188}
189#else
190#define get_nsaddr(n) ((struct sockaddr *)&_resp->nsaddr_list[(n)])
191#endif
192
193/* int
194 * res_isourserver(ina)
195 * looks up "ina" in _resp->ns_addr_list[]
196 * returns:
197 * 0 : not found
198 * >0 : found
199 * author:
200 * paul vixie, 29may94
201 */
202int
203res_isourserver(const struct sockaddr_in *inp)
204{
205 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
206#ifdef INET6
207 const struct sockaddr_in6 *in6p = (const struct sockaddr_in6 *)inp;
208 const struct sockaddr_in6 *srv6;
120#endif 209#endif
121 if (!(_res.options & RES_INIT)) 210 const struct sockaddr_in *srv;
122 if (res_init() == -1) { 211 int ns, ret;
123 return(-1); 212
213 ret = 0;
214 switch (inp->sin_family) {
215#ifdef INET6
216 case AF_INET6:
217 for (ns = 0; ns < _resp->nscount; ns++) {
218 srv6 = (struct sockaddr_in6 *)get_nsaddr(ns);
219 if (srv6->sin6_family == in6p->sin6_family &&
220 srv6->sin6_port == in6p->sin6_port &&
221 srv6->sin6_scope_id == in6p->sin6_scope_id &&
222 (IN6_IS_ADDR_UNSPECIFIED(&srv6->sin6_addr) ||
223 IN6_ARE_ADDR_EQUAL(&srv6->sin6_addr,
224 &in6p->sin6_addr))) {
225 ret++;
226 break;
227 }
124 } 228 }
125 v_circuit = (_res.options & RES_USEVC) || buflen > PACKETSZ; 229 break;
126 id = hp->id; 230#endif
231 case AF_INET:
232 for (ns = 0; ns < _resp->nscount; ns++) {
233 srv = (struct sockaddr_in *)get_nsaddr(ns);
234 if (srv->sin_family == inp->sin_family &&
235 srv->sin_port == inp->sin_port &&
236 (srv->sin_addr.s_addr == INADDR_ANY ||
237 srv->sin_addr.s_addr == inp->sin_addr.s_addr)) {
238 ret++;
239 break;
240 }
241 }
242 break;
243 }
244 return (ret);
245}
246
247/* int
248 * res_nameinquery(name, type, class, buf, eom)
249 * look for (name,type,class) in the query section of packet (buf,eom)
250 * returns:
251 * -1 : format error
252 * 0 : not found
253 * >0 : found
254 * author:
255 * paul vixie, 29may94
256 */
257int
258res_nameinquery(const char *name, int type, int class, const u_char *buf,
259 const u_char *eom)
260{
261 const u_char *cp = buf + HFIXEDSZ;
262 int qdcount = ntohs(((HEADER*)buf)->qdcount);
263
264 while (qdcount-- > 0) {
265 char tname[MAXDNAME+1];
266 int n, ttype, tclass;
267
268 n = dn_expand(buf, eom, cp, tname, sizeof tname);
269 if (n < 0)
270 return (-1);
271 cp += n;
272 ttype = _getshort(cp); cp += INT16SZ;
273 tclass = _getshort(cp); cp += INT16SZ;
274 if (ttype == type &&
275 tclass == class &&
276 strcasecmp(tname, name) == 0)
277 return (1);
278 }
279 return (0);
280}
281
282/* int
283 * res_queriesmatch(buf1, eom1, buf2, eom2)
284 * is there a 1:1 mapping of (name,type,class)
285 * in (buf1,eom1) and (buf2,eom2)?
286 * returns:
287 * -1 : format error
288 * 0 : not a 1:1 mapping
289 * >0 : is a 1:1 mapping
290 * author:
291 * paul vixie, 29may94
292 */
293int
294res_queriesmatch(const u_char *buf1, const u_char *eom1, const u_char *buf2,
295 const u_char *eom2)
296{
297 const u_char *cp = buf1 + HFIXEDSZ;
298 int qdcount = ntohs(((HEADER*)buf1)->qdcount);
299
300 if (qdcount != ntohs(((HEADER*)buf2)->qdcount))
301 return (0);
302 while (qdcount-- > 0) {
303 char tname[MAXDNAME+1];
304 int n, ttype, tclass;
305
306 n = dn_expand(buf1, eom1, cp, tname, sizeof tname);
307 if (n < 0)
308 return (-1);
309 cp += n;
310 ttype = _getshort(cp); cp += INT16SZ;
311 tclass = _getshort(cp); cp += INT16SZ;
312 if (!res_nameinquery(tname, ttype, tclass, buf2, eom2))
313 return (0);
314 }
315 return (1);
316}
317
318int
319res_send(const u_char *buf, int buflen, u_char *ans, int anssiz)
320{
321 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
322 HEADER *hp = (HEADER *) buf;
323 HEADER *anhp = (HEADER *) ans;
324 int gotsomewhere, connreset, terrno, try, v_circuit, resplen, ns;
325 int n;
326 u_int badns; /* XXX NSMAX can't exceed #/bits in this var */
327
328 if (_res_init(0) == -1) {
329 /* errno should have been set by res_init() in this case. */
330 return (-1);
331 }
332 DprintQ((_resp->options & RES_DEBUG) || (_resp->pfcode & RES_PRF_QUERY),
333 (stdout, ";; res_send()\n"), buf, buflen);
334 v_circuit = (_resp->options & RES_USEVC) || buflen > PACKETSZ;
335 gotsomewhere = 0;
336 connreset = 0;
337 terrno = ETIMEDOUT;
127 badns = 0; 338 badns = 0;
339
128 /* 340 /*
129 * Send request, RETRY times, or until successful 341 * Send request, RETRY times, or until successful
130 */ 342 */
131 for (try = 0; try < _res.retry; try++) { 343 for (try = 0; try < _resp->retry; try++) {
132 for (ns = 0; ns < _res.nscount; ns++) { 344 for (ns = 0; ns < _resp->nscount; ns++) {
133 if (badns & (1<<ns)) 345 struct sockaddr *nsap = get_nsaddr(ns);
134 continue; 346 socklen_t salen;
135#ifdef DEBUG 347
136 if (_res.options & RES_DEBUG) 348 if (nsap->sa_len)
137 printf(";; Querying server (# %d) address = %s\n", 349 salen = nsap->sa_len;
138 ns+1, 350#ifdef INET6
139 inet_ntoa(_res.nsaddr_list[ns].sin_addr)); 351 else if (nsap->sa_family == AF_INET6)
352 salen = sizeof(struct sockaddr_in6);
140#endif 353#endif
141 usevc: 354 else if (nsap->sa_family == AF_INET)
355 salen = sizeof(struct sockaddr_in);
356 else
357 salen = 0; /*unknown, die on connect*/
358
359 same_ns:
360 if (badns & (1 << ns)) {
361 res_close();
362 goto next_ns;
363 }
364
365 if (Qhook) {
366 int done = 0, loops = 0;
367
368 do {
369 res_sendhookact act;
370
371 act = (*Qhook)((struct sockaddr_in **)&nsap,
372 &buf, &buflen,
373 ans, anssiz, &resplen);
374 switch (act) {
375 case res_goahead:
376 done = 1;
377 break;
378 case res_nextns:
379 res_close();
380 goto next_ns;
381 case res_done:
382 return (resplen);
383 case res_modified:
384 /* give the hook another try */
385 if (++loops < 42) /*doug adams*/
386 break;
387 /*FALLTHROUGH*/
388 case res_error:
389 /*FALLTHROUGH*/
390 default:
391 return (-1);
392 }
393 } while (!done);
394 }
395
396 Dprint((_resp->options & RES_DEBUG) &&
397 getnameinfo(nsap, salen, abuf, sizeof(abuf),
398 NULL, 0, NI_NUMERICHOST) == 0,
399 (stdout, ";; Querying server (# %d) address = %s\n",
400 ns + 1, abuf));
401
142 if (v_circuit) { 402 if (v_circuit) {
143 int truncated = 0; 403 int truncated;
404 struct iovec iov[2];
405 u_short len;
406 u_char *cp;
144 407
145 /* 408 /*
146 * Use virtual circuit; 409 * Use virtual circuit;
147 * at most one attempt per server. 410 * at most one attempt per server.
148 */ 411 */
149 try = _res.retry; 412 try = _resp->retry;
150 if (s < 0) { 413 truncated = 0;
151 s = socket(AF_INET, SOCK_STREAM, 0); 414 if ((s < 0) || (!vc) || (af != nsap->sa_family)) {
415 if (s >= 0)
416 res_close();
417
418 af = nsap->sa_family;
419 s = socket(af, SOCK_STREAM, 0);
152 if (s < 0) { 420 if (s < 0) {
153 terrno = errno; 421 terrno = errno;
154#ifdef DEBUG 422 Perror(stderr, "socket(vc)", errno);
155 if (_res.options & RES_DEBUG) 423#if 0
156 perror("socket (vc) failed"); 424 return (-1);
425#else
426 badns |= (1 << ns);
427 res_close();
428 goto next_ns;
157#endif 429#endif
158 continue;
159 } 430 }
160 if (connect(s, 431 errno = 0;
161 (struct sockaddr *)&(_res.nsaddr_list[ns]), 432 if (connect(s, nsap, salen) < 0) {
162 sizeof(struct sockaddr)) < 0) {
163 terrno = errno; 433 terrno = errno;
164#ifdef DEBUG 434 Aerror(stderr, "connect/vc",
165 if (_res.options & RES_DEBUG) 435 errno, nsap);
166 perror("connect failed"); 436 badns |= (1 << ns);
167#endif 437 res_close();
168 (void) close(s); 438 goto next_ns;
169 s = -1;
170 continue;
171 } 439 }
440 vc = 1;
172 } 441 }
173 /* 442 /*
174 * Send length & message 443 * Send length & message
175 */ 444 */
176 len = htons((u_short)buflen); 445 putshort((u_short)buflen, (u_char*)&len);
177 iov[0].iov_base = (caddr_t)&len; 446 iov[0].iov_base = (caddr_t)&len;
178 iov[0].iov_len = sizeof(len); 447 iov[0].iov_len = INT16SZ;
179 iov[1].iov_base = (char *)buf; 448 iov[1].iov_base = (caddr_t)buf;
180 iov[1].iov_len = buflen; 449 iov[1].iov_len = buflen;
181 if (writev(s, iov, 2) != sizeof(len) + buflen) { 450 if (writev(s, iov, 2) != (INT16SZ + buflen)) {
182 terrno = errno; 451 terrno = errno;
183#ifdef DEBUG 452 Perror(stderr, "write failed", errno);
184 if (_res.options & RES_DEBUG) 453 badns |= (1 << ns);
185 perror("write failed"); 454 res_close();
186#endif 455 goto next_ns;
187 (void) close(s);
188 s = -1;
189 continue;
190 } 456 }
191 /* 457 /*
192 * Receive length & response 458 * Receive length & response
193 */ 459 */
194 cp = answer; 460 read_len:
195 len = sizeof(short); 461 cp = ans;
196 while (len != 0 && 462 len = INT16SZ;
197 (n = read(s, (char *)cp, (int)len)) > 0) { 463 while ((n = read(s, (char *)cp, (int)len)) > 0) {
198 cp += n; 464 cp += n;
199 len -= n; 465 if ((len -= n) <= 0)
466 break;
200 } 467 }
201 if (n <= 0) { 468 if (n <= 0) {
202 terrno = errno; 469 terrno = errno;
203#ifdef DEBUG 470 Perror(stderr, "read failed", errno);
204 if (_res.options & RES_DEBUG) 471 res_close();
205 perror("read failed");
206#endif
207 (void) close(s);
208 s = -1;
209 /* 472 /*
210 * A long running process might get its TCP 473 * A long running process might get its TCP
211 * connection reset if the remote server was 474 * connection reset if the remote server was
@@ -217,35 +480,32 @@ res_send(buf, buflen, answer, anslen)
217 */ 480 */
218 if (terrno == ECONNRESET && !connreset) { 481 if (terrno == ECONNRESET && !connreset) {
219 connreset = 1; 482 connreset = 1;
220 ns--; 483 res_close();
484 goto same_ns;
221 } 485 }
222 continue; 486 res_close();
487 goto next_ns;
223 } 488 }
224 cp = answer; 489 resplen = _getshort(ans);
225 if ((resplen = ntohs(*(u_short *)cp)) > anslen) { 490 if (resplen > anssiz) {
226#ifdef DEBUG 491 Dprint(_resp->options & RES_DEBUG,
227 if (_res.options & RES_DEBUG) 492 (stdout, ";; response truncated\n")
228 fprintf(stderr, 493 );
229 ";; response truncated\n");
230#endif
231 len = anslen;
232 truncated = 1; 494 truncated = 1;
495 len = anssiz;
233 } else 496 } else
234 len = resplen; 497 len = resplen;
498 cp = ans;
235 while (len != 0 && 499 while (len != 0 &&
236 (n = read(s, (char *)cp, (int)len)) > 0) { 500 (n = read(s, (char *)cp, (int)len)) > 0) {
237 cp += n; 501 cp += n;
238 len -= n; 502 len -= n;
239 } 503 }
240 if (n <= 0) { 504 if (n <= 0) {
241 terrno = errno; 505 terrno = errno;
242#ifdef DEBUG 506 Perror(stderr, "read(vc)", errno);
243 if (_res.options & RES_DEBUG) 507 res_close();
244 perror("read failed"); 508 goto next_ns;
245#endif
246 (void) close(s);
247 s = -1;
248 continue;
249 } 509 }
250 if (truncated) { 510 if (truncated) {
251 /* 511 /*
@@ -253,40 +513,79 @@ res_send(buf, buflen, answer, anslen)
253 * so connection stays in synch. 513 * so connection stays in synch.
254 */ 514 */
255 anhp->tc = 1; 515 anhp->tc = 1;
256 len = resplen - anslen; 516 len = resplen - anssiz;
257 while (len != 0) { 517 while (len != 0) {
258 n = (len > sizeof(junk) ? 518 char junk[PACKETSZ];
259 sizeof(junk) : len); 519
520 n = (len > sizeof(junk)
521 ? sizeof(junk)
522 : len);
260 if ((n = read(s, junk, n)) > 0) 523 if ((n = read(s, junk, n)) > 0)
261 len -= n; 524 len -= n;
262 else 525 else
263 break; 526 break;
264 } 527 }
265 } 528 }
529 /*
530 * The calling applicating has bailed out of
531 * a previous call and failed to arrange to have
532 * the circuit closed or the server has got
533 * itself confused. Anyway drop the packet and
534 * wait for the correct one.
535 */
536 if (hp->id != anhp->id) {
537 DprintQ((_resp->options & RES_DEBUG) ||
538 (_resp->pfcode & RES_PRF_REPLY),
539 (stdout, ";; old answer (unexpected):\n"),
540 ans, (resplen>anssiz)?anssiz:resplen);
541 goto read_len;
542 }
266 } else { 543 } else {
267 /* 544 /*
268 * Use datagrams. 545 * Use datagrams.
269 */ 546 */
270 if (s < 0) { 547 struct pollfd pfd;
271 s = socket(AF_INET, SOCK_DGRAM, 0); 548 int timeout;
549 struct sockaddr_storage from;
550 socklen_t fromlen;
551
552 if ((s < 0) || vc || (af != nsap->sa_family)) {
553 if (vc)
554 res_close();
555 af = nsap->sa_family;
556 s = socket(af, SOCK_DGRAM, 0);
272 if (s < 0) { 557 if (s < 0) {
558#if !CAN_RECONNECT
559 bad_dg_sock:
560#endif
273 terrno = errno; 561 terrno = errno;
274#ifdef DEBUG 562 Perror(stderr, "socket(dg)", errno);
275 if (_res.options & RES_DEBUG) 563#if 0
276 perror("socket (dg) failed"); 564 return (-1);
565#else
566 badns |= (1 << ns);
567 res_close();
568 goto next_ns;
277#endif 569#endif
278 continue;
279 } 570 }
571#ifdef IPV6_MINMTU
572 if (af == AF_INET6) {
573 const int yes = 1;
574 (void)setsockopt(s, IPPROTO_IPV6,
575 IPV6_USE_MIN_MTU, &yes,
576 sizeof(yes));
577 }
578#endif
579 connected = 0;
280 } 580 }
281 /* 581 /*
282 * I'm tired of answering this question, so:
283 * On a 4.3BSD+ machine (client and server, 582 * On a 4.3BSD+ machine (client and server,
284 * actually), sending to a nameserver datagram 583 * actually), sending to a nameserver datagram
285 * port with no nameserver will cause an 584 * port with no nameserver will cause an
286 * ICMP port unreachable message to be returned. 585 * ICMP port unreachable message to be returned.
287 * If our datagram socket is "connected" to the 586 * If our datagram socket is "connected" to the
288 * server, we get an ECONNREFUSED error on the next 587 * server, we get an ECONNREFUSED error on the next
289 * socket operation, and select returns if the 588 * socket operation, and poll returns if the
290 * error message is received. We can thus detect 589 * error message is received. We can thus detect
291 * the absence of a nameserver without timing out. 590 * the absence of a nameserver without timing out.
292 * If we have sent queries to at least two servers, 591 * If we have sent queries to at least two servers,
@@ -294,31 +593,28 @@ res_send(buf, buflen, answer, anslen)
294 * as we wish to receive answers from the first 593 * as we wish to receive answers from the first
295 * server to respond. 594 * server to respond.
296 */ 595 */
297 if (_res.nscount == 1 || (try == 0 && ns == 0)) { 596 if (!(_resp->options & RES_INSECURE1) &&
597 (_resp->nscount == 1 || (try == 0 && ns == 0))) {
298 /* 598 /*
299 * Don't use connect if we might 599 * Connect only if we are sure we won't
300 * still receive a response 600 * receive a response from another server.
301 * from another server.
302 */ 601 */
303 if (connected == 0) { 602 if (!connected) {
304 if (connect(s, 603 if (connect(s, nsap, salen) < 0) {
305 (struct sockaddr *) 604 Aerror(stderr,
306 &_res.nsaddr_list[ns], 605 "connect(dg)",
307 sizeof(struct sockaddr)) < 0) { 606 errno, nsap);
308#ifdef DEBUG 607 badns |= (1 << ns);
309 if (_res.options & RES_DEBUG) 608 res_close();
310 perror("connect"); 609 goto next_ns;
311#endif
312 continue;
313 } 610 }
314 connected = 1; 611 connected = 1;
315 } 612 }
316 if (send(s, buf, buflen, 0) != buflen) { 613 if (send(s, (char*)buf, buflen, 0) != buflen) {
317#ifdef DEBUG 614 Perror(stderr, "send", errno);
318 if (_res.options & RES_DEBUG) 615 badns |= (1 << ns);
319 perror("send"); 616 res_close();
320#endif 617 goto next_ns;
321 continue;
322 } 618 }
323 } else { 619 } else {
324 /* 620 /*
@@ -326,134 +622,213 @@ res_send(buf, buflen, answer, anslen)
326 * for responses from more than one server. 622 * for responses from more than one server.
327 */ 623 */
328 if (connected) { 624 if (connected) {
329 (void) connect(s, &no_addr, 625#if CAN_RECONNECT
330 sizeof(no_addr)); 626#ifdef INET6
627 /* XXX: any errornous address */
628#endif /* INET6 */
629 struct sockaddr_in no_addr;
630
631 no_addr.sin_family = AF_INET;
632 no_addr.sin_addr.s_addr = INADDR_ANY;
633 no_addr.sin_port = 0;
634 (void) connect(s,
635 (struct sockaddr *)
636 &no_addr,
637 sizeof(no_addr));
638#else
639 int s1 = socket(af, SOCK_DGRAM,0);
640 if (s1 < 0)
641 goto bad_dg_sock;
642 (void) dup2(s1, s);
643 (void) close(s1);
644 Dprint(_resp->options & RES_DEBUG,
645 (stdout, ";; new DG socket\n"))
646#endif
647#ifdef IPV6_MINMTU
648 if (af == AF_INET6) {
649 const int yes = 1;
650 (void)setsockopt(s, IPPROTO_IPV6,
651 IPV6_USE_MIN_MTU, &yes,
652 sizeof(yes));
653 }
654#endif
331 connected = 0; 655 connected = 0;
656 errno = 0;
332 } 657 }
333 if (sendto(s, buf, buflen, 0, 658 if (sendto(s, (char*)buf, buflen, 0,
334 (struct sockaddr *)&_res.nsaddr_list[ns], 659 nsap, salen) != buflen) {
335 sizeof(struct sockaddr)) != buflen) { 660 Aerror(stderr, "sendto", errno, nsap);
336#ifdef DEBUG 661 badns |= (1 << ns);
337 if (_res.options & RES_DEBUG) 662 res_close();
338 perror("sendto"); 663 goto next_ns;
339#endif
340 continue;
341 } 664 }
342 } 665 }
343 666
344 /* 667 /*
345 * Wait for reply 668 * Wait for reply
346 */ 669 */
347 timeout.tv_sec = (_res.retrans << try); 670 timeout = 1000 * (_resp->retrans << try);
348 if (try > 0) 671 if (try > 0)
349 timeout.tv_sec /= _res.nscount; 672 timeout /= _resp->nscount;
350 if ((long) timeout.tv_sec <= 0) 673 if (timeout < 1000)
351 timeout.tv_sec = 1; 674 timeout = 1000;
352 timeout.tv_usec = 0; 675 wait:
353wait: 676 pfd.fd = s;
354 FD_ZERO(&dsmask); 677 pfd.events = POLLIN;
355 FD_SET(s, &dsmask); 678 n = poll(&pfd, 1, timeout);
356 n = select(s+1, &dsmask, (fd_set *)NULL,
357 (fd_set *)NULL, &timeout);
358 if (n < 0) { 679 if (n < 0) {
359#ifdef DEBUG 680 if (errno == EINTR)
360 if (_res.options & RES_DEBUG) 681 goto wait;
361 perror("select"); 682 Perror(stderr, "poll", errno);
362#endif 683 res_close();
363 continue; 684 goto next_ns;
364 } 685 }
365 if (n == 0) { 686 if (n == 0) {
366 /* 687 /*
367 * timeout 688 * timeout
368 */ 689 */
369#ifdef DEBUG 690 Dprint(_resp->options & RES_DEBUG,
370 if (_res.options & RES_DEBUG) 691 (stdout, ";; timeout\n"));
371 printf(";; timeout\n");
372#endif
373 gotsomewhere = 1; 692 gotsomewhere = 1;
374 continue; 693 res_close();
694 goto next_ns;
375 } 695 }
376 if ((resplen = recv(s, answer, anslen, 0)) <= 0) { 696 errno = 0;
377#ifdef DEBUG 697 fromlen = sizeof(from);
378 if (_res.options & RES_DEBUG) 698 resplen = recvfrom(s, (char*)ans, anssiz, 0,
379 perror("recvfrom"); 699 (struct sockaddr *)&from, &fromlen);
380#endif 700 if (resplen <= 0) {
381 continue; 701 Perror(stderr, "recvfrom", errno);
702 res_close();
703 goto next_ns;
382 } 704 }
383 gotsomewhere = 1; 705 gotsomewhere = 1;
384 if (id != anhp->id) { 706 if (hp->id != anhp->id) {
385 /* 707 /*
386 * response from old query, ignore it 708 * response from old query, ignore it.
709 * XXX - potential security hazard could
710 * be detected here.
387 */ 711 */
388#ifdef DEBUG 712 DprintQ((_resp->options & RES_DEBUG) ||
389 if ((_res.options & RES_DEBUG) || 713 (_resp->pfcode & RES_PRF_REPLY),
390 (_res.pfcode & RES_PRF_REPLY)) { 714 (stdout, ";; old answer:\n"),
391 printf(";; old answer:\n"); 715 ans, (resplen>anssiz)?anssiz:resplen);
392 __p_query(answer); 716 goto wait;
393 } 717 }
718#if CHECK_SRVR_ADDR
719 if (!(_resp->options & RES_INSECURE1) &&
720 !res_isourserver((struct sockaddr_in *)&from)) {
721 /*
722 * response from wrong server? ignore it.
723 * XXX - potential security hazard could
724 * be detected here.
725 */
726 DprintQ((_resp->options & RES_DEBUG) ||
727 (_resp->pfcode & RES_PRF_REPLY),
728 (stdout, ";; not our server:\n"),
729 ans, (resplen>anssiz)?anssiz:resplen);
730 goto wait;
731 }
394#endif 732#endif
733 if (!(_resp->options & RES_INSECURE2) &&
734 !res_queriesmatch(buf, buf + buflen,
735 ans, ans + anssiz)) {
736 /*
737 * response contains wrong query? ignore it.
738 * XXX - potential security hazard could
739 * be detected here.
740 */
741 DprintQ((_resp->options & RES_DEBUG) ||
742 (_resp->pfcode & RES_PRF_REPLY),
743 (stdout, ";; wrong query name:\n"),
744 ans, (resplen>anssiz)?anssiz:resplen);
395 goto wait; 745 goto wait;
396 } 746 }
397 if (anhp->rcode == SERVFAIL || anhp->rcode == NOTIMP || 747 if (anhp->rcode == SERVFAIL ||
748 anhp->rcode == NOTIMP ||
398 anhp->rcode == REFUSED) { 749 anhp->rcode == REFUSED) {
399#ifdef DEBUG 750 DprintQ(_resp->options & RES_DEBUG,
400 if (_res.options & RES_DEBUG) { 751 (stdout, "server rejected query:\n"),
401 printf("server rejected query:\n"); 752 ans, (resplen>anssiz)?anssiz:resplen);
402 __p_query(answer); 753 badns |= (1 << ns);
403 } 754 res_close();
404#endif 755 /* don't retry if called from dig */
405 badns |= (1<<ns); 756 if (!_resp->pfcode)
406 continue; 757 goto next_ns;
407 } 758 }
408 if (!(_res.options & RES_IGNTC) && anhp->tc) { 759 if (!(_resp->options & RES_IGNTC) && anhp->tc) {
409 /* 760 /*
410 * get rest of answer; 761 * get rest of answer;
411 * use TCP with same server. 762 * use TCP with same server.
412 */ 763 */
413#ifdef DEBUG 764 Dprint(_resp->options & RES_DEBUG,
414 if (_res.options & RES_DEBUG) 765 (stdout, ";; truncated answer\n"));
415 printf(";; truncated answer\n");
416#endif
417 (void) close(s);
418 s = -1;
419 v_circuit = 1; 766 v_circuit = 1;
420 goto usevc; 767 res_close();
768 goto same_ns;
421 } 769 }
422 } 770 } /*if vc/dg*/
423#ifdef DEBUG 771 Dprint((_resp->options & RES_DEBUG) ||
424 if (_res.options & RES_DEBUG) 772 ((_resp->pfcode & RES_PRF_REPLY) &&
425 printf(";; got answer:\n"); 773 (_resp->pfcode & RES_PRF_HEAD1)),
426 if ((_res.options & RES_DEBUG) || 774 (stdout, ";; got answer:\n"));
427 (_res.pfcode & RES_PRF_REPLY)) 775 DprintQ((_resp->options & RES_DEBUG) ||
428 __p_query(answer); 776 (_resp->pfcode & RES_PRF_REPLY),
429#endif 777 (stdout, "%s", ""),
778 ans, (resplen>anssiz)?anssiz:resplen);
430 /* 779 /*
431 * If using virtual circuits, we assume that the first server 780 * If using virtual circuits, we assume that the first server
432 * is preferred * over the rest (i.e. it is on the local 781 * is preferred over the rest (i.e. it is on the local
433 * machine) and only keep that one open. 782 * machine) and only keep that one open.
434 * If we have temporarily opened a virtual circuit, 783 * If we have temporarily opened a virtual circuit,
435 * or if we haven't been asked to keep a socket open, 784 * or if we haven't been asked to keep a socket open,
436 * close the socket. 785 * close the socket.
437 */ 786 */
438 if ((v_circuit && 787 if ((v_circuit && (!(_resp->options & RES_USEVC) || ns != 0)) ||
439 ((_res.options & RES_USEVC) == 0 || ns != 0)) || 788 !(_resp->options & RES_STAYOPEN)) {
440 (_res.options & RES_STAYOPEN) == 0) { 789 res_close();
441 (void) close(s); 790 }
442 s = -1; 791 if (Rhook) {
792 int done = 0, loops = 0;
793
794 do {
795 res_sendhookact act;
796
797 act = (*Rhook)((struct sockaddr_in *)nsap,
798 buf, buflen,
799 ans, anssiz, &resplen);
800 switch (act) {
801 case res_goahead:
802 case res_done:
803 done = 1;
804 break;
805 case res_nextns:
806 res_close();
807 goto next_ns;
808 case res_modified:
809 /* give the hook another try */
810 if (++loops < 42) /*doug adams*/
811 break;
812 /*FALLTHROUGH*/
813 case res_error:
814 /*FALLTHROUGH*/
815 default:
816 return (-1);
817 }
818 } while (!done);
819
443 } 820 }
444 return (resplen); 821 return (resplen);
445 } 822 next_ns: ;
446 } 823 } /*foreach ns*/
447 if (s >= 0) { 824 } /*foreach retry*/
448 (void) close(s); 825 res_close();
449 s = -1; 826 if (!v_circuit) {
450 } 827 if (!gotsomewhere)
451 if (v_circuit == 0)
452 if (gotsomewhere == 0)
453 errno = ECONNREFUSED; /* no nameservers found */ 828 errno = ECONNREFUSED; /* no nameservers found */
454 else 829 else
455 errno = ETIMEDOUT; /* no answer obtained */ 830 errno = ETIMEDOUT; /* no answer obtained */
456 else 831 } else
457 errno = terrno; 832 errno = terrno;
458 return (-1); 833 return (-1);
459} 834}
@@ -465,10 +840,14 @@ wait:
465 * 840 *
466 * This routine is not expected to be user visible. 841 * This routine is not expected to be user visible.
467 */ 842 */
468_res_close() 843void
844res_close(void)
469{ 845{
470 if (s != -1) { 846 if (s >= 0) {
471 (void) close(s); 847 (void) close(s);
472 s = -1; 848 s = -1;
849 connected = 0;
850 vc = 0;
851 af = 0;
473 } 852 }
474} 853}
diff --git a/src/lib/libc/net/resolver.3 b/src/lib/libc/net/resolver.3
index 99abe17f03..e820ea25ed 100644
--- a/src/lib/libc/net/resolver.3
+++ b/src/lib/libc/net/resolver.3
@@ -1,4 +1,4 @@
1.\" $NetBSD: resolver.3,v 1.5 1995/02/25 06:21:02 cgd Exp $ 1.\" $OpenBSD: resolver.3,v 1.21 2007/05/31 19:19:30 jmc Exp $
2.\" 2.\"
3.\" Copyright (c) 1985, 1991, 1993 3.\" Copyright (c) 1985, 1991, 1993
4.\" The Regents of the University of California. All rights reserved. 4.\" The Regents of the University of California. All rights reserved.
@@ -11,11 +11,7 @@
11.\" 2. Redistributions in binary form must reproduce the above copyright 11.\" 2. Redistributions in binary form must reproduce the above copyright
12.\" notice, this list of conditions and the following disclaimer in the 12.\" notice, this list of conditions and the following disclaimer in the
13.\" documentation and/or other materials provided with the distribution. 13.\" documentation and/or other materials provided with the distribution.
14.\" 3. All advertising materials mentioning features or use of this software 14.\" 3. Neither the name of the University nor the names of its contributors
15.\" must display the following acknowledgement:
16.\" This product includes software developed by the University of
17.\" California, Berkeley and its contributors.
18.\" 4. Neither the name of the University nor the names of its contributors
19.\" may be used to endorse or promote products derived from this software 15.\" may be used to endorse or promote products derived from this software
20.\" without specific prior written permission. 16.\" without specific prior written permission.
21.\" 17.\"
@@ -31,11 +27,9 @@
31.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32.\" SUCH DAMAGE. 28.\" SUCH DAMAGE.
33.\" 29.\"
34.\" @(#)resolver.3 8.1 (Berkeley) 6/4/93 30.Dd $Mdocdate: May 31 2007 $
35.\"
36.Dd June 4, 1993
37.Dt RESOLVER 3 31.Dt RESOLVER 3
38.Os BSD 4.3 32.Os
39.Sh NAME 33.Sh NAME
40.Nm res_query , 34.Nm res_query ,
41.Nm res_search , 35.Nm res_search ,
@@ -50,69 +44,76 @@
50.Fd #include <netinet/in.h> 44.Fd #include <netinet/in.h>
51.Fd #include <arpa/nameser.h> 45.Fd #include <arpa/nameser.h>
52.Fd #include <resolv.h> 46.Fd #include <resolv.h>
47.Ft int
53.Fo res_query 48.Fo res_query
54.Fa "char *dname" 49.Fa "const char *dname"
55.Fa "int class" 50.Fa "int class"
56.Fa "int type" 51.Fa "int type"
57.Fa "u_char *answer" 52.Fa "unsigned char *answer"
58.Fa "int anslen" 53.Fa "int anslen"
59.Fc 54.Fc
55.Ft int
60.Fo res_search 56.Fo res_search
61.Fa "char *dname" 57.Fa "const char *dname"
62.Fa "int class" 58.Fa "int class"
63.Fa "int type" 59.Fa "int type"
64.Fa "u_char *answer" 60.Fa "unsigned char *answer"
65.Fa "int anslen" 61.Fa "int anslen"
66.Fc 62.Fc
63.Ft int
67.Fo res_mkquery 64.Fo res_mkquery
68.Fa "int op" 65.Fa "int op"
69.Fa "char *dname" 66.Fa "const char *dname"
70.Fa "int class" 67.Fa "int class"
71.Fa "int type" 68.Fa "int type"
72.Fa "char *data" 69.Fa "const unsigned char *data"
73.Fa "int datalen" 70.Fa "int datalen"
74.Fa "struct rrec *newrr" 71.Fa "const unsigned char *newrr"
75.Fa "char *buf" 72.Fa "unsigned char *buf"
76.Fa "int buflen" 73.Fa "int buflen"
77.Fc 74.Fc
75.Ft int
78.Fo res_send 76.Fo res_send
79.Fa "char *msg" 77.Fa "const unsigned char *msg"
80.Fa "int msglen" 78.Fa "int msglen"
81.Fa "char *answer" 79.Fa "unsigned char *answer"
82.Fa "int anslen" 80.Fa "int anslen"
83.Fc 81.Fc
84.Fn res_init 82.Ft int
83.Fn res_init "void"
84.Ft int
85.Fo dn_comp 85.Fo dn_comp
86.Fa "char *exp_dn" 86.Fa "const char *exp_dn"
87.Fa "char *comp_dn" 87.Fa "unsigned char *comp_dn"
88.Fa "int length" 88.Fa "int length"
89.Fa "char **dnptrs" 89.Fa "unsigned char **dnptrs"
90.Fa "char **lastdnptr" 90.Fa "unsigned char **lastdnptr"
91.Fc 91.Fc
92.Ft int
92.Fo dn_expand 93.Fo dn_expand
93.Fa "u_char *msg" 94.Fa "const unsigned char *msg"
94.Fa "u_char *eomorig" 95.Fa "const unsigned char *eomorig"
95.Fa "u_char *comp_dn" 96.Fa "const unsigned char *comp_dn"
96.Fa "u_char *exp_dn" 97.Fa "char *exp_dn"
97.Fa "int length" 98.Fa "int length"
98.Fc 99.Fc
99.Sh DESCRIPTION 100.Sh DESCRIPTION
100These routines are used for making, sending and interpreting 101These routines are used for making, sending, and interpreting
101query and reply messages with Internet domain name servers. 102query and reply messages with Internet domain name servers.
102.Pp 103.Pp
103Global configuration and state information that is used by the 104Global configuration and state information that is used by the
104resolver routines is kept in the structure 105resolver routines is kept in the structure
105.Em _res . 106.Li _res .
106Most of the values have reasonable defaults and can be ignored. 107Most of the values have reasonable defaults and can be ignored.
107Options 108Options stored in
108stored in 109.Li _res.options
109.Em _res.options
110are defined in 110are defined in
111.Pa resolv.h 111.Aq Pa resolv.h
112and are as follows. 112and are as follows.
113Options are stored as a simple bit mask containing the bitwise ``or'' 113Options are stored as a simple bit mask containing the bitwise
114.Tn OR
114of the options enabled. 115of the options enabled.
115.Bl -tag -width RES_DEFNAMES 116.Bl -tag -width RES_USE_INET6
116.It Dv RES_INIT 117.It Dv RES_INIT
117True if the initial name server address and default domain name are 118True if the initial name server address and default domain name are
118initialized (i.e., 119initialized (i.e.,
@@ -137,8 +138,7 @@ Used with
137.Dv RES_USEVC 138.Dv RES_USEVC
138to keep the 139to keep the
139.Tn TCP 140.Tn TCP
140connection open between 141connection open between queries.
141queries.
142This is useful only in programs that regularly do many queries. 142This is useful only in programs that regularly do many queries.
143.Tn UDP 143.Tn UDP
144should be the normal mode used. 144should be the normal mode used.
@@ -165,16 +165,28 @@ will search for host names in the current domain and in parent domains; see
165This is used by the standard host lookup routine 165This is used by the standard host lookup routine
166.Xr gethostbyname 3 . 166.Xr gethostbyname 3 .
167This option is enabled by default. 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.
168.El 182.El
169.Pp 183.Pp
170The 184The
171.Fn res_init 185.Fn res_init
172routine 186routine reads the configuration file (if any; see
173reads the configuration file (if any; see
174.Xr resolv.conf 5 ) 187.Xr resolv.conf 5 )
175to get the default domain name, 188to get the default domain name, search list, and the Internet address
176search list and 189of the local name server(s).
177the Internet address of the local name server(s).
178If no server is configured, the host running 190If no server is configured, the host running
179the resolver is tried. 191the resolver is tried.
180The current domain name is defined by the hostname 192The current domain name is defined by the hostname
@@ -212,20 +224,26 @@ The query requests information of the specified
212.Fa type 224.Fa type
213and 225and
214.Fa class 226.Fa class
215for the specified fully-qualified domain name 227for the specified fully qualified domain name
216.Fa dname . 228.Fa dname .
217The reply message is left in the 229The reply message is left in the
218.Fa answer 230.Fa answer
219buffer with length 231buffer with length
220.Fa anslen 232.Fa anslen
221supplied by the caller. 233supplied by the caller.
234Values for the
235.Fa class
236and
237.Fa type
238fields
239are defined in
240.Aq Pa arpa/nameser.h .
222.Pp 241.Pp
223The 242The
224.Fn res_search 243.Fn res_search
225routine makes a query and awaits a response like 244routine makes a query and awaits a response like
226.Fn res_query , 245.Fn res_query ,
227but in addition, it implements the default and search rules 246but in addition, it implements the default and search rules controlled by the
228controlled by the
229.Dv RES_DEFNAMES 247.Dv RES_DEFNAMES
230and 248and
231.Dv RES_DNSRCH 249.Dv RES_DNSRCH
@@ -236,11 +254,9 @@ The remaining routines are lower-level routines used by
236.Fn res_query . 254.Fn res_query .
237The 255The
238.Fn res_mkquery 256.Fn res_mkquery
239function 257function constructs a standard query message and places it in
240constructs a standard query message and places it in
241.Fa buf . 258.Fa buf .
242It returns the size of the query, or \-1 if the query is 259It returns the size of the query, or \-1 if the query is larger than
243larger than
244.Fa buflen . 260.Fa buflen .
245The query type 261The query type
246.Fa op 262.Fa op
@@ -250,26 +266,23 @@ but can be any of the query types defined in
250.Aq Pa arpa/nameser.h . 266.Aq Pa arpa/nameser.h .
251The domain name for the query is given by 267The domain name for the query is given by
252.Fa dname . 268.Fa dname .
253.Fa Newrr 269.Fa newrr
254is currently unused but is intended for making update messages. 270is currently unused but is intended for making update messages.
255.Pp 271.Pp
256The 272The
257.Fn res_send 273.Fn res_send
258routine 274routine sends a pre-formatted query and returns an answer.
259sends a pre-formatted query and returns an answer.
260It will call 275It will call
261.Fn res_init 276.Fn res_init
262if 277if
263.Dv RES_INIT 278.Dv RES_INIT
264is not set, send the query to the local name server, and 279is not set, send the query to the local name server, and
265handle timeouts and retries. 280handle timeouts and retries.
266The length of the reply message is returned, or 281The length of the reply message is returned, or \-1 if there were errors.
267\-1 if there were errors.
268.Pp 282.Pp
269The 283The
270.Fn dn_comp 284.Fn dn_comp
271function 285function compresses the domain name
272compresses the domain name
273.Fa exp_dn 286.Fa exp_dn
274and stores it in 287and stores it in
275.Fa comp_dn . 288.Fa comp_dn .
@@ -278,24 +291,23 @@ The size of the array pointed to by
278.Fa comp_dn 291.Fa comp_dn
279is given by 292is given by
280.Fa length . 293.Fa length .
281The compression uses 294The compression uses an array of pointers
282an array of pointers
283.Fa dnptrs 295.Fa dnptrs
284to previously-compressed names in the current message. 296to previously compressed names in the current message.
285The first pointer points to 297The first pointer points
286to the beginning of the message and the list ends with 298to the beginning of the message and the list ends with
287.Dv NULL . 299.Dv NULL .
288The limit to the array is specified by 300The limit to the array is specified by
289.Fa lastdnptr . 301.Fa lastdnptr .
290A side effect of 302A side effect of
291.Fn dn_comp 303.Fn dn_comp
292is to update the list of pointers for 304is to update the list of pointers for labels inserted into the message
293labels inserted into the message
294as the name is compressed. 305as the name is compressed.
295If 306If
296.Em dnptr 307.Fa dnptrs
297is 308is
298.Dv NULL, names are not compressed. 309.Dv NULL ,
310names are not compressed.
299If 311If
300.Fa lastdnptr 312.Fa lastdnptr
301is 313is
@@ -304,10 +316,9 @@ the list of labels is not updated.
304.Pp 316.Pp
305The 317The
306.Fn dn_expand 318.Fn dn_expand
307entry 319entry expands the compressed domain name
308expands the compressed domain name
309.Fa comp_dn 320.Fa comp_dn
310to a full domain name 321to a full domain name.
311The compressed name is contained in a query or reply message; 322The compressed name is contained in a query or reply message;
312.Fa msg 323.Fa msg
313is a pointer to the beginning of the message. 324is a pointer to the beginning of the message.
@@ -317,28 +328,27 @@ which is of size
317.Fa length . 328.Fa length .
318The size of compressed name is returned or \-1 if there was an error. 329The size of compressed name is returned or \-1 if there was an error.
319.Sh FILES 330.Sh FILES
320.Bl -tag -width Pa 331.Bl -tag -width "/etc/resolv.confXX"
321/etc/resolv.conf 332.It Pa /etc/resolv.conf
322The configuration file 333The configuration file.
323see
324.Xr resolv.conf 5 .
325.El 334.El
326.Sh SEE ALSO 335.Sh SEE ALSO
327.Xr gethostbyname 3 , 336.Xr gethostbyname 3 ,
328.Xr named 8 ,
329.Xr resolv.conf 5 , 337.Xr resolv.conf 5 ,
330.Xr hostname 7 , 338.Xr hostname 7 ,
339.Xr named 8
331.Pp 340.Pp
332.%T RFC1032 , 341.%T RFC 974 ,
333.%T RFC1033 , 342.%T RFC 1032 ,
334.%T RFC1034 , 343.%T RFC 1033 ,
335.%T RFC1035 , 344.%T RFC 1034 ,
336.%T RFC974 345.%T RFC 1035 ,
346.%T RFC 1535
337.Rs 347.Rs
338.%T "Name Server Operations Guide for BIND" 348.%T "Name Server Operations Guide for BIND"
339.Re 349.Re
340.Sh HISTORY 350.Sh HISTORY
341The 351The
342.Nm 352.Nm
343function appeared in 353function appeared in
344.Bx 4.3 . 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..d10334e027
--- /dev/null
+++ b/src/lib/libc/net/rthdr.c
@@ -0,0 +1,378 @@
1/* $OpenBSD: rthdr.c,v 1.8 2006/12/09 01:12:28 itojun Exp $ */
2/* $KAME: rthdr.c,v 1.22 2006/02/09 08:18:58 keiichi 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#include <sys/param.h>
34#include <sys/types.h>
35#include <sys/socket.h>
36
37#include <netinet/in.h>
38#include <netinet/ip6.h>
39
40#include <string.h>
41#include <stdio.h>
42
43/*
44 * RFC2292 API
45 */
46
47size_t
48inet6_rthdr_space(int type, int seg)
49{
50 switch (type) {
51 case IPV6_RTHDR_TYPE_0:
52 if (seg < 1 || seg > 23)
53 return (0);
54 return (CMSG_SPACE(sizeof(struct in6_addr) * seg +
55 sizeof(struct ip6_rthdr0)));
56 default:
57 return (0);
58 }
59}
60
61struct cmsghdr *
62inet6_rthdr_init(void *bp, int type)
63{
64 struct cmsghdr *ch = (struct cmsghdr *)bp;
65 struct ip6_rthdr *rthdr;
66
67 rthdr = (struct ip6_rthdr *)CMSG_DATA(ch);
68
69 ch->cmsg_level = IPPROTO_IPV6;
70 ch->cmsg_type = IPV6_RTHDR;
71
72 switch (type) {
73 case IPV6_RTHDR_TYPE_0:
74 ch->cmsg_len = CMSG_LEN(sizeof(struct ip6_rthdr0));
75 bzero(rthdr, sizeof(struct ip6_rthdr0));
76 rthdr->ip6r_type = IPV6_RTHDR_TYPE_0;
77 return (ch);
78 default:
79 return (NULL);
80 }
81}
82
83int
84inet6_rthdr_add(struct cmsghdr *cmsg, const struct in6_addr *addr, u_int flags)
85{
86 struct ip6_rthdr *rthdr;
87
88 rthdr = (struct ip6_rthdr *)CMSG_DATA(cmsg);
89
90 switch (rthdr->ip6r_type) {
91 case IPV6_RTHDR_TYPE_0:
92 {
93 struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr;
94 if (flags != IPV6_RTHDR_LOOSE)
95 return (-1);
96 if (rt0->ip6r0_segleft == 23)
97 return (-1);
98 rt0->ip6r0_segleft++;
99 bcopy(addr, (caddr_t)rt0 + ((rt0->ip6r0_len + 1) << 3),
100 sizeof(struct in6_addr));
101 rt0->ip6r0_len += sizeof(struct in6_addr) >> 3;
102 cmsg->cmsg_len = CMSG_LEN((rt0->ip6r0_len + 1) << 3);
103 break;
104 }
105 default:
106 return (-1);
107 }
108
109 return (0);
110}
111
112int
113inet6_rthdr_lasthop(struct cmsghdr *cmsg, unsigned int flags)
114{
115 struct ip6_rthdr *rthdr;
116
117 rthdr = (struct ip6_rthdr *)CMSG_DATA(cmsg);
118
119 switch (rthdr->ip6r_type) {
120 case IPV6_RTHDR_TYPE_0:
121 {
122 struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr;
123 if (flags != IPV6_RTHDR_LOOSE)
124 return (-1);
125 if (rt0->ip6r0_segleft > 23)
126 return (-1);
127 break;
128 }
129 default:
130 return (-1);
131 }
132
133 return (0);
134}
135
136#if 0
137int
138inet6_rthdr_reverse(in, out)
139 const struct cmsghdr *in;
140 struct cmsghdr *out;
141{
142
143 return (-1);
144}
145#endif
146
147int
148inet6_rthdr_segments(const struct cmsghdr *cmsg)
149{
150 struct ip6_rthdr *rthdr;
151
152 rthdr = (struct ip6_rthdr *)CMSG_DATA(cmsg);
153
154 switch (rthdr->ip6r_type) {
155 case IPV6_RTHDR_TYPE_0:
156 {
157 struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr;
158
159 if (rt0->ip6r0_len % 2 || 46 < rt0->ip6r0_len)
160 return (-1);
161
162 return (rt0->ip6r0_len * 8) / sizeof(struct in6_addr);
163 }
164
165 default:
166 return (-1);
167 }
168}
169
170struct in6_addr *
171inet6_rthdr_getaddr(struct cmsghdr *cmsg, int index)
172{
173 struct ip6_rthdr *rthdr;
174
175 rthdr = (struct ip6_rthdr *)CMSG_DATA(cmsg);
176
177 switch (rthdr->ip6r_type) {
178 case IPV6_RTHDR_TYPE_0:
179 {
180 struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr;
181 int naddr;
182
183 if (rt0->ip6r0_len % 2 || 46 < rt0->ip6r0_len)
184 return NULL;
185 naddr = (rt0->ip6r0_len * 8) / sizeof(struct in6_addr);
186 if (index <= 0 || naddr < index)
187 return NULL;
188 return ((struct in6_addr *)(rt0 + 1)) + index;
189 }
190
191 default:
192 return NULL;
193 }
194}
195
196int
197inet6_rthdr_getflags(const struct cmsghdr *cmsg, int index)
198{
199 struct ip6_rthdr *rthdr;
200
201 rthdr = (struct ip6_rthdr *)CMSG_DATA(cmsg);
202
203 switch (rthdr->ip6r_type) {
204 case IPV6_RTHDR_TYPE_0:
205 {
206 struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr;
207 int naddr;
208
209 if (rt0->ip6r0_len % 2 || 46 < rt0->ip6r0_len)
210 return (-1);
211 naddr = (rt0->ip6r0_len * 8) / sizeof(struct in6_addr);
212 if (index < 0 || naddr < index)
213 return (-1);
214 return IPV6_RTHDR_LOOSE;
215 }
216
217 default:
218 return (-1);
219 }
220}
221
222/*
223 * RFC3542 (2292bis) API
224 */
225
226socklen_t
227inet6_rth_space(int type, int segments)
228{
229 switch (type) {
230 case IPV6_RTHDR_TYPE_0:
231 return (((segments * 2) + 1) << 3);
232 default:
233 return (0); /* type not suppported */
234 }
235}
236
237void *
238inet6_rth_init(void *bp, socklen_t bp_len, int type, int segments)
239{
240 struct ip6_rthdr *rth = (struct ip6_rthdr *)bp;
241 struct ip6_rthdr0 *rth0;
242
243 switch (type) {
244 case IPV6_RTHDR_TYPE_0:
245 /* length validation */
246 if (bp_len < inet6_rth_space(IPV6_RTHDR_TYPE_0, segments))
247 return (NULL);
248
249 memset(bp, 0, bp_len);
250 rth0 = (struct ip6_rthdr0 *)rth;
251 rth0->ip6r0_len = segments * 2;
252 rth0->ip6r0_type = IPV6_RTHDR_TYPE_0;
253 rth0->ip6r0_segleft = 0;
254 rth0->ip6r0_reserved = 0;
255 break;
256 default:
257 return (NULL); /* type not supported */
258 }
259
260 return (bp);
261}
262
263int
264inet6_rth_add(void *bp, const struct in6_addr *addr)
265{
266 struct ip6_rthdr *rth = (struct ip6_rthdr *)bp;
267 struct ip6_rthdr0 *rth0;
268 struct in6_addr *nextaddr;
269
270 switch (rth->ip6r_type) {
271 case IPV6_RTHDR_TYPE_0:
272 rth0 = (struct ip6_rthdr0 *)rth;
273 nextaddr = (struct in6_addr *)(rth0 + 1) + rth0->ip6r0_segleft;
274 *nextaddr = *addr;
275 rth0->ip6r0_segleft++;
276 break;
277 default:
278 return (-1); /* type not supported */
279 }
280
281 return (0);
282}
283
284int
285inet6_rth_reverse(const void *in, void *out)
286{
287 struct ip6_rthdr *rth_in = (struct ip6_rthdr *)in;
288 struct ip6_rthdr0 *rth0_in, *rth0_out;
289 int i, segments;
290
291 switch (rth_in->ip6r_type) {
292 case IPV6_RTHDR_TYPE_0:
293 rth0_in = (struct ip6_rthdr0 *)in;
294 rth0_out = (struct ip6_rthdr0 *)out;
295
296 /* parameter validation XXX too paranoid? */
297 if (rth0_in->ip6r0_len % 2)
298 return (-1);
299 segments = rth0_in->ip6r0_len / 2;
300
301 /* we can't use memcpy here, since in and out may overlap */
302 memmove((void *)rth0_out, (void *)rth0_in,
303 ((rth0_in->ip6r0_len) + 1) << 3);
304 rth0_out->ip6r0_segleft = segments;
305
306 /* reverse the addresses */
307 for (i = 0; i < segments / 2; i++) {
308 struct in6_addr addr_tmp, *addr1, *addr2;
309
310 addr1 = (struct in6_addr *)(rth0_out + 1) + i;
311 addr2 = (struct in6_addr *)(rth0_out + 1) +
312 (segments - i - 1);
313 addr_tmp = *addr1;
314 *addr1 = *addr2;
315 *addr2 = addr_tmp;
316 }
317
318 break;
319 default:
320 return (-1); /* type not supported */
321 }
322
323 return (0);
324}
325
326int
327inet6_rth_segments(const void *bp)
328{
329 struct ip6_rthdr *rh = (struct ip6_rthdr *)bp;
330 struct ip6_rthdr0 *rh0;
331 int addrs;
332
333 switch (rh->ip6r_type) {
334 case IPV6_RTHDR_TYPE_0:
335 rh0 = (struct ip6_rthdr0 *)bp;
336
337 /*
338 * Validation for a type-0 routing header.
339 * Is this too strict?
340 */
341 if ((rh0->ip6r0_len % 2) != 0 ||
342 (addrs = (rh0->ip6r0_len >> 1)) < rh0->ip6r0_segleft)
343 return (-1);
344
345 return (addrs);
346 default:
347 return (-1); /* unknown type */
348 }
349}
350
351struct in6_addr *
352inet6_rth_getaddr(const void *bp, int idx)
353{
354 struct ip6_rthdr *rh = (struct ip6_rthdr *)bp;
355 struct ip6_rthdr0 *rh0;
356 int addrs;
357
358 switch (rh->ip6r_type) {
359 case IPV6_RTHDR_TYPE_0:
360 rh0 = (struct ip6_rthdr0 *)bp;
361
362 /*
363 * Validation for a type-0 routing header.
364 * Is this too strict?
365 */
366 if ((rh0->ip6r0_len % 2) != 0 ||
367 (addrs = (rh0->ip6r0_len >> 1)) < rh0->ip6r0_segleft)
368 return (NULL);
369
370 if (idx < 0 || addrs <= idx)
371 return (NULL);
372
373 return (((struct in6_addr *)(rh0 + 1)) + idx);
374 default:
375 return (NULL); /* unknown type */
376 break;
377 }
378}
diff --git a/src/lib/libc/net/ruserok.c b/src/lib/libc/net/ruserok.c
new file mode 100644
index 0000000000..5ef078ac95
--- /dev/null
+++ b/src/lib/libc/net/ruserok.c
@@ -0,0 +1,437 @@
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 __check_rhosts_file = 1;
58char *__rcmd_errstr;
59
60int
61ruserok(const char *rhost, int superuser, const char *ruser, const char *luser)
62{
63 struct addrinfo hints, *res, *r;
64 int error;
65
66 memset(&hints, 0, sizeof(hints));
67 hints.ai_family = PF_UNSPEC;
68 hints.ai_socktype = SOCK_DGRAM; /*dummy*/
69 error = getaddrinfo(rhost, "0", &hints, &res);
70 if (error)
71 return (-1);
72
73 for (r = res; r; r = r->ai_next) {
74 if (iruserok_sa(r->ai_addr, r->ai_addrlen, superuser, ruser,
75 luser) == 0) {
76 freeaddrinfo(res);
77 return (0);
78 }
79 }
80 freeaddrinfo(res);
81 return (-1);
82}
83
84/*
85 * New .rhosts strategy: We are passed an ip address. We spin through
86 * hosts.equiv and .rhosts looking for a match. When the .rhosts only
87 * has ip addresses, we don't have to trust a nameserver. When it
88 * contains hostnames, we spin through the list of addresses the nameserver
89 * gives us and look for a match.
90 *
91 * Returns 0 if ok, -1 if not ok.
92 */
93int
94iruserok(u_int32_t raddr, int superuser, const char *ruser, const char *luser)
95{
96 struct sockaddr_in sin;
97
98 memset(&sin, 0, sizeof(sin));
99 sin.sin_family = AF_INET;
100 sin.sin_len = sizeof(struct sockaddr_in);
101 memcpy(&sin.sin_addr, &raddr, sizeof(sin.sin_addr));
102 return iruserok_sa(&sin, sizeof(struct sockaddr_in), superuser, ruser,
103 luser);
104}
105
106int
107iruserok_sa(const void *raddr, int rlen, int superuser, const char *ruser,
108 const char *luser)
109{
110 struct sockaddr *sa;
111 char *cp;
112 struct stat sbuf;
113 struct passwd *pwd;
114 FILE *hostf;
115 uid_t uid;
116 int first;
117 char pbuf[MAXPATHLEN];
118
119 sa = (struct sockaddr *)raddr;
120 first = 1;
121 hostf = superuser ? NULL : fopen(_PATH_HEQUIV, "r");
122again:
123 if (hostf) {
124 if (__ivaliduser_sa(hostf, sa, rlen, luser, ruser) == 0) {
125 (void)fclose(hostf);
126 return (0);
127 }
128 (void)fclose(hostf);
129 }
130 if (first == 1 && (__check_rhosts_file || superuser)) {
131 int len;
132
133 first = 0;
134 if ((pwd = getpwnam(luser)) == NULL)
135 return (-1);
136 len = snprintf(pbuf, sizeof pbuf, "%s/.rhosts", pwd->pw_dir);
137 if (len < 0 || len >= sizeof pbuf)
138 return (-1);
139
140 /*
141 * Change effective uid while opening .rhosts. If root and
142 * reading an NFS mounted file system, can't read files that
143 * are protected read/write owner only.
144 */
145 uid = geteuid();
146 (void)seteuid(pwd->pw_uid);
147 hostf = fopen(pbuf, "r");
148 (void)seteuid(uid);
149
150 if (hostf == NULL)
151 return (-1);
152 /*
153 * If not a regular file, or is owned by someone other than
154 * user or root or if writeable by anyone but the owner, quit.
155 */
156 cp = NULL;
157 if (lstat(pbuf, &sbuf) < 0)
158 cp = ".rhosts lstat failed";
159 else if (!S_ISREG(sbuf.st_mode))
160 cp = ".rhosts not regular file";
161 else if (fstat(fileno(hostf), &sbuf) < 0)
162 cp = ".rhosts fstat failed";
163 else if (sbuf.st_uid && sbuf.st_uid != pwd->pw_uid)
164 cp = "bad .rhosts owner";
165 else if (sbuf.st_mode & (S_IWGRP|S_IWOTH))
166 cp = ".rhosts writable by other than owner";
167 /* If there were any problems, quit. */
168 if (cp) {
169 __rcmd_errstr = cp;
170 (void)fclose(hostf);
171 return (-1);
172 }
173 goto again;
174 }
175 return (-1);
176}
177
178/*
179 * XXX
180 * Don't make static, used by lpd(8).
181 *
182 * Returns 0 if ok, -1 if not ok.
183 */
184int
185__ivaliduser(FILE *hostf, in_addr_t raddrl, const char *luser,
186 const char *ruser)
187{
188 struct sockaddr_in sin;
189
190 memset(&sin, 0, sizeof(sin));
191 sin.sin_family = AF_INET;
192 sin.sin_len = sizeof(struct sockaddr_in);
193 memcpy(&sin.sin_addr, &raddrl, sizeof(sin.sin_addr));
194 return __ivaliduser_sa(hostf, (struct sockaddr *)&sin, sin.sin_len,
195 luser, ruser);
196}
197
198int
199__ivaliduser_sa(FILE *hostf, struct sockaddr *raddr, socklen_t salen,
200 const char *luser, const char *ruser)
201{
202 char *user, *p;
203 char *buf;
204 const char *auser, *ahost;
205 int hostok, userok;
206 char *rhost = (char *)-1;
207 char domain[MAXHOSTNAMELEN];
208 size_t buflen;
209
210 getdomainname(domain, sizeof(domain));
211
212 while ((buf = fgetln(hostf, &buflen))) {
213 p = buf;
214 if (*p == '#')
215 continue;
216 while (p < buf + buflen && *p != '\n' && *p != ' ' && *p != '\t') {
217 if (!isprint(*p))
218 goto bail;
219 *p = isupper(*p) ? tolower(*p) : *p;
220 p++;
221 }
222 if (p >= buf + buflen)
223 continue;
224 if (*p == ' ' || *p == '\t') {
225 *p++ = '\0';
226 while (p < buf + buflen && (*p == ' ' || *p == '\t'))
227 p++;
228 if (p >= buf + buflen)
229 continue;
230 user = p;
231 while (p < buf + buflen && *p != '\n' && *p != ' ' &&
232 *p != '\t') {
233 if (!isprint(*p))
234 goto bail;
235 p++;
236 }
237 } else
238 user = p;
239 *p = '\0';
240
241 if (p == buf)
242 continue;
243
244 auser = *user ? user : luser;
245 ahost = buf;
246
247 if (strlen(ahost) >= MAXHOSTNAMELEN)
248 continue;
249
250 /*
251 * innetgr() must lookup a hostname (we do not attempt
252 * to change the semantics so that netgroups may have
253 * #.#.#.# addresses in the list.)
254 */
255 if (ahost[0] == '+')
256 switch (ahost[1]) {
257 case '\0':
258 hostok = 1;
259 break;
260 case '@':
261 if (rhost == (char *)-1)
262 rhost = __gethostloop(raddr, salen);
263 hostok = 0;
264 if (rhost)
265 hostok = innetgr(&ahost[2], rhost,
266 NULL, domain);
267 break;
268 default:
269 hostok = __icheckhost(raddr, salen, &ahost[1]);
270 break;
271 }
272 else if (ahost[0] == '-')
273 switch (ahost[1]) {
274 case '\0':
275 hostok = -1;
276 break;
277 case '@':
278 if (rhost == (char *)-1)
279 rhost = __gethostloop(raddr, salen);
280 hostok = 0;
281 if (rhost)
282 hostok = -innetgr(&ahost[2], rhost,
283 NULL, domain);
284 break;
285 default:
286 hostok = -__icheckhost(raddr, salen, &ahost[1]);
287 break;
288 }
289 else
290 hostok = __icheckhost(raddr, salen, ahost);
291
292
293 if (auser[0] == '+')
294 switch (auser[1]) {
295 case '\0':
296 userok = 1;
297 break;
298 case '@':
299 userok = innetgr(&auser[2], NULL, ruser,
300 domain);
301 break;
302 default:
303 userok = strcmp(ruser, &auser[1]) ? 0 : 1;
304 break;
305 }
306 else if (auser[0] == '-')
307 switch (auser[1]) {
308 case '\0':
309 userok = -1;
310 break;
311 case '@':
312 userok = -innetgr(&auser[2], NULL, ruser,
313 domain);
314 break;
315 default:
316 userok = strcmp(ruser, &auser[1]) ? 0 : -1;
317 break;
318 }
319 else
320 userok = strcmp(ruser, auser) ? 0 : 1;
321
322 /* Check if one component did not match */
323 if (hostok == 0 || userok == 0)
324 continue;
325
326 /* Check if we got a forbidden pair */
327 if (userok <= -1 || hostok <= -1)
328 return (-1);
329
330 /* Check if we got a valid pair */
331 if (hostok >= 1 && userok >= 1)
332 return (0);
333 }
334bail:
335 return (-1);
336}
337
338/*
339 * Returns "true" if match, 0 if no match. If we do not find any
340 * semblance of an A->PTR->A loop, allow a simple #.#.#.# match to work.
341 */
342static int
343__icheckhost(struct sockaddr *raddr, socklen_t salen, const char *lhost)
344{
345 struct addrinfo hints, *res, *r;
346 char h1[NI_MAXHOST], h2[NI_MAXHOST];
347 int error;
348 const int niflags = NI_NUMERICHOST;
349
350 h1[0] = '\0';
351 if (getnameinfo(raddr, salen, h1, sizeof(h1), NULL, 0,
352 niflags) != 0)
353 return (0);
354
355 /* Resolve laddr into sockaddr */
356 memset(&hints, 0, sizeof(hints));
357 hints.ai_family = raddr->sa_family;
358 hints.ai_socktype = SOCK_DGRAM; /*dummy*/
359 res = NULL;
360 error = getaddrinfo(lhost, "0", &hints, &res);
361 if (error)
362 return (0);
363
364 /*
365 * Try string comparisons between raddr and laddr.
366 */
367 for (r = res; r; r = r->ai_next) {
368 h2[0] = '\0';
369 if (getnameinfo(r->ai_addr, r->ai_addrlen, h2, sizeof(h2),
370 NULL, 0, niflags) != 0)
371 continue;
372 if (strcmp(h1, h2) == 0) {
373 freeaddrinfo(res);
374 return (1);
375 }
376 }
377
378 /* No match. */
379 freeaddrinfo(res);
380 return (0);
381}
382
383/*
384 * Return the hostname associated with the supplied address.
385 * Do a reverse lookup as well for security. If a loop cannot
386 * be found, pack the result of inet_ntoa() into the string.
387 */
388static char *
389__gethostloop(struct sockaddr *raddr, socklen_t salen)
390{
391 static char remotehost[NI_MAXHOST];
392 char h1[NI_MAXHOST], h2[NI_MAXHOST];
393 struct addrinfo hints, *res, *r;
394 int error;
395 const int niflags = NI_NUMERICHOST;
396
397 h1[0] = remotehost[0] = '\0';
398 if (getnameinfo(raddr, salen, remotehost, sizeof(remotehost),
399 NULL, 0, NI_NAMEREQD) != 0)
400 return (NULL);
401 if (getnameinfo(raddr, salen, h1, sizeof(h1), NULL, 0,
402 niflags) != 0)
403 return (NULL);
404
405 /*
406 * Look up the name and check that the supplied
407 * address is in the list
408 */
409 memset(&hints, 0, sizeof(hints));
410 hints.ai_family = raddr->sa_family;
411 hints.ai_socktype = SOCK_DGRAM; /*dummy*/
412 hints.ai_flags = AI_CANONNAME;
413 res = NULL;
414 error = getaddrinfo(remotehost, "0", &hints, &res);
415 if (error)
416 return (NULL);
417
418 for (r = res; r; r = r->ai_next) {
419 h2[0] = '\0';
420 if (getnameinfo(r->ai_addr, r->ai_addrlen, h2, sizeof(h2),
421 NULL, 0, niflags) != 0)
422 continue;
423 if (strcmp(h1, h2) == 0) {
424 freeaddrinfo(res);
425 return (remotehost);
426 }
427 }
428
429 /*
430 * either the DNS adminstrator has made a configuration
431 * mistake, or someone has attempted to spoof us
432 */
433 syslog(LOG_NOTICE, "rcmd: address %s not listed for host %s",
434 h1, res->ai_canonname ? res->ai_canonname : remotehost);
435 freeaddrinfo(res);
436 return (NULL);
437}
diff --git a/src/lib/libc/net/send.c b/src/lib/libc/net/send.c
index 88f3550ec6..1bfc80b87a 100644
--- a/src/lib/libc/net/send.c
+++ b/src/lib/libc/net/send.c
@@ -1,5 +1,4 @@
1/* $NetBSD: send.c,v 1.6 1995/02/25 06:21:02 cgd Exp $ */ 1/* $OpenBSD: send.c,v 1.5 2005/08/06 20:30:04 espie Exp $ */
2
3/* 2/*
4 * Copyright (c) 1988, 1993 3 * Copyright (c) 1988, 1993
5 * The Regents of the University of California. All rights reserved. 4 * The Regents of the University of California. All rights reserved.
@@ -12,11 +11,7 @@
12 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software 14 * 3. Neither the name of the University nor the names of its contributors
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software 15 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission. 16 * without specific prior written permission.
22 * 17 *
@@ -33,24 +28,13 @@
33 * SUCH DAMAGE. 28 * SUCH DAMAGE.
34 */ 29 */
35 30
36#if defined(LIBC_SCCS) && !defined(lint)
37#if 0
38static char sccsid[] = "@(#)send.c 8.2 (Berkeley) 2/21/94";
39#else
40static char rcsid[] = "$NetBSD: send.c,v 1.6 1995/02/25 06:21:02 cgd Exp $";
41#endif
42#endif /* LIBC_SCCS and not lint */
43
44#include <sys/types.h> 31#include <sys/types.h>
45#include <sys/socket.h> 32#include <sys/socket.h>
46 33
47#include <stddef.h> 34#include <stddef.h>
48 35
49ssize_t 36ssize_t
50send(s, msg, len, flags) 37send(int s, const void *msg, size_t len, int flags)
51 int s, flags;
52 size_t len;
53 const void *msg;
54{ 38{
55 return (sendto(s, msg, len, flags, NULL, 0)); 39 return (sendto(s, msg, len, flags, NULL, 0));
56} 40}
diff --git a/src/lib/libc/net/sethostent.c b/src/lib/libc/net/sethostent.c
index 00f6499695..6f6d0e405a 100644
--- a/src/lib/libc/net/sethostent.c
+++ b/src/lib/libc/net/sethostent.c
@@ -1,5 +1,4 @@
1/* $NetBSD: sethostent.c,v 1.4 1995/02/25 06:21:03 cgd Exp $ */ 1/* $OpenBSD: sethostent.c,v 1.9 2005/08/06 20:30:04 espie Exp $ */
2
3/* 2/*
4 * Copyright (c) 1985, 1993 3 * Copyright (c) 1985, 1993
5 * The Regents of the University of California. All rights reserved. 4 * The Regents of the University of California. All rights reserved.
@@ -12,11 +11,7 @@
12 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software 14 * 3. Neither the name of the University nor the names of its contributors
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software 15 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission. 16 * without specific prior written permission.
22 * 17 *
@@ -33,30 +28,30 @@
33 * SUCH DAMAGE. 28 * SUCH DAMAGE.
34 */ 29 */
35 30
36#if defined(LIBC_SCCS) && !defined(lint)
37#if 0
38static char sccsid[] = "@(#)sethostent.c 8.1 (Berkeley) 6/4/93";
39#else
40static char rcsid[] = "$NetBSD: sethostent.c,v 1.4 1995/02/25 06:21:03 cgd Exp $";
41#endif
42#endif /* LIBC_SCCS and not lint */
43
44#include <sys/param.h> 31#include <sys/param.h>
45#include <netinet/in.h> 32#include <netinet/in.h>
46#include <arpa/nameser.h> 33#include <arpa/nameser.h>
47#include <netdb.h> 34#include <netdb.h>
48#include <resolv.h> 35#include <resolv.h>
49 36
37#include "thread_private.h"
38
50void 39void
51sethostent(stayopen) 40sethostent(int stayopen)
52{ 41{
42 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
43
44 if (_res_init(0) == -1)
45 return;
53 if (stayopen) 46 if (stayopen)
54 _res.options |= RES_STAYOPEN | RES_USEVC; 47 _resp->options |= RES_STAYOPEN | RES_USEVC;
55} 48}
56 49
57void 50void
58endhostent() 51endhostent(void)
59{ 52{
60 _res.options &= ~(RES_STAYOPEN | RES_USEVC); 53 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
61 _res_close(); 54
55 _resp->options &= ~(RES_STAYOPEN | RES_USEVC);
56 res_close();
62} 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