available, and suppress wildcard binding if not.
1621. [bug] match-destinations did not work for IPv6 TCP queries.
[RT# 11156]
"sending notifies" log message when also-notify was
used. [RT #11177]
-1622. [placeholder] rt11156
+1622. [func] probe the system to see if IPV6_(RECV)PKTINFO is
+ available, and suppress wildcard binding if not.
-1621. [placeholder] rt11156
+1621. [bug] match-destinations did not work for IPv6 TCP queries.
+ [RT# 11156]
1620. [func] When loading a zone report if it is signed. [RT #11149]
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: client.c,v 1.219 2004/03/05 04:57:46 marka Exp $ */
+/* $Id: client.c,v 1.220 2004/04/29 01:37:12 marka Exp $ */
#include <config.h>
}
/*
- * Determine the destination address. For IPv6, we get this from the
- * pktinfo structure (if supported). For IPv4, we have to make do with
- * the address of the interface where the request was received.
+ * Determine the destination address. If the receiving interface is
+ * bound to a specific address, we simply use it regardless of the
+ * address family. All IPv4 queries should fall into this case.
+ * Otherwise, if this is a TCP query, get the address from the
+ * receiving socket (this needs a system call and can be heavy).
+ * For IPv6 UDP queries, we get this from the pktinfo structure (if
+ * supported).
+ * If all the attempts fail (this can happen due to memory shortage,
+ * etc), we regard this as an error for safety.
*/
- if (client->interface->addr.type.sa.sa_family == AF_INET6) {
- if ((client->attributes & NS_CLIENTATTR_PKTINFO) != 0) {
+ if ((client->interface->flags & NS_INTERFACEFLAG_ANYADDR) == 0)
+ isc_netaddr_fromsockaddr(&destaddr, &client->interface->addr);
+ else {
+ result = ISC_R_FAILURE;
+
+ if (TCP_CLIENT(client)) {
+ isc_sockaddr_t destsockaddr;
+
+ result = isc_socket_getsockname(client->tcpsocket,
+ &destsockaddr);
+ if (result == ISC_R_SUCCESS)
+ isc_netaddr_fromsockaddr(&destaddr,
+ &destsockaddr);
+ }
+ if (result != ISC_R_SUCCESS &&
+ client->interface->addr.type.sa.sa_family == AF_INET6 &&
+ (client->attributes & NS_CLIENTATTR_PKTINFO) != 0) {
isc_uint32_t zone = 0;
/*
isc_netaddr_fromin6(&destaddr,
&client->pktinfo.ipi6_addr);
isc_netaddr_setzone(&destaddr, zone);
-
- } else
- isc_netaddr_any6(&destaddr);
- } else {
- isc_netaddr_fromsockaddr(&destaddr, &client->interface->addr);
+ result = ISC_R_SUCCESS;
+ }
+ if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "failed to get request's "
+ "destination: %s",
+ isc_result_totext(result));
+ goto cleanup;
+ }
}
/*
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: interfacemgr.h,v 1.26 2004/03/05 04:57:55 marka Exp $ */
+/* $Id: interfacemgr.h,v 1.27 2004/04/29 01:37:13 marka Exp $ */
#ifndef NAMED_INTERFACEMGR_H
#define NAMED_INTERFACEMGR_H 1
#define IFACE_MAGIC ISC_MAGIC('I',':','-',')')
#define NS_INTERFACE_VALID(t) ISC_MAGIC_VALID(t, IFACE_MAGIC)
+#define NS_INTERFACEFLAG_ANYADDR 0x01U /* bound to "any" address */
+
struct ns_interface {
unsigned int magic; /* Magic number. */
ns_interfacemgr_t * mgr; /* Interface manager. */
int references; /* Locked */
unsigned int generation; /* Generation number. */
isc_sockaddr_t addr; /* Address and port. */
+ unsigned int flags; /* Interface characteristics */
char name[32]; /* Null terminated. */
dns_dispatch_t * udpdispatch; /* UDP dispatcher. */
isc_socket_t * tcpsocket; /* TCP socket. */
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: interfacemgr.c,v 1.76 2004/03/05 04:57:46 marka Exp $ */
+/* $Id: interfacemgr.c,v 1.77 2004/04/29 01:37:12 marka Exp $ */
#include <config.h>
isc_boolean_t scan_ipv6 = ISC_FALSE;
isc_boolean_t adjusting = ISC_FALSE;
isc_boolean_t ipv6only = ISC_TRUE;
+ isc_boolean_t ipv6pktinfo = ISC_TRUE;
isc_result_t result;
isc_netaddr_t zero_address, zero_address6;
ns_listenelt_t *le;
log_explicit = ISC_TRUE;
}
#endif
- if (scan_ipv6 == ISC_TRUE && ipv6only) {
+ if (scan_ipv6 == ISC_TRUE &&
+ isc_net_probe_ipv6pktinfo() != ISC_R_SUCCESS) {
+ ipv6pktinfo = ISC_FALSE;
+ log_explicit = ISC_TRUE;
+ }
+ if (scan_ipv6 == ISC_TRUE && ipv6only && ipv6pktinfo) {
for (le = ISC_LIST_HEAD(mgr->listenon6->elts);
le != NULL;
le = ISC_LIST_NEXT(le, link)) {
result = ns_interface_setup(mgr, &listen_addr,
"<any>", &ifp,
ISC_TRUE);
- if (result != ISC_R_SUCCESS)
+ if (result == ISC_R_SUCCESS)
+ ifp->flags |= NS_INTERFACEFLAG_ANYADDR;
+ else
isc_log_write(IFMGR_COMMON_LOGARGS,
ISC_LOG_ERROR,
"listening on all IPv6 "
* The case of "any" IPv6 address will require
* special considerations later, so remember it.
*/
- if (family == AF_INET6 && ipv6only &&
+ if (family == AF_INET6 && ipv6only && ipv6pktinfo &&
listenon_is_ip6_any(le))
ipv6_wildcard = ISC_TRUE;
continue;
if (log_explicit && family == AF_INET6 &&
- !adjusting) {
+ !adjusting && listenon_is_ip6_any(le)) {
isc_log_write(IFMGR_COMMON_LOGARGS,
verbose ? ISC_LOG_INFO :
ISC_LOG_DEBUG(1),
- "IPv6-only option is not"
- " available; explicitly"
- " binding to all IPv6"
- " addresses.");
+ "IPv6 socket API is "
+ "incomplete; explicitly "
+ "binding to each IPv6 "
+ "address separately");
log_explicit = ISC_FALSE;
}
isc_sockaddr_format(&listen_sockaddr,
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: net.h,v 1.39 2004/03/05 05:11:52 marka Exp $ */
+/* $Id: net.h,v 1.40 2004/04/29 01:37:13 marka Exp $ */
#ifndef ISC_NET_H
#define ISC_NET_H 1
* ISC_R_UNEXPECTED
*/
+isc_result_t
+isc_net_probe_ipv6pktinfo(void);
+/*
+ * Check if the system's kernel supports the IPV6_(RECV)PKTINFO socket option
+ * for UDP sockets.
+ *
+ * Returns:
+ *
+ * ISC_R_SUCCESS the option is supported.
+ * ISC_R_NOTFOUND IPv6 itself or the option is not supported.
+ * ISC_R_UNEXPECTED
+ */
+
void
isc_net_disableipv4(void);
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: net.c,v 1.29 2004/03/05 05:11:46 marka Exp $ */
+/* $Id: net.c,v 1.30 2004/04/29 01:37:13 marka Exp $ */
#include <config.h>
static isc_once_t once = ISC_ONCE_INIT;
static isc_once_t once_ipv6only = ISC_ONCE_INIT;
+static isc_once_t once_ipv6pktinfo = ISC_ONCE_INIT;
static isc_result_t ipv4_result = ISC_R_NOTFOUND;
static isc_result_t ipv6_result = ISC_R_NOTFOUND;
static isc_result_t ipv6only_result = ISC_R_NOTFOUND;
+static isc_result_t ipv6pktinfo_result = ISC_R_NOTFOUND;
static isc_result_t
try_proto(int domain) {
close:
close(s);
return;
-#endif
+#endif /* IPV6_V6ONLY */
}
static void
RUNTIME_CHECK(isc_once_do(&once_ipv6only,
try_ipv6only) == ISC_R_SUCCESS);
}
+#endif /* IPV6_V6ONLY */
+
+static void
+try_ipv6pktinfo(void) {
+ int s, on;
+ char strbuf[ISC_STRERRORSIZE];
+ isc_result_t result;
+ int optname;
+
+ result = isc_net_probeipv6();
+ if (result != ISC_R_SUCCESS) {
+ ipv6pktinfo_result = result;
+ return;
+ }
+
+ /* we only use this for UDP sockets */
+ s = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
+ if (s == -1) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "socket() %s: %s",
+ isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED,
+ "failed"),
+ strbuf);
+ ipv6pktinfo_result = ISC_R_UNEXPECTED;
+ return;
+ }
+
+#ifdef IPV6_RECVPKTINFO
+ optname = IPV6_RECVPKTINFO;
+#else
+ optname = IPV6_PKTINFO;
#endif
-#endif
+ on = 1;
+ if (setsockopt(s, IPPROTO_IPV6, optname, &on, sizeof(on)) < 0) {
+ ipv6pktinfo_result = ISC_R_NOTFOUND;
+ goto close;
+ }
+
+ close(s);
+ ipv6pktinfo_result = ISC_R_SUCCESS;
+
+close:
+ close(s);
+ return;
+}
+
+static void
+initialize_ipv6pktinfo(void) {
+ RUNTIME_CHECK(isc_once_do(&once_ipv6pktinfo,
+ try_ipv6pktinfo) == ISC_R_SUCCESS);
+}
+#endif /* WANT_IPV6 */
isc_result_t
isc_net_probe_ipv6only(void) {
return (ipv6only_result);
}
+isc_result_t
+isc_net_probe_ipv6pktinfo(void) {
+#ifdef ISC_PLATFORM_HAVEIPV6
+#ifdef WANT_IPV6
+ initialize_ipv6pktinfo();
+#else
+ ipv6pktinfo_result = ISC_R_NOTFOUND;
+#endif
+#endif
+ return (ipv6pktinfo_result);
+}
+
void
isc_net_disableipv4(void) {
initialize();
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: net.h,v 1.22 2004/04/19 04:16:55 marka Exp $ */
+/* $Id: net.h,v 1.23 2004/04/29 01:37:14 marka Exp $ */
#ifndef ISC_NET_H
#define ISC_NET_H 1
* ISC_R_UNEXPECTED
*/
+isc_result_t
+isc_net_probe_ipv6pktinfo(void);
+/*
+ * Check if the system's kernel supports the IPV6_(RECV)PKTINFO socket option
+ * for UDP sockets.
+ *
+ * Returns:
+ *
+ * ISC_R_SUCCESS the option is supported.
+ * ISC_R_NOTFOUND IPv6 itself or the option is not supported.
+ * ISC_R_UNEXPECTED
+ */
+
void
isc_net_disableipv4(void);
isc_task_getcurrenttime
isc_net_probe_ipv6only
isc_timermgr_poke
+isc_net_probe_ipv6pktinfo
; Exported Data
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: net.c,v 1.9 2004/03/16 05:52:22 marka Exp $ */
+/* $Id: net.c,v 1.10 2004/04/29 01:37:14 marka Exp $ */
#include <config.h>
static isc_once_t once = ISC_ONCE_INIT;
static isc_once_t once_ipv6only = ISC_ONCE_INIT;
+static isc_once_t once_ipv6pktinfo = ISC_ONCE_INIT;
static isc_result_t ipv4_result = ISC_R_NOTFOUND;
static isc_result_t ipv6_result = ISC_R_NOTFOUND;
static isc_result_t ipv6only_result = ISC_R_NOTFOUND;
+static isc_result_t ipv6pktinfo_result = ISC_R_NOTFOUND;
static isc_result_t
try_proto(int domain) {
close:
close(s);
return;
-#endif
+#endif /* IPV6_V6ONLY */
}
static void
RUNTIME_CHECK(isc_once_do(&once_ipv6only,
try_ipv6only) == ISC_R_SUCCESS);
}
+
+static void
+try_ipv6pktinfo(void) {
+ int s, on;
+ char strbuf[ISC_STRERRORSIZE];
+ isc_result_t result;
+ int optname;
+
+ result = isc_net_probeipv6();
+ if (result != ISC_R_SUCCESS) {
+ ipv6pktinfo_result = result;
+ return;
+ }
+
+ /* we only use this for UDP sockets */
+ s = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
+ if (s == -1) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "socket() %s: %s",
+ isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED,
+ "failed"),
+ strbuf);
+ ipv6pktinfo_result = ISC_R_UNEXPECTED;
+ return;
+ }
+
+#ifdef IPV6_RECVPKTINFO
+ optname = IPV6_RECVPKTINFO;
+#else
+ optname = IPV6_PKTINFO;
#endif
-#endif
+ on = 1;
+ if (setsockopt(s, IPPROTO_IPV6, optname, &on, sizeof(on)) < 0) {
+ ipv6pktinfo_result = ISC_R_NOTFOUND;
+ goto close;
+ }
+
+ close(s);
+ ipv6pktinfo_result = ISC_R_SUCCESS;
+
+close:
+ close(s);
+ return;
+}
+
+static void
+initialize_ipv6pktinfo(void) {
+ RUNTIME_CHECK(isc_once_do(&once_ipv6pktinfo,
+ try_ipv6pktinfo) == ISC_R_SUCCESS);
+}
+#endif /* WANT_IPV6 */
+#endif /* ISC_PLATFORM_HAVEIPV6 */
isc_result_t
isc_net_probe_ipv6only(void) {
return (ipv6only_result);
}
+isc_result_t
+isc_net_probe_ipv6pktinfo(void) {
+#ifdef ISC_PLATFORM_HAVEIPV6
+#ifdef WANT_IPV6
+ initialize_ipv6pktinfo();
+#else
+ ipv6pktinfo_result = ISC_R_NOTFOUND;
+#endif
+#endif
+ return (ipv6pktinfo_result);
+}
+
void
isc_net_disableipv4(void) {
initialize();