From 3aca8e5bf3740bbcc3bb13dde242d7cc369abb27 Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Thu, 10 Feb 2005 05:53:43 +0000 Subject: [PATCH] 1758. [func] Don't send notify messages to self. [RT #12933] --- CHANGES | 2 +- bin/named/client.c | 60 ++++++++++++++++++++++- bin/named/include/named/client.h | 10 +++- bin/named/include/named/interfacemgr.h | 5 +- bin/named/interfacemgr.c | 66 +++++++++++++++++++++++++- bin/named/zoneconf.c | 5 +- lib/dns/include/dns/types.h | 6 ++- lib/dns/include/dns/zone.h | 16 ++++++- lib/dns/win32/libdns.def | 1 + lib/dns/zone.c | 58 +++++++++++++++++++++- 10 files changed, 220 insertions(+), 9 deletions(-) diff --git a/CHANGES b/CHANGES index f234543682..0b31ccc29b 100644 --- a/CHANGES +++ b/CHANGES @@ -145,7 +145,7 @@ 1759. [bug] Named failed to startup if the OS supported IPv6 but had no IPv6 interfaces configured. [RT #12942] -1758. [placeholder] rt12933 +1758. [func] Don't send notify messages to self. [RT #12933] 1757. [func] host now can turn on memory debugging flags with '-m'. diff --git a/bin/named/client.c b/bin/named/client.c index b7533fe12d..689306a850 100644 --- a/bin/named/client.c +++ b/bin/named/client.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: client.c,v 1.222 2004/09/26 22:34:32 marka Exp $ */ +/* $Id: client.c,v 1.223 2005/02/10 05:53:41 marka Exp $ */ #include @@ -1110,6 +1110,64 @@ allowed(isc_netaddr_t *addr, dns_name_t *signer, dns_acl_t *acl) { return (ISC_FALSE); } +/* + * Callback to see if a non-recursive query coming from 'srcaddr' to + * 'destaddr', with optional key 'mykey' for class 'rdclass' would be + * delivered to 'myview'. + * + * We run this unlocked as both the view list and the interface list + * are updated when the approprite task has exclusivity. + */ +isc_boolean_t +ns_client_isself(dns_view_t *myview, dns_tsigkey_t *mykey, + isc_sockaddr_t *srcaddr, isc_sockaddr_t *dstaddr, + dns_rdataclass_t rdclass, void *arg) +{ + dns_view_t *view; + dns_tsigkey_t *key; + isc_netaddr_t netsrc; + isc_netaddr_t netdst; + + UNUSED(arg); + + if (!ns_interfacemgr_listeningon(ns_g_server->interfacemgr, dstaddr)) + return (ISC_FALSE); + + isc_netaddr_fromsockaddr(&netsrc, srcaddr); + isc_netaddr_fromsockaddr(&netdst, dstaddr); + + for (view = ISC_LIST_HEAD(ns_g_server->viewlist); + view != NULL; + view = ISC_LIST_NEXT(view, link)) { + dns_name_t *tsig = NULL; + + if (view->matchrecursiveonly) + continue; + + if (rdclass != view->rdclass) + continue; + + if (mykey != NULL) { + isc_boolean_t match; + isc_result_t result; + + tsig = &mykey->name; + result = dns_view_gettsig(view, tsig, &key); + if (result != ISC_R_SUCCESS) + continue; + match = dst_key_compare(mykey->key, key->key); + dns_tsigkey_detach(&key); + if (!match) + continue; + } + + if (allowed(&netsrc, tsig, view->matchclients) && + allowed(&netdst, tsig, view->matchdestinations)) + break; + } + return (ISC_TF(view == myview)); +} + /* * Handle an incoming request event from the socket (UDP case) * or tcpmsg (TCP case). diff --git a/bin/named/include/named/client.h b/bin/named/include/named/client.h index dbbc77ce27..9dc9d7d52a 100644 --- a/bin/named/include/named/client.h +++ b/bin/named/include/named/client.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: client.h,v 1.70 2004/07/23 02:57:27 marka Exp $ */ +/* $Id: client.h,v 1.71 2005/02/10 05:53:42 marka Exp $ */ #ifndef NAMED_CLIENT_H #define NAMED_CLIENT_H 1 @@ -334,4 +334,12 @@ ns_client_dumprecursing(FILE *f, ns_clientmgr_t *manager); * Dump the outstanding recursive queries to 'f'. */ +isc_boolean_t +ns_client_isself(dns_view_t *myview, dns_tsigkey_t *mykey, + isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr, + dns_rdataclass_t rdclass, void *arg); +/* + * Isself callback. + */ + #endif /* NAMED_CLIENT_H */ diff --git a/bin/named/include/named/interfacemgr.h b/bin/named/include/named/interfacemgr.h index 9c4d422ef7..2e98aab3dc 100644 --- a/bin/named/include/named/interfacemgr.h +++ b/bin/named/include/named/interfacemgr.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: interfacemgr.h,v 1.27 2004/04/29 01:37:13 marka Exp $ */ +/* $Id: interfacemgr.h,v 1.28 2005/02/10 05:53:42 marka Exp $ */ #ifndef NAMED_INTERFACEMGR_H #define NAMED_INTERFACEMGR_H 1 @@ -170,4 +170,7 @@ ns_interface_shutdown(ns_interface_t *ifp); void ns_interfacemgr_dumprecursing(FILE *f, ns_interfacemgr_t *mgr); +isc_boolean_t +ns_interfacemgr_listeningon(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr); + #endif /* NAMED_INTERFACEMGR_H */ diff --git a/bin/named/interfacemgr.c b/bin/named/interfacemgr.c index 3b58baa171..3cd8739e7d 100644 --- a/bin/named/interfacemgr.c +++ b/bin/named/interfacemgr.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: interfacemgr.c,v 1.78 2004/08/10 04:55:39 jinmei Exp $ */ +/* $Id: interfacemgr.c,v 1.79 2005/02/10 05:53:41 marka Exp $ */ #include @@ -50,11 +50,15 @@ struct ns_interfacemgr { ns_listenlist_t * listenon6; dns_aclenv_t aclenv; /* Localhost/localnets ACLs */ ISC_LIST(ns_interface_t) interfaces; /* List of interfaces. */ + ISC_LIST(isc_sockaddr_t) listenon; }; static void purge_old_interfaces(ns_interfacemgr_t *mgr); +static void +clearlistenon(ns_interfacemgr_t *mgr); + isc_result_t ns_interfacemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, isc_socketmgr_t *socketmgr, @@ -85,6 +89,7 @@ ns_interfacemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, mgr->listenon6 = NULL; ISC_LIST_INIT(mgr->interfaces); + ISC_LIST_INIT(mgr->listenon); /* * The listen-on lists are initially empty. @@ -117,6 +122,7 @@ ns_interfacemgr_destroy(ns_interfacemgr_t *mgr) { dns_aclenv_destroy(&mgr->aclenv); ns_listenlist_detach(&mgr->listenon4); ns_listenlist_detach(&mgr->listenon6); + clearlistenon(mgr); DESTROYLOCK(&mgr->lock); mgr->magic = 0; isc_mem_put(mgr->mctx, mgr, sizeof(*mgr)); @@ -536,6 +542,43 @@ setup_locals(ns_interfacemgr_t *mgr, isc_interface_t *interface) { return (ISC_R_SUCCESS); } +static void +setup_listenon(ns_interfacemgr_t *mgr, isc_interface_t *interface, + in_port_t port) +{ + isc_sockaddr_t *addr; + isc_sockaddr_t *old; + + addr = isc_mem_get(mgr->mctx, sizeof(*addr)); + if (addr == NULL) + return; + + isc_sockaddr_fromnetaddr(addr, &interface->address, port); + + for (old = ISC_LIST_HEAD(mgr->listenon); + old != NULL; + old = ISC_LIST_NEXT(old, link)) + if (isc_sockaddr_equal(addr, old)) + break; + + if (old != NULL) + isc_mem_put(mgr->mctx, addr, sizeof(*addr)); + else + ISC_LIST_APPEND(mgr->listenon, addr, link); +} + +static void +clearlistenon(ns_interfacemgr_t *mgr) { + isc_sockaddr_t *old; + + old = ISC_LIST_HEAD(mgr->listenon); + while (old != NULL) { + ISC_LIST_UNLINK(mgr->listenon, old, link); + isc_mem_put(mgr->mctx, old, sizeof(*old)); + old = ISC_LIST_HEAD(mgr->listenon); + } +} + static isc_result_t do_scan(ns_interfacemgr_t *mgr, ns_listenlist_t *ext_listen, isc_boolean_t verbose) @@ -552,6 +595,7 @@ do_scan(ns_interfacemgr_t *mgr, ns_listenlist_t *ext_listen, isc_sockaddr_t listen_addr; ns_interface_t *ifp; isc_boolean_t log_explicit = ISC_FALSE; + isc_boolean_t dolistenon; if (ext_listen != NULL) adjusting = ISC_TRUE; @@ -642,6 +686,7 @@ do_scan(ns_interfacemgr_t *mgr, ns_listenlist_t *ext_listen, result = clearacl(mgr->mctx, &mgr->aclenv.localnets); if (result != ISC_R_SUCCESS) goto cleanup_iter; + clearlistenon(mgr); } for (result = isc_interfaceiter_first(iter); @@ -687,6 +732,7 @@ do_scan(ns_interfacemgr_t *mgr, ns_listenlist_t *ext_listen, } ll = (family == AF_INET) ? mgr->listenon4 : mgr->listenon6; + dolistenon = ISC_TRUE; for (le = ISC_LIST_HEAD(ll->elts); le != NULL; le = ISC_LIST_NEXT(le, link)) @@ -723,6 +769,11 @@ do_scan(ns_interfacemgr_t *mgr, ns_listenlist_t *ext_listen, if (match <= 0) continue; + if (adjusting == ISC_FALSE && dolistenon == ISC_TRUE) { + setup_listenon(mgr, &interface, le->port); + dolistenon = ISC_FALSE; + } + /* * The case of "any" IPv6 address will require * special considerations later, so remember it. @@ -909,3 +960,16 @@ ns_interfacemgr_dumprecursing(FILE *f, ns_interfacemgr_t *mgr) { } UNLOCK(&mgr->lock); } + +isc_boolean_t +ns_interfacemgr_listeningon(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr) { + isc_sockaddr_t *old; + + old = ISC_LIST_HEAD(mgr->listenon); + for (old = ISC_LIST_HEAD(mgr->listenon); + old != NULL; + old = ISC_LIST_NEXT(old, link)) + if (isc_sockaddr_equal(old, addr)) + return (ISC_TRUE); + return (ISC_FALSE); +} diff --git a/bin/named/zoneconf.c b/bin/named/zoneconf.c index e02427219e..cd026617ea 100644 --- a/bin/named/zoneconf.c +++ b/bin/named/zoneconf.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: zoneconf.c,v 1.118 2005/01/11 23:10:04 marka Exp $ */ +/* $Id: zoneconf.c,v 1.119 2005/02/10 05:53:42 marka Exp $ */ #include @@ -35,6 +35,7 @@ #include #include +#include #include #include #include @@ -494,6 +495,8 @@ ns_zone_configure(cfg_obj_t *config, cfg_obj_t *vconfig, cfg_obj_t *zconfig, RETERR(dns_zone_setnotifysrc6(zone, cfg_obj_assockaddr(obj))); ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj)); + dns_zone_setisself(zone, ns_client_isself, NULL); + RETERR(configure_zone_acl(zconfig, vconfig, config, "allow-transfer", ac, zone, dns_zone_setxfracl, diff --git a/lib/dns/include/dns/types.h b/lib/dns/include/dns/types.h index 625380b417..d64d182253 100644 --- a/lib/dns/include/dns/types.h +++ b/lib/dns/include/dns/types.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: types.h,v 1.111 2004/12/21 10:45:19 jinmei Exp $ */ +/* $Id: types.h,v 1.112 2005/02/10 05:53:43 marka Exp $ */ #ifndef DNS_TYPES_H #define DNS_TYPES_H 1 @@ -299,4 +299,8 @@ typedef void typedef int (*dns_rdatasetorderfunc_t)(dns_rdata_t *rdata, void *arg); +typedef isc_boolean_t +(*dns_isselffunc_t)(dns_view_t *, dns_tsigkey_t *, isc_sockaddr_t *, + isc_sockaddr_t *, dns_rdataclass_t, void *); + #endif /* DNS_TYPES_H */ diff --git a/lib/dns/include/dns/zone.h b/lib/dns/include/dns/zone.h index 78a3e28587..3df380b588 100644 --- a/lib/dns/include/dns/zone.h +++ b/lib/dns/include/dns/zone.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: zone.h,v 1.131 2005/01/11 23:10:05 marka Exp $ */ +/* $Id: zone.h,v 1.132 2005/02/10 05:53:43 marka Exp $ */ #ifndef DNS_ZONE_H #define DNS_ZONE_H 1 @@ -1464,6 +1464,20 @@ dns_zone_getnotifydelay(dns_zone_t *zone); * 'zone' to be valid. */ +void +dns_zone_setisself(dns_zone_t *zone, dns_isselffunc_t isself, void *arg); +/* + * Set the isself callback function and arguement. + * + * isc_boolean_t + * isself(dns_view_t *myview, dns_tsigkey_t *mykey, isc_netaddr_t *srcaddr, + * isc_netaddr_t *destaddr, dns_rdataclass_t rdclass, void *arg); + * + * 'isself' returns ISC_TRUE if a non-recursive query from 'srcaddr' to + * 'destaddr' with optional key 'mykey' for class 'rdclass' would be + * delivered to 'myview'. + */ + ISC_LANG_ENDDECLS #endif /* DNS_ZONE_H */ diff --git a/lib/dns/win32/libdns.def b/lib/dns/win32/libdns.def index e8f5fa3a07..f4be1fd88f 100644 --- a/lib/dns/win32/libdns.def +++ b/lib/dns/win32/libdns.def @@ -659,6 +659,7 @@ dns_zone_setflag dns_zone_setforwardacl dns_zone_setidlein dns_zone_setidleout +dns_zone_setisself dns_zone_setjournal dns_zone_setjournalsize dns_zone_setkeydirectory diff --git a/lib/dns/zone.c b/lib/dns/zone.c index 7d3a664eba..9dcea3dae1 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: zone.c,v 1.430 2005/02/03 05:07:35 marka Exp $ */ +/* $Id: zone.c,v 1.431 2005/02/10 05:53:42 marka Exp $ */ #include @@ -223,6 +223,8 @@ struct dns_zone { */ isc_uint64_t *counters; isc_uint32_t notifydelay; + dns_isselffunc_t isself; + void *isselfarg; }; #define DNS_ZONE_FLAG(z,f) (ISC_TF(((z)->flags & (f)) != 0)) @@ -586,6 +588,8 @@ dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) { zone->statelist = NULL; zone->counters = NULL; zone->notifydelay = 5; + zone->isself = NULL; + zone->isselfarg = NULL; zone->magic = ZONE_MAGIC; @@ -2741,6 +2745,46 @@ notify_isqueued(dns_zone_t *zone, dns_name_t *name, isc_sockaddr_t *addr) { return (ISC_FALSE); } +static isc_boolean_t +notify_isself(dns_zone_t *zone, isc_sockaddr_t *dst) { + dns_tsigkey_t *key = NULL; + isc_sockaddr_t src; + isc_sockaddr_t any; + isc_boolean_t isself; + isc_netaddr_t dstaddr; + + if (zone->view == NULL || zone->isself == NULL) + return (ISC_FALSE); + + switch (isc_sockaddr_pf(dst)) { + case PF_INET: + src = zone->notifysrc4; + isc_sockaddr_any(&any); + break; + case PF_INET6: + src = zone->notifysrc6; + isc_sockaddr_any6(&any); + break; + default: + return (ISC_FALSE); + } + + /* + * When sending from any the kernel will assign a source address + * that matches the destination address. + */ + if (isc_sockaddr_eqaddr(&any, &src)) + src = *dst; + + isc_netaddr_fromsockaddr(&dstaddr, dst); + (void)dns_view_getpeertsig(zone->view, &dstaddr, &key); + isself = (zone->isself)(zone->view, key, &src, dst, zone->rdclass, + zone->isselfarg); + if (key != NULL) + dns_tsigkey_detach(&key); + return (isself); +} + static void notify_destroy(dns_notify_t *notify, isc_boolean_t locked) { isc_mem_t *mctx; @@ -2988,6 +3032,8 @@ notify_send(dns_notify_t *notify) { dst = ai->sockaddr; if (notify_isqueued(notify->zone, NULL, &dst)) continue; + if (notify_isself(notify->zone, &dst)) + continue; new = NULL; result = notify_create(notify->mctx, (notify->flags & DNS_NOTIFY_NOSOA), @@ -7013,6 +7059,16 @@ dns_zone_checknames(dns_zone_t *zone, dns_name_t *name, dns_rdata_t *rdata) { return (ISC_R_SUCCESS); } +void +dns_zone_setisself(dns_zone_t *zone, dns_isselffunc_t isself, void *arg) { + REQUIRE(DNS_ZONE_VALID(zone)); + + LOCK_ZONE(zone); + zone->isself = isself; + zone->isselfarg = arg; + UNLOCK_ZONE(zone); +} + void dns_zone_setnotifydelay(dns_zone_t *zone, isc_uint32_t delay) { REQUIRE(DNS_ZONE_VALID(zone));