Add BIND 9.2.4rc7.
[dragonfly.git] / contrib / bind-9.2.4rc7 / lib / isc / unix / net.c
blob7cbe374fe233e972046d65d6995aaf554d03616e
1 /*
2 * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1999-2001 Internet Software Consortium.
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.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
18 /* $Id: net.c,v 1.22.2.3 2004/03/09 06:12:11 marka Exp $ */
20 #include <config.h>
22 #include <errno.h>
23 #include <unistd.h>
25 #include <isc/log.h>
26 #include <isc/msgs.h>
27 #include <isc/net.h>
28 #include <isc/once.h>
29 #include <isc/strerror.h>
30 #include <isc/string.h>
31 #include <isc/util.h>
33 #if defined(ISC_PLATFORM_HAVEIPV6) && defined(ISC_PLATFORM_NEEDIN6ADDRANY)
34 const struct in6_addr isc_net_in6addrany = IN6ADDR_ANY_INIT;
35 #endif
37 #if defined(ISC_PLATFORM_HAVEIPV6) && defined(ISC_PLATFORM_NEEDIN6ADDRLOOPBACK)
38 const struct in6_addr isc_net_in6addrloop = IN6ADDR_LOOPBACK_INIT;
39 #endif
41 static isc_once_t once = ISC_ONCE_INIT;
42 static isc_result_t ipv4_result = ISC_R_NOTFOUND;
43 static isc_result_t ipv6_result = ISC_R_NOTFOUND;
45 static isc_result_t
46 try_proto(int domain) {
47 int s;
48 isc_result_t result = ISC_R_SUCCESS;
49 char strbuf[ISC_STRERRORSIZE];
51 s = socket(domain, SOCK_STREAM, 0);
52 if (s == -1) {
53 switch (errno) {
54 #ifdef EAFNOSUPPORT
55 case EAFNOSUPPORT:
56 #endif
57 #ifdef EPROTONOSUPPORT
58 case EPROTONOSUPPORT:
59 #endif
60 #ifdef EINVAL
61 case EINVAL:
62 #endif
63 return (ISC_R_NOTFOUND);
64 default:
65 isc__strerror(errno, strbuf, sizeof(strbuf));
66 UNEXPECTED_ERROR(__FILE__, __LINE__,
67 "socket() %s: %s",
68 isc_msgcat_get(isc_msgcat,
69 ISC_MSGSET_GENERAL,
70 ISC_MSG_FAILED,
71 "failed"),
72 strbuf);
73 return (ISC_R_UNEXPECTED);
77 #ifdef ISC_PLATFORM_HAVEIPV6
78 #ifdef WANT_IPV6
79 #ifdef ISC_PLATFORM_HAVEIN6PKTINFO
80 if (domain == PF_INET6) {
81 struct sockaddr_in6 sin6;
82 unsigned int len;
85 * Check to see if IPv6 is broken, as is common on Linux.
87 len = sizeof(sin6);
88 if (getsockname(s, (struct sockaddr *)&sin6, (void *)&len) < 0)
90 isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
91 ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR,
92 "retrieving the address of an IPv6 "
93 "socket from the kernel failed.");
94 isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
95 ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR,
96 "IPv6 support is disabled.");
97 result = ISC_R_NOTFOUND;
98 } else {
99 if (len == sizeof(struct sockaddr_in6))
100 result = ISC_R_SUCCESS;
101 else {
102 isc_log_write(isc_lctx,
103 ISC_LOGCATEGORY_GENERAL,
104 ISC_LOGMODULE_SOCKET,
105 ISC_LOG_ERROR,
106 "IPv6 structures in kernel and "
107 "user space do not match.");
108 isc_log_write(isc_lctx,
109 ISC_LOGCATEGORY_GENERAL,
110 ISC_LOGMODULE_SOCKET,
111 ISC_LOG_ERROR,
112 "IPv6 support is disabled.");
113 result = ISC_R_NOTFOUND;
117 #endif
118 #endif
119 #endif
121 close(s);
123 return (result);
126 static void
127 initialize_action(void) {
128 ipv4_result = try_proto(PF_INET);
129 #ifdef ISC_PLATFORM_HAVEIPV6
130 #ifdef WANT_IPV6
131 #ifdef ISC_PLATFORM_HAVEIN6PKTINFO
132 ipv6_result = try_proto(PF_INET6);
133 #endif
134 #endif
135 #endif
138 static void
139 initialize(void) {
140 RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS);
143 isc_result_t
144 isc_net_probeipv4(void) {
145 initialize();
146 return (ipv4_result);
149 isc_result_t
150 isc_net_probeipv6(void) {
151 initialize();
152 return (ipv6_result);