]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
[master] add DSCP support
authorEvan Hunt <each@isc.org>
Fri, 22 Mar 2013 19:27:54 +0000 (12:27 -0700)
committerEvan Hunt <each@isc.org>
Fri, 22 Mar 2013 21:05:33 +0000 (14:05 -0700)
3535. [func] Add support for setting Differentiated Services Code
Point (DSCP) values in named.  Most configuration
options which take a "port" option (e.g.,
listen-on, forwarders, also-notify, masters,
notify-source, etc) can now also take a "dscp"
option specifying a code point for use with
outgoing traffic, if supported by the underlying
OS. [RT #27596]

91 files changed:
CHANGES
bin/named/client.c
bin/named/config.c
bin/named/include/named/client.h
bin/named/include/named/config.h
bin/named/include/named/globals.h
bin/named/include/named/interfacemgr.h
bin/named/include/named/listenlist.h
bin/named/interfacemgr.c
bin/named/listenlist.c
bin/named/lwresd.c
bin/named/main.c
bin/named/server.c
bin/named/zoneconf.c
bin/tests/adb_test.c
bin/tests/resolver/t_resolver.c
bin/tests/system/checkconf/good.conf
bin/tests/system/checkconf/range.conf [new file with mode: 0644]
bin/tests/system/checkconf/tests.sh
bin/tests/system/conf.sh.in
bin/tests/system/dnssec/ns4/named1.conf
bin/tests/system/dnssec/ns4/named2.conf
bin/tests/system/dscp/clean.sh [new file with mode: 0644]
bin/tests/system/dscp/ns1/named.args [new file with mode: 0644]
bin/tests/system/dscp/ns1/named.conf [new file with mode: 0644]
bin/tests/system/dscp/ns1/root.db [new file with mode: 0644]
bin/tests/system/dscp/ns2/named.args [new file with mode: 0644]
bin/tests/system/dscp/ns2/named.conf [new file with mode: 0644]
bin/tests/system/dscp/ns3/hint.db [new file with mode: 0644]
bin/tests/system/dscp/ns3/named.args [new file with mode: 0644]
bin/tests/system/dscp/ns3/named.conf [new file with mode: 0644]
bin/tests/system/dscp/ns4/named.args [new file with mode: 0644]
bin/tests/system/dscp/ns4/named.conf [new file with mode: 0644]
bin/tests/system/dscp/ns4/root.db [new file with mode: 0644]
bin/tests/system/dscp/ns5/named.args [new file with mode: 0644]
bin/tests/system/dscp/ns5/named.conf [new file with mode: 0644]
bin/tests/system/dscp/ns6/hint.db [new file with mode: 0644]
bin/tests/system/dscp/ns6/named.args [new file with mode: 0644]
bin/tests/system/dscp/ns6/named.conf [new file with mode: 0644]
bin/tests/system/dscp/ns7/named.args [new file with mode: 0644]
bin/tests/system/dscp/ns7/named.conf [new file with mode: 0644]
bin/tests/system/dscp/tests.sh [new file with mode: 0644]
bin/tests/system/nsupdate/ns1/named.conf
bin/tests/system/nsupdate/ns2/named.conf
bin/tests/system/nsupdate/ns3/named.conf
bin/tests/system/resolver/ns1/named.conf
bin/tests/system/resolver/ns4/named.conf
bin/tests/system/resolver/ns5/named.conf
bin/tests/system/resolver/ns6/named.conf
bin/tests/system/resolver/ns7/named.conf
doc/arm/Bv9ARM-book.xml
doc/design/dscp [new file with mode: 0644]
doc/misc/options
lib/bind9/check.c
lib/dns/adb.c
lib/dns/dispatch.c
lib/dns/forward.c
lib/dns/include/dns/adb.h
lib/dns/include/dns/dispatch.h
lib/dns/include/dns/forward.h
lib/dns/include/dns/peer.h
lib/dns/include/dns/request.h
lib/dns/include/dns/resolver.h
lib/dns/include/dns/types.h
lib/dns/include/dns/xfrin.h
lib/dns/include/dns/zone.h
lib/dns/peer.c
lib/dns/request.c
lib/dns/resolver.c
lib/dns/win32/libdns.def
lib/dns/xfrin.c
lib/dns/zone.c
lib/isc/include/isc/namespace.h
lib/isc/include/isc/socket.h
lib/isc/include/isc/types.h
lib/isc/socket_api.c
lib/isc/tests/Makefile.in
lib/isc/tests/isctest.c
lib/isc/tests/socket_test.c
lib/isc/unix/include/isc/net.h
lib/isc/unix/net.c
lib/isc/unix/socket.c
lib/isc/win32/include/isc/net.h
lib/isc/win32/libisc.def
lib/isc/win32/net.c
lib/isc/win32/socket.c
lib/isccfg/include/isccfg/cfg.h
lib/isccfg/include/isccfg/grammar.h
lib/isccfg/namedconf.c
lib/isccfg/parser.c
lib/isccfg/win32/libisccfg.def

diff --git a/CHANGES b/CHANGES
index a94d624b645d03d02c643b53eb8d1881539cf2ca..83f6e74af23debb503aaf9db6dac1195444ec479 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,12 @@
+3536.  [func]          Add support for setting Differentiated Services Code
+                       Point (DSCP) values in named.  Most configuration
+                       options which take a "port" option (e.g.,
+                       listen-on, forwarders, also-notify, masters,
+                       notify-source, etc) can now also take a "dscp"
+                       option specifying a code point for use with
+                       outgoing traffic, if supported by the underlying
+                       OS. [RT #27596]
+
 3535.  [bug]           Minor win32 cleanups. [RT #32962]
 
 3534.  [bug]           Extra text after an embedded NULL was ignored when
index 710c876b862bb6f348a912beaf1f3e8dda3e5359..67403d07a48df23d6a05b757e957679c38e3e38a 100644 (file)
@@ -827,6 +827,7 @@ client_sendpkg(ns_client_t *client, isc_buffer_t *buffer) {
        isc_netaddr_t netaddr;
        int match;
        unsigned int sockflags = ISC_SOCKFLAG_IMMEDIATE;
+       isc_dscp_t dispdscp = -1;
 
        if (TCP_CLIENT(client)) {
                socket = client->tcpsocket;
@@ -852,6 +853,20 @@ client_sendpkg(ns_client_t *client, isc_buffer_t *buffer) {
        else
                pktinfo = NULL;
 
+       if (client->dispatch != NULL) {
+               dispdscp = dns_dispatch_getdscp(client->dispatch);
+               if (dispdscp != -1)
+                       client->dscp = dispdscp;
+       }
+
+       if (client->dscp == -1) {
+               client->sendevent->attributes &= ~ISC_SOCKEVENTATTR_DSCP;
+               client->sendevent->dscp = 0;
+       } else {
+               client->sendevent->attributes |= ISC_SOCKEVENTATTR_DSCP;
+               client->sendevent->dscp = client->dscp;
+       }
+
        isc_buffer_usedregion(buffer, &r);
 
        CTRACE("sendto");
@@ -1533,6 +1548,13 @@ client_request(isc_task_t *task, isc_event_t *event) {
                        client->peeraddr = sevent->address;
                        client->peeraddr_valid = ISC_TRUE;
                }
+               if ((sevent->attributes & ISC_SOCKEVENTATTR_DSCP) != 0) {
+                       ns_client_log(client, NS_LOGCATEGORY_CLIENT,
+                             NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(90),
+                             "received DSCP %d", sevent->dscp);
+                       if (client->dscp == -1)
+                               client->dscp = sevent->dscp;
+               }
                if ((sevent->attributes & ISC_SOCKEVENTATTR_PKTINFO) != 0) {
                        client->attributes |= NS_CLIENTATTR_PKTINFO;
                        client->pktinfo = sevent->pktinfo;
@@ -2196,11 +2218,9 @@ client_create(ns_clientmgr_t *manager, ns_client_t **clientp) {
 
        /* XXXRTH  Hardwired constants */
 
-       client->sendevent = (isc_socketevent_t *)
-                           isc_event_allocate(client->mctx, client,
-                                              ISC_SOCKEVENT_SENDDONE,
-                                              client_senddone, client,
-                                              sizeof(isc_socketevent_t));
+       client->sendevent = isc_socket_socketevent(client->mctx, client,
+                                                  ISC_SOCKEVENT_SENDDONE,
+                                                  client_senddone, client);
        if (client->sendevent == NULL) {
                result = ISC_R_NOMEMORY;
                goto cleanup_message;
@@ -2212,11 +2232,9 @@ client_create(ns_clientmgr_t *manager, ns_client_t **clientp) {
                goto cleanup_sendevent;
        }
 
-       client->recvevent = (isc_socketevent_t *)
-                           isc_event_allocate(client->mctx, client,
-                                              ISC_SOCKEVENT_RECVDONE,
-                                              client_request, client,
-                                              sizeof(isc_socketevent_t));
+       client->recvevent = isc_socket_socketevent(client->mctx, client,
+                                                  ISC_SOCKEVENT_RECVDONE,
+                                                  client_request, client);
        if (client->recvevent == NULL) {
                result = ISC_R_NOMEMORY;
                goto cleanup_recvbuf;
@@ -2243,6 +2261,7 @@ client_create(ns_clientmgr_t *manager, ns_client_t **clientp) {
        client->tcpbuf = NULL;
        client->opt = NULL;
        client->udpsize = 512;
+       client->dscp = -1;
        client->extflags = 0;
        client->ednsversion = -1;
        client->next = NULL;
@@ -2737,6 +2756,8 @@ get_client(ns_clientmgr_t *manager, ns_interface_t *ifp,
        client->state = NS_CLIENTSTATE_READY;
        INSIST(client->recursionquota == NULL);
 
+       client->dscp = ifp->dscp;
+
        if (tcp) {
                client->attributes |= NS_CLIENTATTR_TCP;
                isc_socket_attach(ifp->tcpsocket,
index bd1df7540891aa45c69c78407d81987233af9cbe..e423c00f4fe436d82a0f8380715652eaa4b3a7c4 100644 (file)
@@ -64,6 +64,7 @@ options {\n\
        session-keyalg hmac-sha256;\n\
        deallocate-on-exit true;\n\
 #      directory <none>\n\
+       dscp 0;\n\
        dump-file \"named_dump.db\";\n\
        fake-iquery no;\n\
        has-old-clients false;\n\
@@ -279,7 +280,9 @@ ns_config_parsedefaults(cfg_parser_t *parser, cfg_obj_t **conf) {
 }
 
 isc_result_t
-ns_config_get(const cfg_obj_t **maps, const char *name, const cfg_obj_t **obj) {
+ns_config_get(cfg_obj_t const * const *maps, const char *name,
+             const cfg_obj_t **obj)
+{
        int i;
 
        for (i = 0;; i++) {
@@ -402,17 +405,20 @@ ns_config_getzonetype(const cfg_obj_t *zonetypeobj) {
 isc_result_t
 ns_config_getiplist(const cfg_obj_t *config, const cfg_obj_t *list,
                    in_port_t defport, isc_mem_t *mctx,
-                   isc_sockaddr_t **addrsp, isc_uint32_t *countp)
+                   isc_sockaddr_t **addrsp, isc_dscp_t **dscpsp,
+                   isc_uint32_t *countp)
 {
        int count, i = 0;
        const cfg_obj_t *addrlist;
-       const cfg_obj_t *portobj;
+       const cfg_obj_t *portobj, *dscpobj;
        const cfg_listelt_t *element;
        isc_sockaddr_t *addrs;
        in_port_t port;
+       isc_dscp_t dscp = -1, *dscps;
        isc_result_t result;
 
        INSIST(addrsp != NULL && *addrsp == NULL);
+       INSIST(dscpsp == NULL || *dscpsp == NULL);
        INSIST(countp != NULL);
 
        addrlist = cfg_tuple_get(list, "addresses");
@@ -435,6 +441,23 @@ ns_config_getiplist(const cfg_obj_t *config, const cfg_obj_t *list,
                        return (result);
        }
 
+       if (dscpsp != NULL) {
+               dscps = isc_mem_get(mctx, count * sizeof(isc_dscp_t));
+               if (dscps == NULL)
+                       return (ISC_R_NOMEMORY);
+
+               dscpobj = cfg_tuple_get(list, "dscp");
+               if (dscpobj != NULL && cfg_obj_isuint32(dscpobj)) {
+                       if (cfg_obj_asuint32(dscpobj) > 63) {
+                               cfg_obj_log(dscpobj, ns_g_lctx, ISC_LOG_ERROR,
+                                           "dscp value '%u' is out of range",
+                                           cfg_obj_asuint32(dscpobj));
+                               return (ISC_R_RANGE);
+                       }
+                       dscp = (isc_dscp_t)cfg_obj_asuint32(dscpobj);
+               }
+       }
+
        addrs = isc_mem_get(mctx, count * sizeof(isc_sockaddr_t));
        if (addrs == NULL)
                return (ISC_R_NOMEMORY);
@@ -443,8 +466,17 @@ ns_config_getiplist(const cfg_obj_t *config, const cfg_obj_t *list,
             element != NULL;
             element = cfg_list_next(element), i++)
        {
+               const cfg_obj_t *addr;
                INSIST(i < count);
-               addrs[i] = *cfg_obj_assockaddr(cfg_listelt_value(element));
+               addr = cfg_listelt_value(element);
+               addrs[i] = *cfg_obj_assockaddr(addr);
+               if (dscpsp != NULL) {
+                       isc_dscp_t innerdscp;
+                       innerdscp = cfg_obj_getdscp(addr);
+                       if (innerdscp == -1)
+                               innerdscp = dscp;
+                       dscps[i] = innerdscp;
+               }
                if (isc_sockaddr_getport(&addrs[i]) == 0)
                        isc_sockaddr_setport(&addrs[i], port);
        }
@@ -453,17 +485,26 @@ ns_config_getiplist(const cfg_obj_t *config, const cfg_obj_t *list,
        *addrsp = addrs;
        *countp = count;
 
+       if (dscpsp != NULL)
+               *dscpsp = dscps;
+
        return (ISC_R_SUCCESS);
 }
 
 void
 ns_config_putiplist(isc_mem_t *mctx, isc_sockaddr_t **addrsp,
-                   isc_uint32_t count)
+                   isc_dscp_t **dscpsp, isc_uint32_t count)
 {
        INSIST(addrsp != NULL && *addrsp != NULL);
+       INSIST(dscpsp == NULL || *dscpsp != NULL);
 
        isc_mem_put(mctx, *addrsp, count * sizeof(isc_sockaddr_t));
        *addrsp = NULL;
+
+       if (dscpsp != NULL) {
+               isc_mem_put(mctx, *dscpsp, count * sizeof(isc_dscp_t));
+               *dscpsp = NULL;
+       }
 }
 
 static isc_result_t
@@ -497,32 +538,40 @@ get_masters_def(const cfg_obj_t *cctx, const char *name,
 isc_result_t
 ns_config_getipandkeylist(const cfg_obj_t *config, const cfg_obj_t *list,
                          isc_mem_t *mctx, isc_sockaddr_t **addrsp,
-                         dns_name_t ***keysp, isc_uint32_t *countp)
+                         isc_dscp_t **dscpsp, dns_name_t ***keysp,
+                         isc_uint32_t *countp)
 {
-       isc_uint32_t addrcount = 0, keycount = 0, i = 0;
+       isc_uint32_t addrcount = 0, dscpcount = 0, keycount = 0, i = 0;
        isc_uint32_t listcount = 0, l = 0, j;
        isc_uint32_t stackcount = 0, pushed = 0;
        isc_result_t result;
        const cfg_listelt_t *element;
        const cfg_obj_t *addrlist;
        const cfg_obj_t *portobj;
+       const cfg_obj_t *dscpobj;
        in_port_t port;
+       isc_dscp_t dscp;
        dns_fixedname_t fname;
        isc_sockaddr_t *addrs = NULL;
+       isc_dscp_t *dscps = NULL;
        dns_name_t **keys = NULL;
        struct { const char *name; } *lists = NULL;
        struct {
                const cfg_listelt_t *element;
                in_port_t port;
+               isc_dscp_t dscp;
        } *stack = NULL;
 
        REQUIRE(addrsp != NULL && *addrsp == NULL);
+       REQUIRE(dscpsp != NULL && *dscpsp == NULL);
        REQUIRE(keysp != NULL && *keysp == NULL);
        REQUIRE(countp != NULL);
 
  newlist:
        addrlist = cfg_tuple_get(list, "addresses");
        portobj = cfg_tuple_get(list, "port");
+       dscpobj = cfg_tuple_get(list, "dscp");
+
        if (cfg_obj_isuint32(portobj)) {
                isc_uint32_t val = cfg_obj_asuint32(portobj);
                if (val > ISC_UINT16_MAX) {
@@ -538,6 +587,20 @@ ns_config_getipandkeylist(const cfg_obj_t *config, const cfg_obj_t *list,
                        goto cleanup;
        }
 
+       if (dscpobj != NULL && cfg_obj_isuint32(dscpobj)) {
+               if (cfg_obj_asuint32(dscpobj) > 63) {
+                       cfg_obj_log(dscpobj, ns_g_lctx, ISC_LOG_ERROR,
+                                   "dscp value '%u' is out of range",
+                                   cfg_obj_asuint32(dscpobj));
+                       return (ISC_R_RANGE);
+               }
+               dscp = (isc_dscp_t)cfg_obj_asuint32(dscpobj);
+       } else {
+               result = ns_config_getdscp(config, &dscp);
+               if (result != ISC_R_SUCCESS)
+                       goto cleanup;
+       }
+
        result = ISC_R_NOMEMORY;
 
        element = cfg_list_first(addrlist);
@@ -618,6 +681,7 @@ ns_config_getipandkeylist(const cfg_obj_t *config, const cfg_obj_t *list,
                         */
                        stack[pushed].element = cfg_list_next(element);
                        stack[pushed].port = port;
+                       stack[pushed].dscp = dscp;
                        pushed++;
                        goto newlist;
                }
@@ -639,6 +703,18 @@ ns_config_getipandkeylist(const cfg_obj_t *config, const cfg_obj_t *list,
                        addrs = new;
                        addrcount = newlen;
 
+                       newsize = newlen * sizeof(isc_dscp_t);
+                       oldsize = dscpcount * sizeof(isc_dscp_t);
+                       new = isc_mem_get(mctx, newsize);
+                       if (new == NULL)
+                               goto cleanup;
+                       if (dscpcount != 0) {
+                               memcpy(new, dscps, oldsize);
+                               isc_mem_put(mctx, dscps, oldsize);
+                       }
+                       dscps = new;
+                       dscpcount = newlen;
+
                        newsize = newlen * sizeof(dns_name_t *);
                        oldsize = keycount * sizeof(dns_name_t *);
                        new = isc_mem_get(mctx, newsize);
@@ -655,6 +731,9 @@ ns_config_getipandkeylist(const cfg_obj_t *config, const cfg_obj_t *list,
                addrs[i] = *cfg_obj_assockaddr(addr);
                if (isc_sockaddr_getport(&addrs[i]) == 0)
                        isc_sockaddr_setport(&addrs[i], port);
+               dscps[i] = cfg_obj_getdscp(addr);
+               if (dscps[i] == -1)
+                       dscps[i] = dscp;
                keys[i] = NULL;
                i++;    /* Increment here so that cleanup on error works. */
                if (!cfg_obj_isstring(key))
@@ -681,6 +760,7 @@ ns_config_getipandkeylist(const cfg_obj_t *config, const cfg_obj_t *list,
                pushed--;
                element = stack[pushed].element;
                port = stack[pushed].port;
+               dscp = stack[pushed].dscp;
                goto resume;
        }
        if (i < addrcount) {
@@ -700,6 +780,19 @@ ns_config_getipandkeylist(const cfg_obj_t *config, const cfg_obj_t *list,
                addrs = new;
                addrcount = i;
 
+               newsize = i * sizeof(isc_dscp_t);
+               oldsize = dscpcount * sizeof(isc_dscp_t);
+               if (i != 0) {
+                       new = isc_mem_get(mctx, newsize);
+                       if (new == NULL)
+                               goto cleanup;
+                       memcpy(new, dscps, newsize);
+               } else
+                       new = NULL;
+               isc_mem_put(mctx, dscps, oldsize);
+               dscps = new;
+               dscpcount = i;
+
                newsize = i * sizeof(dns_name_t *);
                oldsize = keycount * sizeof(dns_name_t *);
                if (i != 0) {
@@ -722,6 +815,7 @@ ns_config_getipandkeylist(const cfg_obj_t *config, const cfg_obj_t *list,
        INSIST(keycount == addrcount);
 
        *addrsp = addrs;
+       *dscpsp = dscps;
        *keysp = keys;
        *countp = addrcount;
 
@@ -730,6 +824,8 @@ ns_config_getipandkeylist(const cfg_obj_t *config, const cfg_obj_t *list,
  cleanup:
        if (addrs != NULL)
                isc_mem_put(mctx, addrs, addrcount * sizeof(isc_sockaddr_t));
+       if (dscps != NULL)
+               isc_mem_put(mctx, dscps, dscpcount * sizeof(isc_dscp_t));
        if (keys != NULL) {
                for (j = 0; j < i; j++) {
                        if (keys[j] == NULL)
@@ -749,14 +845,21 @@ ns_config_getipandkeylist(const cfg_obj_t *config, const cfg_obj_t *list,
 
 void
 ns_config_putipandkeylist(isc_mem_t *mctx, isc_sockaddr_t **addrsp,
-                         dns_name_t ***keysp, isc_uint32_t count)
+                         isc_dscp_t **dscpsp, dns_name_t ***keysp,
+                         isc_uint32_t count)
 {
        unsigned int i;
-       dns_name_t **keys = *keysp;
+       dns_name_t **keys;
 
-       INSIST(addrsp != NULL && *addrsp != NULL);
+       REQUIRE(addrsp != NULL && *addrsp != NULL);
+       REQUIRE(dscpsp == NULL || *dscpsp != NULL);
+       REQUIRE(keysp != NULL && *keysp != NULL);
+
+       keys = *keysp;
 
        isc_mem_put(mctx, *addrsp, count * sizeof(isc_sockaddr_t));
+       if (dscpsp != NULL)
+               isc_mem_put(mctx, *dscpsp, count * sizeof(isc_dscp_t));
        for (i = 0; i < count; i++) {
                if (keys[i] == NULL)
                        continue;
@@ -766,6 +869,8 @@ ns_config_putipandkeylist(isc_mem_t *mctx, isc_sockaddr_t **addrsp,
        }
        isc_mem_put(mctx, *keysp, count * sizeof(dns_name_t *));
        *addrsp = NULL;
+       if (dscpsp != NULL)
+               *dscpsp = NULL;
        *keysp = NULL;
 }
 
@@ -796,6 +901,35 @@ ns_config_getport(const cfg_obj_t *config, in_port_t *portp) {
        return (ISC_R_SUCCESS);
 }
 
+isc_result_t
+ns_config_getdscp(const cfg_obj_t *config, isc_dscp_t *dscpp) {
+       const cfg_obj_t *maps[2];
+       const cfg_obj_t *options = NULL;
+       const cfg_obj_t *dscpobj = NULL;
+       isc_result_t result;
+       int i;
+
+       (void)cfg_map_get(config, "options", &options);
+       i = 0;
+       if (options != NULL)
+               maps[i++] = options;
+       maps[i] = NULL;
+
+       result = ns_config_get(maps, "dscp", &dscpobj);
+       if (dscpobj == NULL) {
+               *dscpp = -1;
+               return (ISC_R_SUCCESS);
+       }
+       if (cfg_obj_asuint32(dscpobj) >= 64) {
+               cfg_obj_log(dscpobj, ns_g_lctx, ISC_LOG_ERROR,
+                           "dscp '%u' out of range",
+                           cfg_obj_asuint32(dscpobj));
+               return (ISC_R_RANGE);
+       }
+       *dscpp = (isc_dscp_t)cfg_obj_asuint32(dscpobj);
+       return (ISC_R_SUCCESS);
+}
+
 struct keyalgorithms {
        const char *str;
        enum { hmacnone, hmacmd5, hmacsha1, hmacsha224,
index 483464d2f0d86c0be963b89bf565c5b97c4d2d9d..38cf14fd6df61ba3efd5440ef8f7b4f147529cd5 100644 (file)
@@ -141,6 +141,7 @@ struct ns_client {
        isc_boolean_t           peeraddr_valid;
        isc_netaddr_t           destaddr;
        struct in6_pktinfo      pktinfo;
+       isc_dscp_t              dscp;
        isc_event_t             ctlevent;
 #ifdef ALLOW_FILTER_AAAA
        dns_aaaa_t              filter_aaaa;
index c16c800fe12661fed80a0e3a600be04514de50c2..dd388c6aa6190730e6fb15b49d88119a6c0a8b84 100644 (file)
@@ -31,7 +31,8 @@ isc_result_t
 ns_config_parsedefaults(cfg_parser_t *parser, cfg_obj_t **conf);
 
 isc_result_t
-ns_config_get(const cfg_obj_t **maps, const char* name, const cfg_obj_t **obj);
+ns_config_get(cfg_obj_t const * const *maps, const char* name,
+             const cfg_obj_t **obj);
 
 isc_result_t
 ns_checknames_get(const cfg_obj_t **maps, const char* name,
@@ -54,20 +55,23 @@ ns_config_getzonetype(const cfg_obj_t *zonetypeobj);
 isc_result_t
 ns_config_getiplist(const cfg_obj_t *config, const cfg_obj_t *list,
                    in_port_t defport, isc_mem_t *mctx,
-                   isc_sockaddr_t **addrsp, isc_uint32_t *countp);
+                   isc_sockaddr_t **addrsp, isc_dscp_t **dscpsp,
+                   isc_uint32_t *countp);
 
 void
 ns_config_putiplist(isc_mem_t *mctx, isc_sockaddr_t **addrsp,
-                   isc_uint32_t count);
+                   isc_dscp_t **dscpsp, isc_uint32_t count);
 
 isc_result_t
 ns_config_getipandkeylist(const cfg_obj_t *config, const cfg_obj_t *list,
                          isc_mem_t *mctx, isc_sockaddr_t **addrsp,
-                         dns_name_t ***keys, isc_uint32_t *countp);
+                         isc_dscp_t **dscpp, dns_name_t ***keys,
+                         isc_uint32_t *countp);
 
 void
 ns_config_putipandkeylist(isc_mem_t *mctx, isc_sockaddr_t **addrsp,
-                         dns_name_t ***keys, isc_uint32_t count);
+                         isc_dscp_t **dscpsp, dns_name_t ***keys,
+                         isc_uint32_t count);
 
 isc_result_t
 ns_config_getport(const cfg_obj_t *config, in_port_t *portp);
@@ -79,4 +83,7 @@ isc_result_t
 ns_config_getkeyalgorithm2(const char *str, dns_name_t **name,
                           unsigned int *typep, isc_uint16_t *digestbits);
 
+isc_result_t
+ns_config_getdscp(const cfg_obj_t *config, isc_dscp_t *dscpp);
+
 #endif /* NAMED_CONFIG_H */
index dddcdc98e12d9121213cd7a3929f6a57b6c7e8ed..dfa0647b90ea7c9d242bc1618e7dd81b4213d768 100644 (file)
@@ -72,6 +72,7 @@ EXTERN const char *           ns_g_product            INIT(PRODUCT);
 EXTERN const char *            ns_g_srcid              INIT(SRCID);
 EXTERN const char *            ns_g_configargs         INIT(CONFIGARGS);
 EXTERN in_port_t               ns_g_port               INIT(0);
+EXTERN isc_dscp_t              ns_g_dscp               INIT(-1);
 EXTERN in_port_t               lwresd_g_listenport     INIT(0);
 
 EXTERN ns_server_t *           ns_g_server             INIT(NULL);
index 380dbedd76868d8bfb5533f34a5f99a5c76bef0b..014d8730e40964ad1e07a7d4c81a69ed594e56ac 100644 (file)
@@ -80,6 +80,7 @@ struct ns_interface {
        dns_dispatch_t *        udpdispatch[MAX_UDP_DISPATCH];
                                                /*%< UDP dispatchers. */
        isc_socket_t *          tcpsocket;      /*%< TCP socket. */
+       isc_dscp_t              dscp;           /*%< "listen-on" DSCP value */
        int                     ntcptarget;     /*%< Desired number of concurrent
                                                     TCP accepts */
        int                     ntcpcurrent;    /*%< Current ditto, locked */
index 9e65d5df3a9373368f506388ba30ef16d52ea1fc..d6c2dbb9090c9cbad38e8ebd7e0a37d0e6856f07 100644 (file)
@@ -46,6 +46,7 @@ typedef struct ns_listenlist ns_listenlist_t;
 struct ns_listenelt {
        isc_mem_t *                     mctx;
        in_port_t                       port;
+       isc_dscp_t                      dscp;  /* -1 = not set, 0..63 */
        dns_acl_t *                     acl;
        ISC_LINK(ns_listenelt_t)        link;
 };
@@ -61,7 +62,7 @@ struct ns_listenlist {
  ***/
 
 isc_result_t
-ns_listenelt_create(isc_mem_t *mctx, in_port_t port,
+ns_listenelt_create(isc_mem_t *mctx, in_port_t port, isc_dscp_t dscp,
                    dns_acl_t *acl, ns_listenelt_t **target);
 /*%
  * Create a listen-on list element.
@@ -92,7 +93,7 @@ ns_listenlist_detach(ns_listenlist_t **listp);
  */
 
 isc_result_t
-ns_listenlist_default(isc_mem_t *mctx, in_port_t port,
+ns_listenlist_default(isc_mem_t *mctx, in_port_t port, isc_dscp_t dscp,
                      isc_boolean_t enabled, ns_listenlist_t **target);
 /*%
  * Create a listen-on list with default contents, matching
index 268e47d893911e410acfe7d5525d273f6aaad236..418107214ce038bc9b34bd023e802e42e1e3cc26 100644 (file)
@@ -234,6 +234,8 @@ ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr,
        ifp->ntcpcurrent = 0;
        ifp->nudpdispatch = 0;
 
+       ifp->dscp = -1;
+
        ISC_LINK_INIT(ifp, link);
 
        ns_interfacemgr_attach(mgr, &ifp->mgr);
@@ -345,6 +347,10 @@ ns_interface_accepttcp(ns_interface_t *ifp) {
                                 isc_result_totext(result));
                goto tcp_bind_failure;
        }
+
+       if (ifp->dscp != -1)
+               isc_socket_dscp(ifp->tcpsocket, ifp->dscp);
+
        result = isc_socket_listen(ifp->tcpsocket, ns_g_listen);
        if (result != ISC_R_SUCCESS) {
                isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
@@ -381,7 +387,7 @@ ns_interface_accepttcp(ns_interface_t *ifp) {
 static isc_result_t
 ns_interface_setup(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr,
                   const char *name, ns_interface_t **ifpret,
-                  isc_boolean_t accept_tcp)
+                  isc_boolean_t accept_tcp, isc_dscp_t dscp)
 {
        isc_result_t result;
        ns_interface_t *ifp = NULL;
@@ -391,6 +397,8 @@ ns_interface_setup(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr,
        if (result != ISC_R_SUCCESS)
                return (result);
 
+       ifp->dscp = dscp;
+
        result = ns_interface_listenudp(ifp);
        if (result != ISC_R_SUCCESS)
                goto cleanup_interface;
@@ -627,6 +635,7 @@ do_scan(ns_interfacemgr_t *mgr, ns_listenlist_t *ext_listen,
        ns_interface_t *ifp;
        isc_boolean_t log_explicit = ISC_FALSE;
        isc_boolean_t dolistenon;
+       char sabuf[ISC_SOCKADDR_FORMATSIZE];
 
        if (ext_listen != NULL)
                adjusting = ISC_TRUE;
@@ -682,6 +691,18 @@ do_scan(ns_interfacemgr_t *mgr, ns_listenlist_t *ext_listen,
                        ifp = find_matching_interface(mgr, &listen_addr);
                        if (ifp != NULL) {
                                ifp->generation = mgr->generation;
+                               if (le->dscp != -1 && ifp->dscp == -1)
+                                       ifp->dscp = le->dscp;
+                               else if (le->dscp != ifp->dscp) {
+                                       isc_sockaddr_format(&listen_addr,
+                                                           sabuf,
+                                                           sizeof(sabuf));
+                                       isc_log_write(IFMGR_COMMON_LOGARGS,
+                                                     ISC_LOG_WARNING,
+                                                     "%s: conflicting DSCP "
+                                                     "values, using %d",
+                                                     sabuf, ifp->dscp);
+                               }
                        } else {
                                isc_log_write(IFMGR_COMMON_LOGARGS,
                                              ISC_LOG_INFO,
@@ -690,7 +711,8 @@ do_scan(ns_interfacemgr_t *mgr, ns_listenlist_t *ext_listen,
                                              le->port);
                                result = ns_interface_setup(mgr, &listen_addr,
                                                            "<any>", &ifp,
-                                                           ISC_TRUE);
+                                                           ISC_TRUE,
+                                                           le->dscp);
                                if (result == ISC_R_SUCCESS)
                                        ifp->flags |= NS_INTERFACEFLAG_ANYADDR;
                                else
@@ -843,9 +865,19 @@ do_scan(ns_interfacemgr_t *mgr, ns_listenlist_t *ext_listen,
                        ifp = find_matching_interface(mgr, &listen_sockaddr);
                        if (ifp != NULL) {
                                ifp->generation = mgr->generation;
+                               if (le->dscp != -1 && ifp->dscp == -1)
+                                       ifp->dscp = le->dscp;
+                               else if (le->dscp != ifp->dscp) {
+                                       isc_sockaddr_format(&listen_addr,
+                                                           sabuf,
+                                                           sizeof(sabuf));
+                                       isc_log_write(IFMGR_COMMON_LOGARGS,
+                                                     ISC_LOG_WARNING,
+                                                     "%s: conflicting DSCP "
+                                                     "values, using %d",
+                                                     sabuf, ifp->dscp);
+                               }
                        } else {
-                               char sabuf[ISC_SOCKADDR_FORMATSIZE];
-
                                if (adjusting == ISC_FALSE &&
                                    ipv6_wildcard == ISC_TRUE)
                                        continue;
@@ -875,12 +907,12 @@ do_scan(ns_interfacemgr_t *mgr, ns_listenlist_t *ext_listen,
                                              interface.name, sabuf);
 
                                result = ns_interface_setup(mgr,
-                                                           &listen_sockaddr,
-                                                           interface.name,
-                                                           &ifp,
-                                                           (adjusting == ISC_TRUE) ?
-                                                           ISC_FALSE :
-                                                           ISC_TRUE);
+                                                   &listen_sockaddr,
+                                                   interface.name,
+                                                   &ifp,
+                                                   (adjusting == ISC_TRUE) ?
+                                                   ISC_FALSE : ISC_TRUE,
+                                                   le->dscp);
 
                                if (result != ISC_R_SUCCESS) {
                                        isc_log_write(IFMGR_COMMON_LOGARGS,
index 513fe9c70b138aca85267c22c6072620bf3e9d6b..691f83c8325a944563506b47a18ff31d7b897b3e 100644 (file)
@@ -32,7 +32,7 @@ static void
 destroy(ns_listenlist_t *list);
 
 isc_result_t
-ns_listenelt_create(isc_mem_t *mctx, in_port_t port,
+ns_listenelt_create(isc_mem_t *mctx, in_port_t port, isc_dscp_t dscp,
                    dns_acl_t *acl, ns_listenelt_t **target)
 {
        ns_listenelt_t *elt = NULL;
@@ -43,6 +43,7 @@ ns_listenelt_create(isc_mem_t *mctx, in_port_t port,
        elt->mctx = mctx;
        ISC_LINK_INIT(elt, link);
        elt->port = port;
+       elt->dscp = dscp;
        elt->acl = acl;
        *target = elt;
        return (ISC_R_SUCCESS);
@@ -100,7 +101,7 @@ ns_listenlist_detach(ns_listenlist_t **listp) {
 }
 
 isc_result_t
-ns_listenlist_default(isc_mem_t *mctx, in_port_t port,
+ns_listenlist_default(isc_mem_t *mctx, in_port_t port, isc_dscp_t dscp,
                      isc_boolean_t enabled, ns_listenlist_t **target)
 {
        isc_result_t result;
@@ -116,7 +117,7 @@ ns_listenlist_default(isc_mem_t *mctx, in_port_t port,
        if (result != ISC_R_SUCCESS)
                goto cleanup;
 
-       result = ns_listenelt_create(mctx, port, acl, &elt);
+       result = ns_listenelt_create(mctx, port, dscp, acl, &elt);
        if (result != ISC_R_SUCCESS)
                goto cleanup_acl;
 
index 7ee2196364e939d693170bbe1f94f468b1dda3a6..d1d1f76de5c0dcddefc012854b0165e6cb9a6938 100644 (file)
@@ -812,11 +812,12 @@ ns_lwresd_configure(isc_mem_t *mctx, const cfg_obj_t *config) {
                        isc_uint32_t i;
 
                        CHECK(ns_config_getiplist(config, listenerslist,
-                                                 port, mctx, &addrs, &count));
+                                                 port, mctx, &addrs, NULL,
+                                                 &count));
                        for (i = 0; i < count; i++)
                                CHECK(configure_listener(&addrs[i], lwresd,
                                                         mctx, &newlisteners));
-                       ns_config_putiplist(mctx, &addrs, count);
+                       ns_config_putiplist(mctx, &addrs, NULL, count);
                }
                ns_lwdmanager_detach(&lwresd);
        }
@@ -845,7 +846,7 @@ ns_lwresd_configure(isc_mem_t *mctx, const cfg_obj_t *config) {
        ISC_LIST_APPENDLIST(listeners, newlisteners, link);
 
        if (addrs != NULL)
-               ns_config_putiplist(mctx, &addrs, count);
+               ns_config_putiplist(mctx, &addrs, NULL, count);
 
        if (lwresd != NULL)
                ns_lwdmanager_detach(&lwresd);
index 785c65e758f8e565cfa9d0cda25da01c5a677782..fdabbbe0c4372546ce141fec3cd938504f2577d0 100644 (file)
@@ -97,6 +97,8 @@
 #define BACKTRACE_MAXFRAME 128
 #endif
 
+extern int isc_dscp_check_value;
+
 static isc_boolean_t   want_stats = ISC_FALSE;
 static char            program_name[ISC_DIR_NAMEMAX] = "named";
 static char            absolute_conffile[ISC_DIR_PATHMAX];
@@ -510,10 +512,15 @@ parse_command_line(int argc, char *argv[]) {
                        break;
                case 'T':       /* NOT DOCUMENTED */
                        /*
+                        * force the server to behave (or misbehave) in
+                        * specified ways for testing purposes.
+                        *
                         * clienttest: make clients single shot with their
                         *             own memory context.
                         * delay=xxxx: delay client responses by xxxx ms to
                         *             simulate remote servers.
+                        * dscp=x:     check that dscp values are as
+                        *             expected and assert otherwise.
                         */
                        if (!strcmp(isc_commandline_argument, "clienttest"))
                                ns_g_clienttest = ISC_TRUE;
@@ -539,6 +546,9 @@ parse_command_line(int argc, char *argv[]) {
                                ns_g_nosyslog = ISC_TRUE;
                        else if (!strcmp(isc_commandline_argument, "nonearest"))
                                ns_g_nonearest = ISC_TRUE;
+                       else if (!strncmp(isc_commandline_argument, "dscp=", 5))
+                               isc_dscp_check_value =
+                                          atoi(isc_commandline_argument + 5);
                        else
                                fprintf(stderr, "unknown -T flag '%s\n",
                                        isc_commandline_argument);
index 84ac1b8900ee181ddb2d8b2048cfb096cc14e68b..a5c20350d1b8dc3f6cb8525d52b85c21e1be2a1f 100644 (file)
@@ -936,8 +936,8 @@ mustbesecure(const cfg_obj_t *mbs, dns_resolver_t *resolver) {
  * Get a dispatch appropriate for the resolver of a given view.
  */
 static isc_result_t
-get_view_querysource_dispatch(const cfg_obj_t **maps,
-                             int af, dns_dispatch_t **dispatchp,
+get_view_querysource_dispatch(const cfg_obj_t **maps, int af,
+                             dns_dispatch_t **dispatchp, isc_dscp_t *dscpp,
                              isc_boolean_t is_firstview)
 {
        isc_result_t result = ISC_R_FAILURE;
@@ -946,6 +946,7 @@ get_view_querysource_dispatch(const cfg_obj_t **maps,
        unsigned int attrs, attrmask;
        const cfg_obj_t *obj = NULL;
        unsigned int maxdispatchbuffers;
+       isc_dscp_t dscp = -1;
 
        switch (af) {
        case AF_INET:
@@ -963,6 +964,10 @@ get_view_querysource_dispatch(const cfg_obj_t **maps,
        sa = *(cfg_obj_assockaddr(obj));
        INSIST(isc_sockaddr_pf(&sa) == af);
 
+       dscp = cfg_obj_getdscp(obj);
+       if (dscp != -1 && dscpp != NULL)
+               *dscpp = dscp;
+
        /*
         * If we don't support this address family, we're done!
         */
@@ -1206,6 +1211,9 @@ configure_peer(const cfg_obj_t *cpeer, isc_mem_t *mctx, dns_peer_t **peerp) {
        if (obj != NULL) {
                result = dns_peer_settransfersource(peer,
                                                    cfg_obj_assockaddr(obj));
+               if (result != ISC_R_SUCCESS)
+                       goto cleanup;
+               result = dns_peer_settransferdscp(peer, cfg_obj_getdscp(obj));
                if (result != ISC_R_SUCCESS)
                        goto cleanup;
                ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj));
@@ -1219,6 +1227,9 @@ configure_peer(const cfg_obj_t *cpeer, isc_mem_t *mctx, dns_peer_t **peerp) {
        if (obj != NULL) {
                result = dns_peer_setnotifysource(peer,
                                                  cfg_obj_assockaddr(obj));
+               if (result != ISC_R_SUCCESS)
+                       goto cleanup;
+               result = dns_peer_setnotifydscp(peer, cfg_obj_getdscp(obj));
                if (result != ISC_R_SUCCESS)
                        goto cleanup;
                ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj));
@@ -1232,6 +1243,9 @@ configure_peer(const cfg_obj_t *cpeer, isc_mem_t *mctx, dns_peer_t **peerp) {
        if (obj != NULL) {
                result = dns_peer_setquerysource(peer,
                                                 cfg_obj_assockaddr(obj));
+               if (result != ISC_R_SUCCESS)
+                       goto cleanup;
+               result = dns_peer_setquerydscp(peer, cfg_obj_getdscp(obj));
                if (result != ISC_R_SUCCESS)
                        goto cleanup;
                ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj));
@@ -2082,6 +2096,7 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig,
        unsigned int query_timeout, ndisp;
        struct cfg_context *nzctx;
        isc_boolean_t old_rpz_ok = ISC_FALSE;
+       isc_dscp_t dscp4 = -1, dscp6 = -1;
 
        REQUIRE(DNS_VIEW_VALID(view));
 
@@ -2652,10 +2667,10 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig,
         *
         * XXXRTH  Hardwired number of tasks.
         */
-       CHECK(get_view_querysource_dispatch(maps, AF_INET, &dispatch4,
+       CHECK(get_view_querysource_dispatch(maps, AF_INET, &dispatch4, &dscp4,
                                            ISC_TF(ISC_LIST_PREV(view, link)
                                                   == NULL)));
-       CHECK(get_view_querysource_dispatch(maps, AF_INET6, &dispatch6,
+       CHECK(get_view_querysource_dispatch(maps, AF_INET6, &dispatch6, &dscp6,
                                            ISC_TF(ISC_LIST_PREV(view, link)
                                                   == NULL)));
        if (dispatch4 == NULL && dispatch6 == NULL) {
@@ -2681,6 +2696,15 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig,
                                      resopts, ns_g_dispatchmgr,
                                      dispatch4, dispatch6));
 
+       if (dscp4 == -1)
+               dscp4 = ns_g_dscp;
+       if (dscp6 == -1)
+               dscp6 = ns_g_dscp;
+       if (dscp4 != -1)
+               dns_resolver_setquerydscp4(view->resolver, dscp4);
+       if (dscp6 != -1)
+               dns_resolver_setquerydscp6(view->resolver, dscp6);
+
        /*
         * Set the ADB cache size to 1/8th of the max-cache-size or
         * MAX_ADB_SIZE_FOR_CACHESHARE when the cache is shared.
@@ -3589,16 +3613,17 @@ static isc_result_t
 configure_forward(const cfg_obj_t *config, dns_view_t *view, dns_name_t *origin,
                  const cfg_obj_t *forwarders, const cfg_obj_t *forwardtype)
 {
-       const cfg_obj_t *portobj;
+       const cfg_obj_t *portobj, *dscpobj;
        const cfg_obj_t *faddresses;
        const cfg_listelt_t *element;
        dns_fwdpolicy_t fwdpolicy = dns_fwdpolicy_none;
-       isc_sockaddrlist_t addresses;
-       isc_sockaddr_t *sa;
+       dns_forwarderlist_t fwdlist;
+       dns_forwarder_t *fwd;
        isc_result_t result;
        in_port_t port;
+       isc_dscp_t dscp = -1;
 
-       ISC_LIST_INIT(addresses);
+       ISC_LIST_INIT(fwdlist);
 
        /*
         * Determine which port to send forwarded requests to.
@@ -3621,6 +3646,22 @@ configure_forward(const cfg_obj_t *config, dns_view_t *view, dns_name_t *origin,
                }
        }
 
+       /*
+        * DSCP value for forwarded requests.
+        */
+       dscpobj = cfg_tuple_get(forwarders, "dscp");
+       if (!cfg_obj_isuint32(dscpobj))
+               dscp = ns_g_dscp;
+       else {
+               if (cfg_obj_asuint32(dscpobj) > 63) {
+                       cfg_obj_log(dscpobj, ns_g_lctx, ISC_LOG_ERROR,
+                                   "dscp value '%u' is out of range",
+                                   cfg_obj_asuint32(dscpobj));
+                       return (ISC_R_RANGE);
+               }
+               dscp = (isc_dscp_t)cfg_obj_asuint32(dscpobj);
+       }
+
        faddresses = NULL;
        if (forwarders != NULL)
                faddresses = cfg_tuple_get(forwarders, "addresses");
@@ -3630,19 +3671,22 @@ configure_forward(const cfg_obj_t *config, dns_view_t *view, dns_name_t *origin,
             element = cfg_list_next(element))
        {
                const cfg_obj_t *forwarder = cfg_listelt_value(element);
-               sa = isc_mem_get(view->mctx, sizeof(isc_sockaddr_t));
-               if (sa == NULL) {
+               fwd = isc_mem_get(view->mctx, sizeof(dns_forwarder_t));
+               if (fwd == NULL) {
                        result = ISC_R_NOMEMORY;
                        goto cleanup;
                }
-               *sa = *cfg_obj_assockaddr(forwarder);
-               if (isc_sockaddr_getport(sa) == 0)
-                       isc_sockaddr_setport(sa, port);
-               ISC_LINK_INIT(sa, link);
-               ISC_LIST_APPEND(addresses, sa, link);
+               fwd->addr = *cfg_obj_assockaddr(forwarder);
+               if (isc_sockaddr_getport(&fwd->addr) == 0)
+                       isc_sockaddr_setport(&fwd->addr, port);
+               fwd->dscp = cfg_obj_getdscp(forwarder);
+               if (fwd->dscp == -1)
+                       fwd->dscp = dscp;
+               ISC_LINK_INIT(fwd, link);
+               ISC_LIST_APPEND(fwdlist, fwd, link);
        }
 
-       if (ISC_LIST_EMPTY(addresses)) {
+       if (ISC_LIST_EMPTY(fwdlist)) {
                if (forwardtype != NULL)
                        cfg_obj_log(forwarders, ns_g_lctx, ISC_LOG_WARNING,
                                    "no forwarders seen; disabling "
@@ -3662,8 +3706,8 @@ configure_forward(const cfg_obj_t *config, dns_view_t *view, dns_name_t *origin,
                }
        }
 
-       result = dns_fwdtable_add(view->fwdtable, origin, &addresses,
-                                 fwdpolicy);
+       result = dns_fwdtable_addfwd(view->fwdtable, origin, &fwdlist,
+                                    fwdpolicy);
        if (result != ISC_R_SUCCESS) {
                char namebuf[DNS_NAME_FORMATSIZE];
                dns_name_format(origin, namebuf, sizeof(namebuf));
@@ -3677,10 +3721,10 @@ configure_forward(const cfg_obj_t *config, dns_view_t *view, dns_name_t *origin,
 
  cleanup:
 
-       while (!ISC_LIST_EMPTY(addresses)) {
-               sa = ISC_LIST_HEAD(addresses);
-               ISC_LIST_UNLINK(addresses, sa, link);
-               isc_mem_put(view->mctx, sa, sizeof(isc_sockaddr_t));
+       while (!ISC_LIST_EMPTY(fwdlist)) {
+               fwd = ISC_LIST_HEAD(fwdlist);
+               ISC_LIST_UNLINK(fwdlist, fwd, link);
+               isc_mem_put(view->mctx, fwd, sizeof(dns_forwarder_t));
        }
 
        return (result);
@@ -4275,7 +4319,7 @@ scan_interfaces(ns_server_t *server, isc_boolean_t verbose) {
 
 static isc_result_t
 add_listenelt(isc_mem_t *mctx, ns_listenlist_t *list, isc_sockaddr_t *addr,
-             isc_boolean_t wcardport_ok)
+             isc_dscp_t dscp, isc_boolean_t wcardport_ok)
 {
        ns_listenelt_t *lelt = NULL;
        dns_acl_t *src_acl = NULL;
@@ -4300,7 +4344,7 @@ add_listenelt(isc_mem_t *mctx, ns_listenlist_t *list, isc_sockaddr_t *addr,
                        goto clean;
 
                result = ns_listenelt_create(mctx, isc_sockaddr_getport(addr),
-                                            src_acl, &lelt);
+                                            dscp, src_acl, &lelt);
                if (result != ISC_R_SUCCESS)
                        goto clean;
                ISC_LIST_APPEND(list->elts, lelt, link);
@@ -4328,6 +4372,7 @@ adjust_interfaces(ns_server_t *server, isc_mem_t *mctx) {
        dns_view_t *view;
        dns_zone_t *zone, *next;
        isc_sockaddr_t addr, *addrp;
+       isc_dscp_t dscp;
 
        result = ns_listenlist_create(mctx, &list);
        if (result != ISC_R_SUCCESS)
@@ -4353,7 +4398,7 @@ adjust_interfaces(ns_server_t *server, isc_mem_t *mctx) {
                 * query ports, and some of them may override an existing
                 * wildcard IPv6 port.
                 */
-               result = add_listenelt(mctx, list, &addr, ISC_TRUE);
+               result = add_listenelt(mctx, list, &addr, dscp, ISC_TRUE);
                if (result != ISC_R_SUCCESS)
                        goto fail;
        }
@@ -4383,12 +4428,14 @@ adjust_interfaces(ns_server_t *server, isc_mem_t *mctx) {
                        continue;
 
                addrp = dns_zone_getnotifysrc6(zone);
-               result = add_listenelt(mctx, list, addrp, ISC_FALSE);
+               dscp = dns_zone_getnotifysrc6dscp(zone);
+               result = add_listenelt(mctx, list, addrp, dscp, ISC_FALSE);
                if (result != ISC_R_SUCCESS)
                        goto fail;
 
                addrp = dns_zone_getxfrsource6(zone);
-               result = add_listenelt(mctx, list, addrp, ISC_FALSE);
+               dscp = dns_zone_getxfrsource6dscp(zone);
+               result = add_listenelt(mctx, list, addrp, dscp, ISC_FALSE);
                if (result != ISC_R_SUCCESS)
                        goto fail;
        }
@@ -5241,6 +5288,11 @@ load_configuration(const char *filename, ns_server_t *server,
        else
                CHECKM(ns_config_getport(config, &listen_port), "port");
 
+       /*
+        * Determing the default DSCP code point.
+        */
+       CHECKM(ns_config_getdscp(config, &ns_g_dscp), "dscp");
+
        /*
         * Find the listen queue depth.
         */
@@ -5277,7 +5329,7 @@ load_configuration(const char *filename, ns_server_t *server,
                         * Not specified, use default.
                         */
                        CHECK(ns_listenlist_default(ns_g_mctx, listen_port,
-                                                   ISC_TRUE, &listenon));
+                                                   -1, ISC_TRUE, &listenon));
                }
                if (listenon != NULL) {
                        ns_interfacemgr_setlistenon4(server->interfacemgr,
@@ -5304,7 +5356,7 @@ load_configuration(const char *filename, ns_server_t *server,
                         * Not specified, use default.
                         */
                        CHECK(ns_listenlist_default(ns_g_mctx, listen_port,
-                                                   ISC_TRUE, &listenon));
+                                                   -1, ISC_TRUE, &listenon));
                }
                if (listenon != NULL) {
                        ns_interfacemgr_setlistenon6(server->interfacemgr,
@@ -6869,8 +6921,9 @@ ns_listenelt_fromconfig(const cfg_obj_t *listener, const cfg_obj_t *config,
                        isc_mem_t *mctx, ns_listenelt_t **target)
 {
        isc_result_t result;
-       const cfg_obj_t *portobj;
+       const cfg_obj_t *portobj, *dscpobj;
        in_port_t port;
+       isc_dscp_t dscp = -1;
        ns_listenelt_t *delt = NULL;
        REQUIRE(target != NULL && *target == NULL);
 
@@ -6893,7 +6946,20 @@ ns_listenelt_fromconfig(const cfg_obj_t *listener, const cfg_obj_t *config,
                port = (in_port_t)cfg_obj_asuint32(portobj);
        }
 
-       result = ns_listenelt_create(mctx, port, NULL, &delt);
+       dscpobj = cfg_tuple_get(listener, "dscp");
+       if (!cfg_obj_isuint32(dscpobj))
+               dscp = ns_g_dscp;
+       else {
+               if (cfg_obj_asuint32(dscpobj) > 63) {
+                       cfg_obj_log(dscpobj, ns_g_lctx, ISC_LOG_ERROR,
+                                   "dscp value '%u' is out of range",
+                                   cfg_obj_asuint32(dscpobj));
+                       return (ISC_R_RANGE);
+               }
+               dscp = (isc_dscp_t)cfg_obj_asuint32(dscpobj);
+       }
+
+       result = ns_listenelt_create(mctx, port, dscp, NULL, &delt);
        if (result != ISC_R_SUCCESS)
                return (result);
 
index 251f1383551bc53312da0c3d37cd7a05b1439186..cffe4c5c71f7e48de53da86ab45076f8018fc6d2 100644 (file)
@@ -807,6 +807,7 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
        const char *dupcheck;
        dns_notifytype_t notifytype = dns_notifytype_yes;
        isc_sockaddr_t *addrs;
+       isc_dscp_t *dscps;
        dns_name_t **keynames;
        isc_uint32_t count;
        unsigned int dbargc;
@@ -831,6 +832,7 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
        dns_zonestat_level_t statlevel;
        int seconds;
        dns_zone_t *mayberaw = (raw != NULL) ? raw : zone;
+       isc_dscp_t dscp;
 
        i = 0;
        if (zconfig != NULL) {
@@ -1103,17 +1105,20 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
                        isc_uint32_t addrcount;
                        addrs = NULL;
                        keynames = NULL;
+                       dscps = NULL;
                        RETERR(ns_config_getipandkeylist(config, obj, mctx,
-                                                        &addrs, &keynames,
+                                                        &addrs, &dscps,
+                                                        &keynames,
                                                         &addrcount));
-                       result = dns_zone_setalsonotifywithkeys(zone, addrs,
-                                                               keynames,
+                       result = dns_zone_setalsonotifydscpkeys(zone, addrs,
+                                                               dscps, keynames,
                                                                addrcount);
                        if (addrcount != 0)
-                               ns_config_putipandkeylist(mctx, &addrs,
+                               ns_config_putipandkeylist(mctx, &addrs, &dscps,
                                                          &keynames, addrcount);
                        else
-                               INSIST(addrs == NULL && keynames == NULL);
+                               INSIST(addrs == NULL && dscps == NULL &&
+                                      keynames == NULL);
                        RETERR(result);
                } else
                        RETERR(dns_zone_setalsonotify(zone, NULL, 0));
@@ -1122,12 +1127,20 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
                result = ns_config_get(maps, "notify-source", &obj);
                INSIST(result == ISC_R_SUCCESS && obj != NULL);
                RETERR(dns_zone_setnotifysrc4(zone, cfg_obj_assockaddr(obj)));
+               dscp = cfg_obj_getdscp(obj);
+               if (dscp == -1)
+                       dscp = ns_g_dscp;
+               RETERR(dns_zone_setnotifysrc4dscp(zone, dscp));
                ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj));
 
                obj = NULL;
                result = ns_config_get(maps, "notify-source-v6", &obj);
                INSIST(result == ISC_R_SUCCESS && obj != NULL);
                RETERR(dns_zone_setnotifysrc6(zone, cfg_obj_assockaddr(obj)));
+               dscp = cfg_obj_getdscp(obj);
+               if (dscp == -1)
+                       dscp = ns_g_dscp;
+               RETERR(dns_zone_setnotifysrc6dscp(zone, dscp));
                ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj));
 
                obj = NULL;
@@ -1550,14 +1563,15 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
                (void)cfg_map_get(zoptions, "masters", &obj);
                if (obj != NULL) {
                        addrs = NULL;
+                       dscps = NULL;
                        keynames = NULL;
                        RETERR(ns_config_getipandkeylist(config, obj, mctx,
-                                                        &addrs, &keynames,
-                                                        &count));
+                                                        &addrs, &dscps,
+                                                        &keynames, &count));
                        result = dns_zone_setmasterswithkeys(mayberaw, addrs,
                                                             keynames, count);
                        if (count != 0)
-                               ns_config_putipandkeylist(mctx, &addrs,
+                               ns_config_putipandkeylist(mctx, &addrs, &dscps,
                                                          &keynames, count);
                        else
                                INSIST(addrs == NULL && keynames == NULL);
@@ -1609,6 +1623,10 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
                INSIST(result == ISC_R_SUCCESS && obj != NULL);
                RETERR(dns_zone_setxfrsource4(mayberaw,
                                              cfg_obj_assockaddr(obj)));
+               dscp = cfg_obj_getdscp(obj);
+               if (dscp == -1)
+                       dscp = ns_g_dscp;
+               RETERR(dns_zone_setxfrsource4dscp(mayberaw, dscp));
                ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj));
 
                obj = NULL;
@@ -1616,6 +1634,10 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
                INSIST(result == ISC_R_SUCCESS && obj != NULL);
                RETERR(dns_zone_setxfrsource6(mayberaw,
                                              cfg_obj_assockaddr(obj)));
+               dscp = cfg_obj_getdscp(obj);
+               if (dscp == -1)
+                       dscp = ns_g_dscp;
+               RETERR(dns_zone_setxfrsource6dscp(mayberaw, dscp));
                ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj));
 
                obj = NULL;
@@ -1623,12 +1645,20 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
                INSIST(result == ISC_R_SUCCESS && obj != NULL);
                RETERR(dns_zone_setaltxfrsource4(mayberaw,
                                                 cfg_obj_assockaddr(obj)));
+               dscp = cfg_obj_getdscp(obj);
+               if (dscp == -1)
+                       dscp = ns_g_dscp;
+               RETERR(dns_zone_setaltxfrsource4dscp(mayberaw, dscp));
 
                obj = NULL;
                result = ns_config_get(maps, "alt-transfer-source-v6", &obj);
                INSIST(result == ISC_R_SUCCESS && obj != NULL);
                RETERR(dns_zone_setaltxfrsource6(mayberaw,
                                                 cfg_obj_assockaddr(obj)));
+               dscp = cfg_obj_getdscp(obj);
+               if (dscp == -1)
+                       dscp = ns_g_dscp;
+               RETERR(dns_zone_setaltxfrsource6dscp(mayberaw, dscp));
 
                obj = NULL;
                (void)ns_config_get(maps, "use-alt-transfer-source", &obj);
index 2caf43bf640bb4f0faa40096bf391d7dcf2cfb25..967f241d4e5082cae07a98a86ef0d354afec17ea 100644 (file)
@@ -204,15 +204,17 @@ create_view(void) {
 
                attrs = DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_UDP;
                RUNTIME_CHECK(dns_dispatch_getudp(dispatchmgr, socketmgr,
-                                                 taskmgr, &any4, 512, 6, 1024,
-                                                 17, 19, attrs, attrs, &disp4)
+                                                 taskmgr, &any4,
+                                                 512, 6, 1024, 17, 19,
+                                                 attrs, attrs, &disp4)
                              == ISC_R_SUCCESS);
                INSIST(disp4 != NULL);
 
                attrs = DNS_DISPATCHATTR_IPV6 | DNS_DISPATCHATTR_UDP;
                RUNTIME_CHECK(dns_dispatch_getudp(dispatchmgr, socketmgr,
-                                                 taskmgr, &any6, 512, 6, 1024,
-                                                 17, 19, attrs, attrs, &disp6)
+                                                 taskmgr, &any6,
+                                                 512, 6, 1024, 17, 19,
+                                                 attrs, attrs, &disp6)
                              == ISC_R_SUCCESS);
                INSIST(disp6 != NULL);
 
index 27a18ac71401117eb87b6d02f972b8bb9cbb7e89..11341e2cc2c19ed3f66daf4d30b2279659abc3fc 100644 (file)
@@ -53,9 +53,9 @@ setup_create_dispatch_v4(void)
        isc_sockaddr_t local_address;
        isc_sockaddr_any(&local_address);
 
-       CHECK(dns_dispatch_getudp(dispatch_manager, socket_manager, task_manager,
-                                 &local_address, 4096, 100, 100, 100, 500,
-                                 0, 0, /* unsigned int attributes, unsigned int mask, */
+       CHECK(dns_dispatch_getudp(dispatch_manager, socket_manager,
+                                 task_manager, &local_address,
+                                 4096, 100, 100, 100, 500, 0, 0,
                                  &dispatch_v4));
 }
 static void
index 5444fdde0a9e81dac72a01c8ea808d68de4c1510..8f0312b49f598c81cb2bb21d0060528950e01740 100644 (file)
@@ -35,6 +35,7 @@ options {
        datasize 104857600;
        deallocate-on-exit yes;
        directory ".";
+       dscp 41;
        dump-file "named_dumpdb";
        fake-iquery yes;
        files 1000;
@@ -47,10 +48,10 @@ options {
        listen-on port 90 {
                "any";
        };
-       listen-on port 100 {
+       listen-on port 100 dscp 33 {
                127.0.0.1/32;
        };
-       listen-on-v6 port 53 {
+       listen-on-v6 port 53 dscp 57 {
                "none";
        };
        match-mapped-addresses yes;
@@ -67,6 +68,7 @@ options {
        serial-query-rate 100;
        server-id none;
        max-cache-size 20000000000000;
+       transfer-source 0.0.0.0 dscp 63;
        zone-statistics none;
 };
 view "first" {
@@ -77,6 +79,7 @@ view "first" {
                type master;
                file "xxx";
                update-policy local;
+               notify-source 10.10.10.10 port 53 dscp 55;
        };
        dnssec-lookaside auto;
        dnssec-validation auto;
diff --git a/bin/tests/system/checkconf/range.conf b/bin/tests/system/checkconf/range.conf
new file mode 100644 (file)
index 0000000..9908df7
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2012  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+options {
+       port 999999;
+        dscp 222;
+       listen-on port 100 dscp 444 {
+               127.0.0.1/32;
+       };
+};
+
+zone "example" {
+        type master;
+        file "example.db";
+};
index 7cbce53ec457acf46002f1d24e502f3891d4de87..1d8712a3806ffca203c8f08279136631cace04c2 100644 (file)
@@ -43,6 +43,12 @@ do
        status=`expr $status + $ret`
 done
 
+echo "I: checking that named-checkconf catches range errors"
+ret=0
+$CHECKCONF range.conf > /dev/null 2>&1 && ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
 echo "I: checking named-checkconf dnssec warnings"
 ret=0
 $CHECKCONF dnssec.1 2>&1 | grep 'validation yes.*enable no' > /dev/null || ret=1
index 9f9f25b1790c8ae3b421dad391d87e6eeb624d5c..17e60a910429dbf3841a6dd38bab207fd481bdce 100644 (file)
@@ -60,7 +60,7 @@ ARPANAME=$TOP/bin/tools/arpaname
 SUBDIRS="acl additional allow_query addzone autosign builtin
         cacheclean checkconf @CHECKDS@ checknames checkzone @COVERAGE@
          database dlv dlvauto dlz dlzexternal dlzredir dname dns64 dnssec
-        dsdigest ecdsa formerr forward glue gost ixfr inline limits
+        dsdigest dscp ecdsa formerr forward glue gost ixfr inline limits
         logfileconfig lwresd masterfile masterformat metadata
         notify nsupdate pending pkcs11 redirect resolver rndc rpz
         rrl rrsetorder rsabigexponent sortlist smartsign staticstub
index 3f7fd05247ee17416887984101bffe64632ef2f0..d69652a1d7538ad4a10876957898954fc332f69b 100644 (file)
@@ -21,9 +21,9 @@
 controls { /* empty */ };
 
 options {
-       query-source address 10.53.0.4;
-       notify-source 10.53.0.4;
-       transfer-source 10.53.0.4;
+       query-source address 10.53.0.4 dscp 1;
+       notify-source 10.53.0.4 dscp 2;
+       transfer-source 10.53.0.4 dscp 3;
        port 5300;
        pid-file "named.pid";
        listen-on { 10.53.0.4; };
index 4abf44b4360f4c0837dbd63f715d402ce5e7a27c..0158e03a8f23f0eaacd99507aa29a4c142e1ea7a 100644 (file)
 controls { /* empty */ };
 
 options {
-       query-source address 10.53.0.4;
-       notify-source 10.53.0.4;
-       transfer-source 10.53.0.4;
+       query-source address 10.53.0.4 dscp 4;
+       notify-source 10.53.0.4 dscp 5;
+       transfer-source 10.53.0.4 dscp 6;
+        dscp 16;
        port 5300;
        pid-file "named.pid";
        listen-on { 10.53.0.4; };
diff --git a/bin/tests/system/dscp/clean.sh b/bin/tests/system/dscp/clean.sh
new file mode 100644 (file)
index 0000000..d55200e
--- /dev/null
@@ -0,0 +1,2 @@
+rm -f */root.bk
+rm -f dig.out.10.53.0.?
diff --git a/bin/tests/system/dscp/ns1/named.args b/bin/tests/system/dscp/ns1/named.args
new file mode 100644 (file)
index 0000000..9b94ece
--- /dev/null
@@ -0,0 +1 @@
+-m record,size,mctx -T clienttest -c named.conf -d 99 -g -U 4 -T dscp=46
diff --git a/bin/tests/system/dscp/ns1/named.conf b/bin/tests/system/dscp/ns1/named.conf
new file mode 100644 (file)
index 0000000..a7f2344
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2013  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+controls { /* empty */ };
+
+options {
+       dscp 46;
+       query-source address 10.53.0.1;
+       notify-source 10.53.0.1;
+       transfer-source 10.53.0.1;
+       port 5300;
+       pid-file "named.pid";
+       listen-on { 10.53.0.1; };
+       listen-on-v6 { none; };
+       recursion no;
+       notify yes;
+};
+
+zone "." {
+       type master;
+       file "root.db";
+};
diff --git a/bin/tests/system/dscp/ns1/root.db b/bin/tests/system/dscp/ns1/root.db
new file mode 100644 (file)
index 0000000..d13075a
--- /dev/null
@@ -0,0 +1,8 @@
+$TTL 3600
+.      SOA     ns1.nil-servers. marka.isc.org. 1 3600 1200 3600000 1200
+.      NS      ns1.nil-servers.
+.      NS      ns2.nil-servers.
+ns1.nil-servers. A 10.53.0.1
+ns2.nil-servers. A 10.53.0.2
+xxx.example.   A       10.53.0.1
+xxx.tld.       A       10.53.0.1
diff --git a/bin/tests/system/dscp/ns2/named.args b/bin/tests/system/dscp/ns2/named.args
new file mode 100644 (file)
index 0000000..9b94ece
--- /dev/null
@@ -0,0 +1 @@
+-m record,size,mctx -T clienttest -c named.conf -d 99 -g -U 4 -T dscp=46
diff --git a/bin/tests/system/dscp/ns2/named.conf b/bin/tests/system/dscp/ns2/named.conf
new file mode 100644 (file)
index 0000000..dbcc97b
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2013  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+controls { /* empty */ };
+
+options {
+       dscp 46;
+       query-source address 10.53.0.2;
+       notify-source 10.53.0.2;
+       transfer-source 10.53.0.2;
+       port 5300;
+       pid-file "named.pid";
+       listen-on { 10.53.0.2; };
+       listen-on-v6 { none; };
+       recursion no;
+       notify yes;
+};
+
+zone "." {
+       type slave;
+       file "root.bk";
+       masters { 10.53.0.1; };
+};
diff --git a/bin/tests/system/dscp/ns3/hint.db b/bin/tests/system/dscp/ns3/hint.db
new file mode 100644 (file)
index 0000000..c3df01d
--- /dev/null
@@ -0,0 +1,5 @@
+$TTL 3600
+. NS ns1.nil-servers.
+. NS ns2.nil-servers.
+ns1.nil-servers. A 10.53.0.1
+ns2.nil-servers. A 10.53.0.2
diff --git a/bin/tests/system/dscp/ns3/named.args b/bin/tests/system/dscp/ns3/named.args
new file mode 100644 (file)
index 0000000..9b94ece
--- /dev/null
@@ -0,0 +1 @@
+-m record,size,mctx -T clienttest -c named.conf -d 99 -g -U 4 -T dscp=46
diff --git a/bin/tests/system/dscp/ns3/named.conf b/bin/tests/system/dscp/ns3/named.conf
new file mode 100644 (file)
index 0000000..a12b5e2
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2013  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+controls { /* empty */ };
+
+options {
+       dscp 46;
+       query-source address 10.53.0.3;
+       notify-source 10.53.0.3;
+       transfer-source 10.53.0.3;
+       port 5300;
+       pid-file "named.pid";
+       listen-on { 10.53.0.3; };
+       listen-on-v6 { none; };
+       notify yes;
+};
+
+zone "." {
+       type hint;
+       file "hint.db";
+};
diff --git a/bin/tests/system/dscp/ns4/named.args b/bin/tests/system/dscp/ns4/named.args
new file mode 100644 (file)
index 0000000..9b94ece
--- /dev/null
@@ -0,0 +1 @@
+-m record,size,mctx -T clienttest -c named.conf -d 99 -g -U 4 -T dscp=46
diff --git a/bin/tests/system/dscp/ns4/named.conf b/bin/tests/system/dscp/ns4/named.conf
new file mode 100644 (file)
index 0000000..01c5a35
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2013  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+controls { /* empty */ };
+
+options {
+       dscp 47;
+       query-source dscp 46 address 10.53.0.4;
+       notify-source 10.53.0.4 dscp 46;
+       transfer-source 10.53.0.4 dscp 46;
+       port 5300;
+       pid-file "named.pid";
+       listen-on dscp 46 { 10.53.0.4; };
+       listen-on-v6 { none; };
+       recursion no;
+       notify yes;
+};
+
+zone "." {
+       type master;
+       file "root.db";
+};
diff --git a/bin/tests/system/dscp/ns4/root.db b/bin/tests/system/dscp/ns4/root.db
new file mode 100644 (file)
index 0000000..cfd1adf
--- /dev/null
@@ -0,0 +1,8 @@
+$TTL 3600
+.      SOA     ns4.nil-servers. marka.isc.org. 1 3600 1200 3600000 1200
+.      NS      ns4.nil-servers.
+.      NS      ns5.nil-servers.
+ns4.nil-servers. A 10.53.0.4
+ns5.nil-servers. A 10.53.0.5
+xxx.example.   A       10.53.0.1
+xxx.tld.       A       10.53.0.1
diff --git a/bin/tests/system/dscp/ns5/named.args b/bin/tests/system/dscp/ns5/named.args
new file mode 100644 (file)
index 0000000..9b94ece
--- /dev/null
@@ -0,0 +1 @@
+-m record,size,mctx -T clienttest -c named.conf -d 99 -g -U 4 -T dscp=46
diff --git a/bin/tests/system/dscp/ns5/named.conf b/bin/tests/system/dscp/ns5/named.conf
new file mode 100644 (file)
index 0000000..c330963
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2013  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+controls { /* empty */ };
+
+options {
+       dscp 47;
+       query-source dscp 46 address 10.53.0.5;
+       notify-source 10.53.0.5 dscp 46;
+       transfer-source 10.53.0.5 dscp 46;
+       alt-transfer-source 10.53.0.5 dscp 46;
+       port 5300;
+       pid-file "named.pid";
+       listen-on dscp 46 { 10.53.0.5; };
+       listen-on-v6 { none; };
+       recursion no;
+       notify yes;
+};
+
+zone "." {
+       type slave;
+       file "root.bk";
+       masters { 10.53.0.4; };
+};
diff --git a/bin/tests/system/dscp/ns6/hint.db b/bin/tests/system/dscp/ns6/hint.db
new file mode 100644 (file)
index 0000000..6527767
--- /dev/null
@@ -0,0 +1,5 @@
+$TTL 3600
+. NS ns4.nil-servers.
+. NS ns5.nil-servers.
+ns4.nil-servers. A 10.53.0.4
+ns5.nil-servers. A 10.53.0.5
diff --git a/bin/tests/system/dscp/ns6/named.args b/bin/tests/system/dscp/ns6/named.args
new file mode 100644 (file)
index 0000000..9b94ece
--- /dev/null
@@ -0,0 +1 @@
+-m record,size,mctx -T clienttest -c named.conf -d 99 -g -U 4 -T dscp=46
diff --git a/bin/tests/system/dscp/ns6/named.conf b/bin/tests/system/dscp/ns6/named.conf
new file mode 100644 (file)
index 0000000..91e9754
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2013  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+controls { /* empty */ };
+
+options {
+       dscp 47;
+       query-source dscp 46 address 10.53.0.6;
+       notify-source 10.53.0.6 dscp 46;
+       transfer-source 10.53.0.6 dscp 46;
+       port 5300;
+       pid-file "named.pid";
+       listen-on dscp 46 { 10.53.0.6; };
+       listen-on-v6 { none; };
+       notify yes;
+};
+
+zone "." {
+       type hint;
+       file "hint.db";
+};
diff --git a/bin/tests/system/dscp/ns7/named.args b/bin/tests/system/dscp/ns7/named.args
new file mode 100644 (file)
index 0000000..9b94ece
--- /dev/null
@@ -0,0 +1 @@
+-m record,size,mctx -T clienttest -c named.conf -d 99 -g -U 4 -T dscp=46
diff --git a/bin/tests/system/dscp/ns7/named.conf b/bin/tests/system/dscp/ns7/named.conf
new file mode 100644 (file)
index 0000000..31e5ac1
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2013  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+controls { /* empty */ };
+
+options {
+       dscp 47;
+       query-source dscp 46 address 10.53.0.7;
+       notify-source 10.53.0.7 dscp 47;
+       transfer-source 10.53.0.7 dscp 47;
+       alt-transfer-source 10.53.0.7 dscp 47;
+       port 5300;
+       pid-file "named.pid";
+       listen-on dscp 46 { 10.53.0.7; };
+       listen-on-v6 { none; };
+       recursion no;
+       notify yes;
+};
+
+zone "." {
+       type slave;
+       file "root.bk";
+       transfer-source 10.53.0.7 dscp 46;
+       notify-source 10.53.0.7 dscp 46;
+       alt-transfer-source 10.53.0.7 dscp 46;
+       masters { 10.53.0.4; };
+};
diff --git a/bin/tests/system/dscp/tests.sh b/bin/tests/system/dscp/tests.sh
new file mode 100644 (file)
index 0000000..7c767bd
--- /dev/null
@@ -0,0 +1,27 @@
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+DIGOPTS="+tcp +noadd +nosea +nostat +noquest"
+
+status=0
+
+#
+# 10.53.0.1 10.53.0.2 10.53.0.3 have a global dscp setting;
+# 10.53.0.4 10.53.0.5 10.53.0.6 have dscp set in option *-source clauses;
+# 10.53.0.7 has dscp set in zone *-source clauses;
+#
+for server in 10.53.0.1 10.53.0.2 10.53.0.3 10.53.0.4 10.53.0.5 \
+             10.53.0.6 10.53.0.7
+do
+       echo "I:testing root SOA lookup at $server"
+       for i in 0 1 2 3 4 5 6 7 8 9
+       do
+               ret=0
+               $DIG -p 5300 @$server $DIGOPTS soa . > dig.out.$server
+               grep "status: NOERROR" dig.out.$server > /dev/null || ret=1
+               test $ret = 0 && break
+               sleep 1
+       done
+       test $ret = 0 || { echo "I:failed"; status=`expr $status + $ret`; }
+done
+exit $status
index 86fe91d070747aeab8dd460a8a49670b083743ef..0fd61487997857632c0a49ffbe1d26026142cfbb 100644 (file)
@@ -20,9 +20,9 @@
 controls { /* empty */ };
 
 options {
-       query-source address 10.53.0.1;
-       notify-source 10.53.0.1;
-       transfer-source 10.53.0.1;
+       query-source address 10.53.0.1 dscp 1;
+       notify-source 10.53.0.1 dscp 22;
+       transfer-source 10.53.0.1 dscp 3;
        port 5300;
        pid-file "named.pid";
        session-keyfile "session.key";
index 6db32202fffb920a54f64af09a4d8b02aa48375f..fc6dd611b82511ae1984f685d4a7e53253225440 100644 (file)
@@ -20,9 +20,9 @@
 controls { /* empty */ };
 
 options {
-       query-source address 10.53.0.2;
-       notify-source 10.53.0.2;
-       transfer-source 10.53.0.2;
+       query-source address 10.53.0.2 dscp 4;
+       notify-source 10.53.0.2 dscp 5;
+       transfer-source 10.53.0.2 dscp 6;
        port 5300;
        pid-file "named.pid";
        listen-on { 10.53.0.2; };
index 4b43efe4f22d293685ba34ea522ca9648ec1f41e..8b706e9bd7d897227813d1cf0707a2ec5249fbbc 100644 (file)
@@ -21,9 +21,9 @@
 controls { /* empty */ };
 
 options {
-       query-source address 10.53.0.3;
-       notify-source 10.53.0.3;
-       transfer-source 10.53.0.3;
+       query-source address 10.53.0.3 dscp 7;
+       notify-source 10.53.0.3 dscp 8;
+       transfer-source 10.53.0.3 dscp 9;
        port 5300;
        pid-file "named.pid";
        listen-on { 10.53.0.3; };
index 65068655ea28b824ab69783161096a0fb17cd995..f249df907a7f965bd3534f2cc6fade90cd6cf597 100644 (file)
@@ -20,9 +20,9 @@
 controls { /* empty */ };
 
 options {
-       query-source address 10.53.0.1;
-       notify-source 10.53.0.1;
-       transfer-source 10.53.0.1;
+       query-source address 10.53.0.1 dscp 1;
+       notify-source 10.53.0.1 dscp 2;
+       transfer-source 10.53.0.1 dscp 3;
        port 5300;
        pid-file "named.pid";
        listen-on { 10.53.0.1; };
index 307b07c765ed828256921e62a61a3265d08f80bf..c2275d8e67e187bef42024092b09674fe19fcab4 100644 (file)
@@ -21,9 +21,9 @@
 controls { /* empty */ };
 
 options {
-       query-source address 10.53.0.4;
-       notify-source 10.53.0.4;
-       transfer-source 10.53.0.4;
+       query-source address 10.53.0.4 dscp 4;
+       notify-source 10.53.0.4 dscp 5;
+       transfer-source 10.53.0.4 dscp 6;
        port 5300;
        pid-file "named.pid";
        listen-on { 10.53.0.4; };
index 1abedf67f1349a3166a250b96e8ea190fe76c2d9..4457ae5cfa5f16eb24fc9d122fc45d8f370a5ad6 100644 (file)
@@ -21,9 +21,9 @@
 controls { /* empty */ };
 
 options {
-       query-source address 10.53.0.5;
-       notify-source 10.53.0.5;
-       transfer-source 10.53.0.5;
+       query-source address 10.53.0.5 dscp 7;
+       notify-source 10.53.0.5 dscp 8;
+       transfer-source 10.53.0.5 dscp 9;
        port 5300;
        pid-file "named.pid";
        listen-on { 10.53.0.5; };
index 35cccb79dfaf7ef7360d33b47a07efdc5e904d00..d8bbf09e11764802671c7430a265f8f64ff30936 100644 (file)
@@ -21,9 +21,9 @@
 controls { /* empty */ };
 
 options {
-       query-source address 10.53.0.6;
-       notify-source 10.53.0.6;
-       transfer-source 10.53.0.6;
+       query-source address 10.53.0.6 dscp 10;
+       notify-source 10.53.0.6 dscp 11;
+       transfer-source 10.53.0.6 dscp 12;
        port 5300;
        pid-file "named.pid";
        listen-on { 10.53.0.6; };
index a41afd0ebcf80fc211f85b4b7bd3ee6abf24ba44..cde389c283d2fd9ffa8c067277ae71452ce147bb 100644 (file)
@@ -21,9 +21,9 @@
 controls { /* empty */ };
 
 options {
-       query-source address 10.53.0.7;
-       notify-source 10.53.0.7;
-       transfer-source 10.53.0.7;
+       query-source address 10.53.0.7 dscp 13;
+       notify-source 10.53.0.7 dscp 14;
+       transfer-source 10.53.0.7 dscp 15;
        port 5300;
        pid-file "named.pid";
        listen-on { 10.53.0.7; };
index df4c02db3bb76e7a63c93ff8c3e5b01a12cedcd2..7bdcc64aaa486b5ba106c9f0212f2a2b413136d4 100644 (file)
@@ -3279,6 +3279,21 @@ $ORIGIN 0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa.
                 </para>
               </entry>
             </row>
+            <row rowsep="0">
+              <entry colname="1">
+                <para>
+                  <varname>ip_dscp</varname>
+                </para>
+              </entry>
+              <entry colname="2">
+                <para>
+                  A <varname>number</varname> between 0 and 63, used
+                  to select a differentiated services code point (DSCP)
+                  value for use with outgoing traffic on operating systems
+                  that support DSCP.
+                </para>
+              </entry>
+            </row>
             <row rowsep="0">
               <entry colname="1">
                 <para>
@@ -5170,8 +5185,8 @@ badresp:1,adberr:0,findfail:0,valfail:0]
         </para>
 
 <programlisting><command>lwres</command> {
-    <optional> listen-on { <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> ;
-                <optional> <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> ; ... </optional> }; </optional>
+    <optional> listen-on { <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> <optional>dscp <replaceable>ip_dscp</replaceable></optional> ;
+    <optional> <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> <optional>dscp <replaceable>ip_dscp</replaceable></optional> ; ... </optional> }; </optional>
     <optional> view <replaceable>view_name</replaceable>; </optional>
     <optional> search { <replaceable>domain_name</replaceable> ; <optional> <replaceable>domain_name</replaceable> ; ... </optional> }; </optional>
     <optional> ndots <replaceable>number</replaceable>; </optional>
@@ -5238,7 +5253,7 @@ badresp:1,adberr:0,findfail:0,valfail:0]
         <title><command>masters</command> Statement Grammar</title>
 
 <programlisting>
-<command>masters</command> <replaceable>name</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> { ( <replaceable>masters_list</replaceable> | 
+<command>masters</command> <replaceable>name</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> <optional>dscp <replaceable>ip_dscp</replaceable></optional> { ( <replaceable>masters_list</replaceable> | 
       <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> <optional>key <replaceable>key</replaceable></optional> ) ; <optional>...</optional> };
 </programlisting>
 
@@ -5313,10 +5328,10 @@ badresp:1,adberr:0,findfail:0,valfail:0]
     <optional> dnssec-must-be-secure <replaceable>domain yes_or_no</replaceable>; </optional>
     <optional> dnssec-accept-expired <replaceable>yes_or_no</replaceable>; </optional>
     <optional> forward ( <replaceable>only</replaceable> | <replaceable>first</replaceable> ); </optional>
-    <optional> forwarders { <optional> <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> ; ... </optional> }; </optional>
-    <optional> dual-stack-servers <optional>port <replaceable>ip_port</replaceable></optional> {
-        ( <replaceable>domain_name</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> |
-          <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> ) ; 
+    <optional> forwarders { <optional> <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> <optional>dscp <replaceable>ip_dscp</replaceable></optional> ; ... </optional> }; </optional>
+    <optional> dual-stack-servers <optional>port <replaceable>ip_port</replaceable></optional> <optional>dscp <replaceable>ip_dscp</replaceable></optional> {
+        ( <replaceable>domain_name</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> <optional>dscp <replaceable>ip_dscp</replaceable></optional> |
+          <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> <optional>dscp <replaceable>ip_dscp</replaceable></optional>) ; 
         ... }; </optional>
     <optional> check-names ( <replaceable>master</replaceable> | <replaceable>slave</replaceable> | <replaceable>response</replaceable> )
         ( <replaceable>warn</replaceable> | <replaceable>fail</replaceable> | <replaceable>ignore</replaceable> ); </optional>
@@ -5350,16 +5365,21 @@ badresp:1,adberr:0,findfail:0,valfail:0]
     <optional> avoid-v4-udp-ports { <replaceable>port_list</replaceable> }; </optional>
     <optional> use-v6-udp-ports { <replaceable>port_list</replaceable> }; </optional>
     <optional> avoid-v6-udp-ports { <replaceable>port_list</replaceable> }; </optional>
-    <optional> listen-on <optional> port <replaceable>ip_port</replaceable> </optional> { <replaceable>address_match_list</replaceable> }; </optional>
-    <optional> listen-on-v6 <optional> port <replaceable>ip_port</replaceable> </optional> { <replaceable>address_match_list</replaceable> }; </optional>
+    <optional> listen-on <optional> port <replaceable>ip_port</replaceable> </optional> <optional>dscp <replaceable>ip_dscp</replaceable></optional> { <replaceable>address_match_list</replaceable> }; </optional>
+    <optional> listen-on-v6 <optional> port <replaceable>ip_port</replaceable></optional> <optional>dscp <replaceable>ip_dscp</replaceable></optional>
+{ <replaceable>address_match_list</replaceable> }; </optional>
     <optional> query-source ( ( <replaceable>ip4_addr</replaceable> | <replaceable>*</replaceable> )
-        <optional> port ( <replaceable>ip_port</replaceable> | <replaceable>*</replaceable> ) </optional> |
+        <optional> port ( <replaceable>ip_port</replaceable> | <replaceable>*</replaceable> ) </optional>
+        <optional> dscp <replaceable>ip_dscp</replaceable></optional> |
         <optional> address ( <replaceable>ip4_addr</replaceable> | <replaceable>*</replaceable> ) </optional>
-        <optional> port ( <replaceable>ip_port</replaceable> | <replaceable>*</replaceable> ) </optional> ) ; </optional>
+        <optional> port ( <replaceable>ip_port</replaceable> | <replaceable>*</replaceable> ) </optional> )
+        <optional> dscp <replaceable>ip_dscp</replaceable></optional> ; </optional>
     <optional> query-source-v6 ( ( <replaceable>ip6_addr</replaceable> | <replaceable>*</replaceable> )
-        <optional> port ( <replaceable>ip_port</replaceable> | <replaceable>*</replaceable> ) </optional> | 
+        <optional> port ( <replaceable>ip_port</replaceable> | <replaceable>*</replaceable> ) </optional>
+        <optional> dscp <replaceable>ip_dscp</replaceable></optional> |
         <optional> address ( <replaceable>ip6_addr</replaceable> | <replaceable>*</replaceable> ) </optional> 
-        <optional> port ( <replaceable>ip_port</replaceable> | <replaceable>*</replaceable> ) </optional> ) ; </optional>
+        <optional> port ( <replaceable>ip_port</replaceable> | <replaceable>*</replaceable> ) </optional> )
+        <optional> dscp <replaceable>ip_dscp</replaceable></optional> ; </optional>
     <optional> use-queryport-pool <replaceable>yes_or_no</replaceable>; </optional>
     <optional> queryport-pool-ports <replaceable>number</replaceable>; </optional>
     <optional> queryport-pool-updateinterval <replaceable>number</replaceable>; </optional>
@@ -5377,19 +5397,18 @@ badresp:1,adberr:0,findfail:0,valfail:0]
     <optional> transfers-in  <replaceable>number</replaceable>; </optional>
     <optional> transfers-out <replaceable>number</replaceable>; </optional>
     <optional> transfers-per-ns <replaceable>number</replaceable>; </optional>
-    <optional> transfer-source (<replaceable>ip4_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> ; </optional>
-    <optional> transfer-source-v6 (<replaceable>ip6_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> ; </optional>
-    <optional> alt-transfer-source (<replaceable>ip4_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> ; </optional>
-    <optional> alt-transfer-source-v6 (<replaceable>ip6_addr</replaceable> | <constant>*</constant>)
-                             <optional>port <replaceable>ip_port</replaceable></optional> ; </optional>
+    <optional> transfer-source (<replaceable>ip4_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> <optional>dscp <replaceable>ip_dscp</replaceable></optional> ; </optional>
+    <optional> transfer-source-v6 (<replaceable>ip6_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> <optional>dscp <replaceable>ip_dscp</replaceable></optional> ; </optional>
+    <optional> alt-transfer-source (<replaceable>ip4_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> <optional>dscp <replaceable>ip_dscp</replaceable></optional> ; </optional>
+    <optional> alt-transfer-source-v6 (<replaceable>ip6_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> <optional>dscp <replaceable>ip_dscp</replaceable></optional> ; </optional>
     <optional> use-alt-transfer-source <replaceable>yes_or_no</replaceable>; </optional>
     <optional> notify-delay <replaceable>seconds</replaceable> ; </optional>
-    <optional> notify-source (<replaceable>ip4_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> ; </optional>
-    <optional> notify-source-v6 (<replaceable>ip6_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> ; </optional>
+    <optional> notify-source (<replaceable>ip4_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> <optional>dscp <replaceable>ip_dscp</replaceable></optional> ; </optional>
+    <optional> notify-source-v6 (<replaceable>ip6_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> <optional>dscp <replaceable>ip_dscp</replaceable></optional> ; </optional>
     <optional> notify-to-soa <replaceable>yes_or_no</replaceable> ; </optional>
     <optional> also-notify { <replaceable>ip_addr</replaceable>
-                    <optional>port <replaceable>ip_port</replaceable></optional> <optional>key <replaceable>keyname</replaceable></optional> ;
-                    <optional> <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> <optional>key <replaceable>keyname</replaceable></optional> ; ... </optional> }; </optional>
+                    <optional>port <replaceable>ip_port</replaceable></optional> <optional>dscp <replaceable>ip_dscp</replaceable></optional> <optional>key <replaceable>keyname</replaceable></optional> ;
+                    <optional> <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> <optional>dscp <replaceable>ip_dscp</replaceable></optional> <optional>key <replaceable>keyname</replaceable></optional> ; ... </optional> }; </optional>
     <optional> max-ixfr-log-size <replaceable>number</replaceable>; </optional>
     <optional> max-journal-size <replaceable>size_spec</replaceable>; </optional>
     <optional> coresize <replaceable>size_spec</replaceable> ; </optional>
@@ -5420,6 +5439,7 @@ badresp:1,adberr:0,findfail:0,valfail:0]
     <optional> min-retry-time <replaceable>number</replaceable> ; </optional>
     <optional> max-retry-time <replaceable>number</replaceable> ; </optional>
     <optional> port <replaceable>ip_port</replaceable>; </optional>
+    <optional> dscp <replaceable>ip_dscp</replaceable></optional> ;
     <optional> additional-from-auth <replaceable>yes_or_no</replaceable> ; </optional>
     <optional> additional-from-cache <replaceable>yes_or_no</replaceable> ; </optional>
     <optional> random-device <replaceable>path_name</replaceable> ; </optional>
@@ -10275,14 +10295,14 @@ ns.domain.com.rpz-nsdname   CNAME   .
     <optional> transfers <replaceable>number</replaceable> ; </optional>
     <optional> transfer-format <replaceable>( one-answer | many-answers )</replaceable> ; ]</optional>
     <optional> keys <replaceable>{ string ; <optional> string ; <optional>...</optional></optional> }</replaceable> ; </optional>
-    <optional> transfer-source (<replaceable>ip4_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> ; </optional>
-    <optional> transfer-source-v6 (<replaceable>ip6_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> ; </optional>
-    <optional> notify-source (<replaceable>ip4_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> ; </optional>
-    <optional> notify-source-v6 (<replaceable>ip6_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> ; </optional>
+    <optional> transfer-source (<replaceable>ip4_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> <optional>dscp <replaceable>ip_dscp</replaceable></optional> ; </optional>
+    <optional> transfer-source-v6 (<replaceable>ip6_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> <optional>dscp <replaceable>ip_dscp</replaceable></optional> ; </optional>
+    <optional> notify-source (<replaceable>ip4_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> <optional>dscp <replaceable>ip_dscp</replaceable></optional> ; </optional>
+    <optional> notify-source-v6 (<replaceable>ip6_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> <optional>dscp <replaceable>ip_dscp</replaceable></optional> ; </optional>
     <optional> query-source <optional> address ( <replaceable>ip_addr</replaceable> | <replaceable>*</replaceable> ) </optional>
-                  <optional> port ( <replaceable>ip_port</replaceable> | <replaceable>*</replaceable> ) </optional>; </optional>
+                  <optional> port ( <replaceable>ip_port</replaceable> | <replaceable>*</replaceable> ) </optional> <optional>dscp <replaceable>ip_dscp</replaceable></optional> ; </optional>
     <optional> query-source-v6 <optional> address ( <replaceable>ip_addr</replaceable> | <replaceable>*</replaceable> ) </optional>
-                     <optional> port ( <replaceable>ip_port</replaceable> | <replaceable>*</replaceable> ) </optional>; </optional>
+                     <optional> port ( <replaceable>ip_port</replaceable> | <replaceable>*</replaceable> ) </optional> <optional>dscp <replaceable>ip_dscp</replaceable></optional> ; </optional>
     <optional> use-queryport-pool <replaceable>yes_or_no</replaceable>; </optional>
     <optional> queryport-pool-ports <replaceable>number</replaceable>; </optional>
     <optional> queryport-pool-updateinterval <replaceable>number</replaceable>; </optional>
@@ -10930,8 +10950,8 @@ view "external" {
     <optional> dnssec-dnskey-kskonly <replaceable>yes_or_no</replaceable>; </optional>
     <optional> dnssec-loadkeys-interval <replaceable>number</replaceable>; </optional>
     <optional> update-policy <replaceable>local</replaceable> | { <replaceable>update_policy_rule</replaceable> <optional>...</optional> }; </optional>
-    <optional> also-notify { <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> ;
-                  <optional> <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> ; ... </optional> }; </optional>
+    <optional> also-notify { <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> <optional>dscp <replaceable>ip_dscp</replaceable></optional> ;
+                  <optional> <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> <optional>dscp <replaceable>ip_dscp</replaceable></optional> ; ... </optional> }; </optional>
     <optional> check-names (<constant>warn</constant>|<constant>fail</constant>|<constant>ignore</constant>) ; </optional>
     <optional> check-mx (<constant>warn</constant>|<constant>fail</constant>|<constant>ignore</constant>) ; </optional>
     <optional> check-wildcard <replaceable>yes_or_no</replaceable>; </optional>
@@ -10942,7 +10962,7 @@ view "external" {
     <optional> journal <replaceable>string</replaceable> ; </optional>
     <optional> max-journal-size <replaceable>size_spec</replaceable>; </optional>
     <optional> forward (<constant>only</constant>|<constant>first</constant>) ; </optional>
-    <optional> forwarders { <optional> <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> ; ... </optional> }; </optional>
+    <optional> forwarders { <optional> <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> <optional>dscp <replaceable>ip_dscp</replaceable></optional> ; ... </optional> }; </optional>
     <optional> ixfr-base <replaceable>string</replaceable> ; </optional>
     <optional> ixfr-from-differences <replaceable>yes_or_no</replaceable>; </optional>
     <optional> ixfr-tmp-file <replaceable>string</replaceable> ; </optional>
@@ -10955,8 +10975,8 @@ view "external" {
     <optional> notify-delay <replaceable>seconds</replaceable> ; </optional>
     <optional> notify-to-soa <replaceable>yes_or_no</replaceable>; </optional>
     <optional> pubkey <replaceable>number</replaceable> <replaceable>number</replaceable> <replaceable>number</replaceable> <replaceable>string</replaceable> ; </optional>
-    <optional> notify-source (<replaceable>ip4_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> ; </optional>
-    <optional> notify-source-v6 (<replaceable>ip6_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> ; </optional>
+    <optional> notify-source (<replaceable>ip4_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> <optional>dscp <replaceable>ip_dscp</replaceable></optional> ; </optional>
+    <optional> notify-source-v6 (<replaceable>ip6_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> <optional>dscp <replaceable>ip_dscp</replaceable></optional> ; </optional>
     <optional> zone-statistics <replaceable>full</replaceable> | <replaceable>terse</replaceable> | <replaceable>none</replaceable>; </optional>
     <optional> sig-validity-interval <replaceable>number</replaceable> <optional><replaceable>number</replaceable></optional> ; </optional>
     <optional> sig-signing-nodes <replaceable>number</replaceable> ; </optional>
@@ -10987,8 +11007,9 @@ zone <replaceable>zone_name</replaceable> <optional><replaceable>class</replacea
     <optional> dnssec-loadkeys-interval <replaceable>number</replaceable>; </optional>
     <optional> dnssec-secure-to-insecure <replaceable>yes_or_no</replaceable> ; </optional>
     <optional> try-tcp-refresh <replaceable>yes_or_no</replaceable>; </optional>
-    <optional> also-notify <optional>port <replaceable>ip_port</replaceable></optional> { ( <replaceable>masters_list</replaceable> | <replaceable>ip_addr</replaceable>
+    <optional> also-notify <optional>port <replaceable>ip_port</replaceable></optional> <optional>dscp <replaceable>ip_dscp</replaceable></optional> { ( <replaceable>masters_list</replaceable> | <replaceable>ip_addr</replaceable>
                               <optional>port <replaceable>ip_port</replaceable></optional>
+                              <optional>dscp <replaceable>ip_dscp</replaceable></optional>
                               <optional>key <replaceable>key</replaceable></optional> ) ; <optional>...</optional> }; </optional>
     <optional> check-names (<constant>warn</constant>|<constant>fail</constant>|<constant>ignore</constant>) ; </optional>
     <optional> dialup <replaceable>dialup_option</replaceable> ; </optional>
@@ -10997,13 +11018,14 @@ zone <replaceable>zone_name</replaceable> <optional><replaceable>class</replacea
     <optional> journal <replaceable>string</replaceable> ; </optional>
     <optional> max-journal-size <replaceable>size_spec</replaceable>; </optional>
     <optional> forward (<constant>only</constant>|<constant>first</constant>) ; </optional>
-    <optional> forwarders { <optional> <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> ; ... </optional> }; </optional>
+    <optional> forwarders { <optional> <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> <optional>dscp <replaceable>ip_dscp</replaceable></optional> ; ... </optional> }; </optional>
     <optional> ixfr-base <replaceable>string</replaceable> ; </optional>
     <optional> ixfr-from-differences <replaceable>yes_or_no</replaceable>; </optional>
     <optional> ixfr-tmp-file <replaceable>string</replaceable> ; </optional>
     <optional> maintain-ixfr-base <replaceable>yes_or_no</replaceable> ; </optional>
-    <optional> masters <optional>port <replaceable>ip_port</replaceable></optional> { ( <replaceable>masters_list</replaceable> | <replaceable>ip_addr</replaceable>
+    <optional> masters <optional>port <replaceable>ip_port</replaceable></optional> <optional>dscp <replaceable>ip_dscp</replaceable></optional> { ( <replaceable>masters_list</replaceable> | <replaceable>ip_addr</replaceable>
                               <optional>port <replaceable>ip_port</replaceable></optional>
+                              <optional>dscp <replaceable>ip_dscp</replaceable></optional>
                               <optional>key <replaceable>key</replaceable></optional> ) ; <optional>...</optional> }; </optional>
     <optional> max-ixfr-log-size <replaceable>number</replaceable> ; </optional>
     <optional> max-transfer-idle-in <replaceable>number</replaceable> ; </optional>
@@ -11014,14 +11036,15 @@ zone <replaceable>zone_name</replaceable> <optional><replaceable>class</replacea
     <optional> notify-delay <replaceable>seconds</replaceable> ; </optional>
     <optional> notify-to-soa <replaceable>yes_or_no</replaceable>; </optional>
     <optional> pubkey <replaceable>number</replaceable> <replaceable>number</replaceable> <replaceable>number</replaceable> <replaceable>string</replaceable> ; </optional>
-    <optional> transfer-source (<replaceable>ip4_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> ; </optional>
-    <optional> transfer-source-v6 (<replaceable>ip6_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> ; </optional>
-    <optional> alt-transfer-source (<replaceable>ip4_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> ; </optional>
+    <optional> transfer-source (<replaceable>ip4_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> <optional>dscp <replaceable>ip_dscp</replaceable></optional> ; </optional>
+    <optional> transfer-source-v6 (<replaceable>ip6_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> <optional>dscp <replaceable>ip_dscp</replaceable></optional> ; </optional>
+    <optional> alt-transfer-source (<replaceable>ip4_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> <optional>dscp <replaceable>ip_dscp</replaceable></optional> ; </optional>
     <optional> alt-transfer-source-v6 (<replaceable>ip6_addr</replaceable> | <constant>*</constant>)
-                             <optional>port <replaceable>ip_port</replaceable></optional> ; </optional>
+                             <optional>port <replaceable>ip_port</replaceable></optional>
+                             <optional>dscp <replaceable>ip_dscp</replaceable></optional> ; </optional>
     <optional> use-alt-transfer-source <replaceable>yes_or_no</replaceable>; </optional>
-    <optional> notify-source (<replaceable>ip4_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> ; </optional>
-    <optional> notify-source-v6 (<replaceable>ip6_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> ; </optional>
+    <optional> notify-source (<replaceable>ip4_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> <optional>dscp <replaceable>ip_dscp</replaceable></optional> ; </optional>
+    <optional> notify-source-v6 (<replaceable>ip6_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> <optional>dscp <replaceable>ip_dscp</replaceable></optional> ; </optional>
     <optional> zone-statistics <replaceable>full</replaceable> | <replaceable>terse</replaceable> | <replaceable>none</replaceable>; </optional>
     <optional> sig-validity-interval <replaceable>number</replaceable> <optional><replaceable>number</replaceable></optional> ; </optional>
     <optional> sig-signing-nodes <replaceable>number</replaceable> ; </optional>
@@ -11056,19 +11079,20 @@ zone <replaceable>zone_name</replaceable> <optional><replaceable>class</replacea
     <optional> file <replaceable>string</replaceable> ; </optional>
     <optional> masterfile-format (<constant>text</constant>|<constant>raw</constant>|<constant>map</constant>) ; </optional>
     <optional> forward (<constant>only</constant>|<constant>first</constant>) ; </optional>
-    <optional> forwarders { <optional> <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> ; ... </optional> }; </optional>
-    <optional> masters <optional>port <replaceable>ip_port</replaceable></optional> { ( <replaceable>masters_list</replaceable> | <replaceable>ip_addr</replaceable>
+    <optional> forwarders { <optional> <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> <optional>dscp <replaceable>ip_dscp</replaceable></optional> ; ... </optional> }; </optional>
+    <optional> masters <optional>port <replaceable>ip_port</replaceable></optional> <optional>dscp <replaceable>ip_dscp</replaceable></optional> { ( <replaceable>masters_list</replaceable> | <replaceable>ip_addr</replaceable>
                               <optional>port <replaceable>ip_port</replaceable></optional>
+                              <optional>dscp <replaceable>ip_dscp</replaceable></optional>
                               <optional>key <replaceable>key</replaceable></optional> ) ; <optional>...</optional> }; </optional>
     <optional> max-transfer-idle-in <replaceable>number</replaceable> ; </optional>
     <optional> max-transfer-time-in <replaceable>number</replaceable> ; </optional>
     <optional> pubkey <replaceable>number</replaceable> <replaceable>number</replaceable> <replaceable>number</replaceable> <replaceable>string</replaceable> ; </optional>
-    <optional> transfer-source (<replaceable>ip4_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> ; </optional>
+    <optional> transfer-source (<replaceable>ip4_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> <optional>dscp <replaceable>ip_dscp</replaceable></optional> ; </optional>
     <optional> transfer-source-v6 (<replaceable>ip6_addr</replaceable> | <constant>*</constant>)
-                         <optional>port <replaceable>ip_port</replaceable></optional> ; </optional>
-    <optional> alt-transfer-source (<replaceable>ip4_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> ; </optional>
+                         <optional>port <replaceable>ip_port</replaceable></optional> <optional>dscp <replaceable>ip_dscp</replaceable></optional> ; </optional>
+    <optional> alt-transfer-source (<replaceable>ip4_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> <optional>dscp <replaceable>ip_dscp</replaceable></optional> ; </optional>
     <optional> alt-transfer-source-v6 (<replaceable>ip6_addr</replaceable> | <constant>*</constant>)
-                            <optional>port <replaceable>ip_port</replaceable></optional> ; </optional>
+                            <optional>port <replaceable>ip_port</replaceable></optional> <optional>dscp <replaceable>ip_dscp</replaceable></optional> ; </optional>
     <optional> use-alt-transfer-source <replaceable>yes_or_no</replaceable>; </optional>
     <optional> zone-statistics <replaceable>yes_or_no</replaceable> ; </optional>
     <optional> database <replaceable>string</replaceable> ; </optional>
@@ -11090,7 +11114,7 @@ zone <replaceable>zone_name</replaceable> <optional><replaceable>class</replacea
 zone <replaceable>zone_name</replaceable> <optional><replaceable>class</replaceable></optional> {
     type forward;
     <optional> forward (<constant>only</constant>|<constant>first</constant>) ; </optional>
-    <optional> forwarders { <optional> <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> ; ... </optional> }; </optional>
+    <optional> forwarders { <optional> <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> <optional>dscp <replaceable>ip_dscp</replaceable></optional> ; ... </optional> }; </optional>
     <optional> delegation-only <replaceable>yes_or_no</replaceable> ; </optional>
 };
 
diff --git a/doc/design/dscp b/doc/design/dscp
new file mode 100644 (file)
index 0000000..cc9fded
--- /dev/null
@@ -0,0 +1,133 @@
+
+       Differentiate Services Code Point Support
+
+$Id: dscp,v 1.1.2.1 2012/02/24 05:20:36 marka Exp $
+
+Differentiate Services Code Point (DSCP) is implemented in IPv4 using the
+TOS octet and in IPv6 using the TCLASS octet.
+
+RFC 3542 defines the api to manipulate the TCLASS octet as part of
+the advanced socket API.  TCLASS is settable on both a socket and
+packet basis (setsockopt/sendmsg) and the sent value can be retrieved
+using recvmsg over UDP.  Retrieval is undefined for TCP.
+
+The Advanced socket API was not incorporated into the POSIX socket
+API for IPv6 and may not be completely implemented in any OS.
+
+For TOS setsockopt() supports setting of the field on a persocket
+basis.  TOS may also be set on a per packet basis on some OS using
+sendmsg.  If it is not supported the sendmsg call reports a error.
+Support can only be determined by attempted to send a packet with
+the option set.  Retrieval of the sent TOS value is retrievable on
+Linux.  This can be determined at compile time.
+
+DSCP values need to be compatible with TOS values as it is a re-use
+of the field.
+
+LIBISC:
+
+We will need to be able to probe for the level of DSCP support.  We
+need to know if we can set it at the socket level, packet level and
+if we can retrieve the DSCP value sent.  This needs to be done
+independently for IPv4 and IPv6.
+
+#define ISC_NET_DSCPRECVV4      0x01    /* Can receive sent DSCP value IPv4 */
+#define ISC_NET_DSCPRECVV6      0x02    /* Can receive sent DSCP value IPv6 */
+#define ISC_NET_DSCPSETV4       0x04    /* Can set DSCP on socket IPv4 */
+#define ISC_NET_DSCPSETV6       0x08    /* Can set DSCP on socket IPv6 */
+#define ISC_NET_DSCPPKTV4       0x10    /* Can set DSCP on per packet IPv4 */
+#define ISC_NET_DSCPPKTV6       0x20    /* Can set DSCP on per packet IPv6 */
+#define ISC_NET_DSCPALL         0x3f    /* All valid flags */
+
+unsigned int
+isc_net_probedscp(void);
+/*%<
+ * Probe the level of DSCP support.
+ */
+
+We also need to be able to set DSCP values on a per socket basis, per packet
+basis and to retrieve dscp values from received packet.
+
+Setting dscp on a per socket basis shall be done using isc_socket_dscp.
+
+void
+isc_socket_dscp(isc_socket_t *sock, unsigned int dscp);
+/*%<
+ * Requires:
+ *\li   'sock' is a valid socket.
+ */
+/*@}*/
+
+isc_socketevent shall be extended to support the sending of and retrieval
+of DSCP values.  If ISC_SOCKEVENTATTR_DSCP is set then isc_socket_sendto2
+shall set the DSCP value.  isc_socket_recv shall set ISC_SOCKEVENTATTR_DSCP
+and the dscp element if the OS returns the value via recvmsg.
+
+#define ISC_SOCKEVENTATTR_DSCP                  0x00040000U /* public */
+
+struct isc_socketevent {
+        ISC_EVENT_COMMON(isc_socketevent_t);
+        isc_result_t            result;         /*%< OK, EOF, whatever else */
+        unsigned int            minimum;        /*%< minimum i/o for event */
+        unsigned int            n;              /*%< bytes read or written */
+        unsigned int            offset;         /*%< offset into buffer list */
+        isc_region_t            region;         /*%< for single-buffer i/o */
+        isc_bufferlist_t        bufferlist;     /*%< list of buffers */
+        isc_sockaddr_t          address;        /*%< source address */
+        isc_time_t              timestamp;      /*%< timestamp of packet recv */
+        struct in6_pktinfo      pktinfo;        /*%< ipv6 pktinfo */
+        isc_uint32_t            attributes;     /*%< see below */
+        isc_eventdestructor_t   destroy;        /*%< original destructor */
+        unsigned int            dscp;           /*%< UDP dscp value */
+};
+
+A convience function will be provided to allocate and intialize the structure.
+
+isc_socketevent_t *
+isc_socket_socketevent(isc_socket_t *sock0, isc_eventtype_t eventtype,
+                       isc_taskaction_t action, const void *arg)
+
+NAMED/LIBDNS:
+
+Named needs to be able to set the DSCP value of sent traffic.  We should
+be able to set DSCP for all TCP connections.
+
+For UDP we should have a default DSCP value for when we can't set this on
+a per packet basis with the ability to override for specific destinations.
+
+options/view/server;
+tcp-dscp <value>;
+udp-dscp <value>;
+
+http://bogpeople.com/networking/dscp.shtml list a set of TOS compatible
+values (below).
+
+DSCP Name      DS Field Value  IP Precedence
+                Binary Decimal
+CS0            000 000 0       0
+CS1            001 000 8       1
+AF11           001 010 10      1
+AF12           001 100 12      1
+AF13           001 110 14      1
+CS2            010 000 16      2
+AF21           010 010 18      2
+AF22           010 100 20      2
+AF23           010 110 22      2
+CS3            011 000 24      3
+AF31           011 010 26      3
+AF32           011 100 28      3
+AF33           011 110 30      3
+CS4            100 000 32      4
+AF41           100 010 34      4
+AF42           100 100 36      4
+AF43           100 110 38      4
+CS5            101 000 40      5
+EF             101 110 46      5
+CS6            110 000 48      6
+CS7            111 000 56      7
+
+CS     Class Selector (RFC 2474)
+AFxy   Assured Forwarding (x=class, y=drop precedence) (RFC2597)
+EF     Expedited Forwarding (RFC 3246)
+
+value should be one of these or a numeric 0..63.  The default value is 0.
index 723645ca4bd9e7e0b5ce947c373656e1af0f8d34..6069010ec4503b025110685462935d25b7c9ce9f 100644 (file)
@@ -38,8 +38,8 @@ logging {
 };
 
 lwres {
-        listen-on [ port <integer> ] { ( <ipv4_address> | <ipv6_address> )
-            [ port <integer> ]; ... };
+        listen-on [ port <integer> ] [ dscp <integer> ] { ( <ipv4_address>
+            | <ipv6_address> ) [ port <integer> ] [ dscp <integer> ]; ... };
         ndots <integer>;
         search { <string>; ... };
         view <string> <optional_class>;
@@ -48,8 +48,9 @@ lwres {
 managed-keys { <string> <string> <integer> <integer> <integer>
     <quoted_string>; ... };
 
-masters <string> [ port <integer> ] { ( <masters> | <ipv4_address> [ port
-    <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ]; ... };
+masters <string> [ port <integer> ] [ dscp <integer> ] { ( <masters> |
+    <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] )
+    [ key <string> ]; ... };
 
 options {
         acache-cleaning-interval <integer>;
@@ -68,12 +69,13 @@ options {
         allow-update { <address_match_element>; ... };
         allow-update-forwarding { <address_match_element>; ... };
         allow-v6-synthesis { <address_match_element>; ... }; // obsolete
-        also-notify [ port <integer> ] { ( <masters> | <ipv4_address> [
-            port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key
-            <string> ]; ... };
-        alt-transfer-source ( <ipv4_address> | * ) [ port ( <integer> | * ) ];
+        also-notify [ port <integer> ] [ dscp <integer> ] { ( <masters> |
+            <ipv4_address> [ port <integer> ] | <ipv6_address> [ port
+            <integer> ] ) [ key <string> ]; ... };
+        alt-transfer-source ( <ipv4_address> | * ) [ port ( <integer> | * )
+            ] [ dscp <integer> ];
         alt-transfer-source-v6 ( <ipv6_address> | * ) [ port ( <integer> |
-            * ) ];
+            * ) ] [ dscp <integer> ];
         attach-cache <string>;
         auth-nxdomain <boolean>; // default changed
         auto-dnssec ( allow | maintain | off );
@@ -123,9 +125,11 @@ options {
         dnssec-secure-to-insecure <boolean>;
         dnssec-update-mode ( maintain | no-resign );
         dnssec-validation ( yes | no | auto );
+        dscp <integer>;
         dual-stack-servers [ port <integer> ] { ( <quoted_string> [ port
-            <integer> ] | <ipv4_address> [ port <integer> ] |
-            <ipv6_address> [ port <integer> ] ); ... };
+            <integer> ] [ dscp <integer> ] | <ipv4_address> [ port
+            <integer> ] [ dscp <integer> ] | <ipv6_address> [ port
+            <integer> ] [ dscp <integer> ] ); ... };
         dump-file <quoted_string>;
         edns-udp-size <integer>;
         empty-contact <string>;
@@ -134,13 +138,13 @@ options {
         fake-iquery <boolean>; // obsolete
         fetch-glue <boolean>; // obsolete
         files <size>;
-        filter-aaaa { <address_match_element>; ... }; // not configured
-        filter-aaaa-on-v4 <filter_aaaa>; // not configured
-        filter-aaaa-on-v6 <filter_aaaa>; // not configured
+        filter-aaaa { <address_match_element>; ... };
+        filter-aaaa-on-v4 <filter_aaaa>;
+        filter-aaaa-on-v6 <filter_aaaa>;
         flush-zones-on-shutdown <boolean>;
         forward ( first | only );
-        forwarders [ port <integer> ] { ( <ipv4_address> | <ipv6_address> )
-            [ port <integer> ]; ... };
+        forwarders [ port <integer> ] [ dscp <integer> ] { ( <ipv4_address>
+            | <ipv6_address> ) [ port <integer> ] [ dscp <integer> ]; ... };
         has-old-clients <boolean>; // obsolete
         heartbeat-interval <integer>;
         host-statistics <boolean>; // not implemented
@@ -151,8 +155,10 @@ options {
         ixfr-from-differences <ixfrdiff>;
         key-directory <quoted_string>;
         lame-ttl <integer>;
-        listen-on [ port <integer> ] { <address_match_element>; ... };
-        listen-on-v6 [ port <integer> ] { <address_match_element>; ... };
+        listen-on [ port <integer> ] [ dscp <integer> ] {
+            <address_match_element>; ... };
+        listen-on-v6 [ port <integer> ] [ dscp <integer> ] {
+            <address_match_element>; ... };
         maintain-ixfr-base <boolean>; // obsolete
         managed-keys-directory <quoted_string>;
         masterfile-format ( text | raw | map );
@@ -183,8 +189,10 @@ options {
         named-xfer <quoted_string>; // obsolete
         notify <notifytype>;
         notify-delay <integer>;
-        notify-source ( <ipv4_address> | * ) [ port ( <integer> | * ) ];
-        notify-source-v6 ( <ipv6_address> | * ) [ port ( <integer> | * ) ];
+        notify-source ( <ipv4_address> | * ) [ port ( <integer> | * ) ] [
+            dscp <integer> ];
+        notify-source-v6 ( <ipv6_address> | * ) [ port ( <integer> | * ) ]
+            [ dscp <integer> ];
         notify-to-soa <boolean>;
         nsec3-test-zone <boolean>; // test only
         pid-file ( <quoted_string> | none );
@@ -256,8 +264,10 @@ options {
         tkey-gssapi-keytab <quoted_string>;
         topology { <address_match_element>; ... }; // not implemented
         transfer-format ( many-answers | one-answer );
-        transfer-source ( <ipv4_address> | * ) [ port ( <integer> | * ) ];
-        transfer-source-v6 ( <ipv6_address> | * ) [ port ( <integer> | * ) ];
+        transfer-source ( <ipv4_address> | * ) [ port ( <integer> | * ) ] [
+            dscp <integer> ];
+        transfer-source-v6 ( <ipv6_address> | * ) [ port ( <integer> | * )
+            ] [ dscp <integer> ];
         transfers-in <integer>;
         transfers-out <integer>;
         transfers-per-ns <integer>;
@@ -282,16 +292,20 @@ server <netprefix> {
         edns-udp-size <integer>;
         keys <server_key>;
         max-udp-size <integer>;
-        notify-source ( <ipv4_address> | * ) [ port ( <integer> | * ) ];
-        notify-source-v6 ( <ipv6_address> | * ) [ port ( <integer> | * ) ];
+        notify-source ( <ipv4_address> | * ) [ port ( <integer> | * ) ] [
+            dscp <integer> ];
+        notify-source-v6 ( <ipv6_address> | * ) [ port ( <integer> | * ) ]
+            [ dscp <integer> ];
         provide-ixfr <boolean>;
         query-source <querysource4>;
         query-source-v6 <querysource6>;
         request-ixfr <boolean>;
         support-ixfr <boolean>; // obsolete
         transfer-format ( many-answers | one-answer );
-        transfer-source ( <ipv4_address> | * ) [ port ( <integer> | * ) ];
-        transfer-source-v6 ( <ipv6_address> | * ) [ port ( <integer> | * ) ];
+        transfer-source ( <ipv4_address> | * ) [ port ( <integer> | * ) ] [
+            dscp <integer> ];
+        transfer-source-v6 ( <ipv6_address> | * ) [ port ( <integer> | * )
+            ] [ dscp <integer> ];
         transfers <integer>;
 };
 
@@ -319,12 +333,13 @@ view <string> <optional_class> {
         allow-update { <address_match_element>; ... };
         allow-update-forwarding { <address_match_element>; ... };
         allow-v6-synthesis { <address_match_element>; ... }; // obsolete
-        also-notify [ port <integer> ] { ( <masters> | <ipv4_address> [
-            port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key
-            <string> ]; ... };
-        alt-transfer-source ( <ipv4_address> | * ) [ port ( <integer> | * ) ];
+        also-notify [ port <integer> ] [ dscp <integer> ] { ( <masters> |
+            <ipv4_address> [ port <integer> ] | <ipv6_address> [ port
+            <integer> ] ) [ key <string> ]; ... };
+        alt-transfer-source ( <ipv4_address> | * ) [ port ( <integer> | * )
+            ] [ dscp <integer> ];
         alt-transfer-source-v6 ( <ipv6_address> | * ) [ port ( <integer> |
-            * ) ];
+            * ) ] [ dscp <integer> ];
         attach-cache <string>;
         auth-nxdomain <boolean>; // default changed
         auto-dnssec ( allow | maintain | off );
@@ -372,19 +387,20 @@ view <string> <optional_class> {
         dnssec-update-mode ( maintain | no-resign );
         dnssec-validation ( yes | no | auto );
         dual-stack-servers [ port <integer> ] { ( <quoted_string> [ port
-            <integer> ] | <ipv4_address> [ port <integer> ] |
-            <ipv6_address> [ port <integer> ] ); ... };
+            <integer> ] [ dscp <integer> ] | <ipv4_address> [ port
+            <integer> ] [ dscp <integer> ] | <ipv6_address> [ port
+            <integer> ] [ dscp <integer> ] ); ... };
         edns-udp-size <integer>;
         empty-contact <string>;
         empty-server <string>;
         empty-zones-enable <boolean>;
         fetch-glue <boolean>; // obsolete
-        filter-aaaa { <address_match_element>; ... }; // not configured
-        filter-aaaa-on-v4 <filter_aaaa>; // not configured
-        filter-aaaa-on-v6 <filter_aaaa>; // not configured
+        filter-aaaa { <address_match_element>; ... };
+        filter-aaaa-on-v4 <filter_aaaa>;
+        filter-aaaa-on-v6 <filter_aaaa>;
         forward ( first | only );
-        forwarders [ port <integer> ] { ( <ipv4_address> | <ipv6_address> )
-            [ port <integer> ]; ... };
+        forwarders [ port <integer> ] [ dscp <integer> ] { ( <ipv4_address>
+            | <ipv6_address> ) [ port <integer> ] [ dscp <integer> ]; ... };
         inline-signing <boolean>;
         ixfr-from-differences <ixfrdiff>;
         key <string> {
@@ -421,8 +437,10 @@ view <string> <optional_class> {
         multi-master <boolean>;
         notify <notifytype>;
         notify-delay <integer>;
-        notify-source ( <ipv4_address> | * ) [ port ( <integer> | * ) ];
-        notify-source-v6 ( <ipv6_address> | * ) [ port ( <integer> | * ) ];
+        notify-source ( <ipv4_address> | * ) [ port ( <integer> | * ) ] [
+            dscp <integer> ];
+        notify-source-v6 ( <ipv6_address> | * ) [ port ( <integer> | * ) ]
+            [ dscp <integer> ];
         notify-to-soa <boolean>;
         nsec3-test-zone <boolean>; // test only
         preferred-glue <string>;
@@ -471,9 +489,9 @@ view <string> <optional_class> {
                 keys <server_key>;
                 max-udp-size <integer>;
                 notify-source ( <ipv4_address> | * ) [ port ( <integer> | *
-                    ) ];
+                    ) ] [ dscp <integer> ];
                 notify-source-v6 ( <ipv6_address> | * ) [ port ( <integer>
-                    | * ) ];
+                    | * ) ] [ dscp <integer> ];
                 provide-ixfr <boolean>;
                 query-source <querysource4>;
                 query-source-v6 <querysource6>;
@@ -481,9 +499,9 @@ view <string> <optional_class> {
                 support-ixfr <boolean>; // obsolete
                 transfer-format ( many-answers | one-answer );
                 transfer-source ( <ipv4_address> | * ) [ port ( <integer> |
-                    * ) ];
+                    * ) ] [ dscp <integer> ];
                 transfer-source-v6 ( <ipv6_address> | * ) [ port (
-                    <integer> | * ) ];
+                    <integer> | * ) ] [ dscp <integer> ];
                 transfers <integer>;
         };
         sig-signing-nodes <integer>;
@@ -494,8 +512,10 @@ view <string> <optional_class> {
         suppress-initial-notify <boolean>; // not yet implemented
         topology { <address_match_element>; ... }; // not implemented
         transfer-format ( many-answers | one-answer );
-        transfer-source ( <ipv4_address> | * ) [ port ( <integer> | * ) ];
-        transfer-source-v6 ( <ipv6_address> | * ) [ port ( <integer> | * ) ];
+        transfer-source ( <ipv4_address> | * ) [ port ( <integer> | * ) ] [
+            dscp <integer> ];
+        transfer-source-v6 ( <ipv6_address> | * ) [ port ( <integer> | * )
+            ] [ dscp <integer> ];
         trusted-keys { <string> <integer> <integer> <integer>
             <quoted_string>; ... };
         try-tcp-refresh <boolean>;
@@ -511,13 +531,14 @@ view <string> <optional_class> {
                 allow-transfer { <address_match_element>; ... };
                 allow-update { <address_match_element>; ... };
                 allow-update-forwarding { <address_match_element>; ... };
-                also-notify [ port <integer> ] { ( <masters> |
-                    <ipv4_address> [ port <integer> ] | <ipv6_address> [
-                    port <integer> ] ) [ key <string> ]; ... };
+                also-notify [ port <integer> ] [ dscp <integer> ] { (
+                    <masters> | <ipv4_address> [ port <integer> ] |
+                    <ipv6_address> [ port <integer> ] ) [ key <string> ];
+                    ... };
                 alt-transfer-source ( <ipv4_address> | * ) [ port (
-                    <integer> | * ) ];
+                    <integer> | * ) ] [ dscp <integer> ];
                 alt-transfer-source-v6 ( <ipv6_address> | * ) [ port (
-                    <integer> | * ) ];
+                    <integer> | * ) ] [ dscp <integer> ];
                 auto-dnssec ( allow | maintain | off );
                 check-dup-records ( fail | warn | ignore );
                 check-integrity <boolean>;
@@ -537,8 +558,9 @@ view <string> <optional_class> {
                 dnssec-update-mode ( maintain | no-resign );
                 file <quoted_string>;
                 forward ( first | only );
-                forwarders [ port <integer> ] { ( <ipv4_address> |
-                    <ipv6_address> ) [ port <integer> ]; ... };
+                forwarders [ port <integer> ] [ dscp <integer> ] { (
+                    <ipv4_address> | <ipv6_address> ) [ port <integer> ] [
+                    dscp <integer> ]; ... };
                 inline-signing <boolean>;
                 ixfr-base <quoted_string>; // obsolete
                 ixfr-from-differences <boolean>;
@@ -547,9 +569,9 @@ view <string> <optional_class> {
                 key-directory <quoted_string>;
                 maintain-ixfr-base <boolean>; // obsolete
                 masterfile-format ( text | raw | map );
-                masters [ port <integer> ] { ( <masters> | <ipv4_address> [
-                    port <integer> ] | <ipv6_address> [ port <integer> ] )
-                    [ key <string> ]; ... };
+                masters [ port <integer> ] [ dscp <integer> ] { ( <masters>
+                    | <ipv4_address> [ port <integer> ] | <ipv6_address> [
+                    port <integer> ] ) [ key <string> ]; ... };
                 max-ixfr-log-size <size>; // obsolete
                 max-journal-size <size_no_default>;
                 max-refresh-time <integer>;
@@ -564,9 +586,9 @@ view <string> <optional_class> {
                 notify <notifytype>;
                 notify-delay <integer>;
                 notify-source ( <ipv4_address> | * ) [ port ( <integer> | *
-                    ) ];
+                    ) ] [ dscp <integer> ];
                 notify-source-v6 ( <ipv6_address> | * ) [ port ( <integer>
-                    | * ) ];
+                    | * ) ] [ dscp <integer> ];
                 notify-to-soa <boolean>;
                 nsec3-test-zone <boolean>; // test only
                 pubkey <integer> <integer> <integer>
@@ -581,9 +603,9 @@ view <string> <optional_class> {
                 sig-signing-type <integer>;
                 sig-validity-interval <integer> [ <integer> ];
                 transfer-source ( <ipv4_address> | * ) [ port ( <integer> |
-                    * ) ];
+                    * ) ] [ dscp <integer> ];
                 transfer-source-v6 ( <ipv6_address> | * ) [ port (
-                    <integer> | * ) ];
+                    <integer> | * ) ] [ dscp <integer> ];
                 try-tcp-refresh <boolean>;
                 type ( master | slave | stub | static-stub | hint | forward
                     | delegation-only | redirect );
@@ -607,12 +629,13 @@ zone <string> <optional_class> {
         allow-transfer { <address_match_element>; ... };
         allow-update { <address_match_element>; ... };
         allow-update-forwarding { <address_match_element>; ... };
-        also-notify [ port <integer> ] { ( <masters> | <ipv4_address> [
-            port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key
-            <string> ]; ... };
-        alt-transfer-source ( <ipv4_address> | * ) [ port ( <integer> | * ) ];
+        also-notify [ port <integer> ] [ dscp <integer> ] { ( <masters> |
+            <ipv4_address> [ port <integer> ] | <ipv6_address> [ port
+            <integer> ] ) [ key <string> ]; ... };
+        alt-transfer-source ( <ipv4_address> | * ) [ port ( <integer> | * )
+            ] [ dscp <integer> ];
         alt-transfer-source-v6 ( <ipv6_address> | * ) [ port ( <integer> |
-            * ) ];
+            * ) ] [ dscp <integer> ];
         auto-dnssec ( allow | maintain | off );
         check-dup-records ( fail | warn | ignore );
         check-integrity <boolean>;
@@ -632,8 +655,8 @@ zone <string> <optional_class> {
         dnssec-update-mode ( maintain | no-resign );
         file <quoted_string>;
         forward ( first | only );
-        forwarders [ port <integer> ] { ( <ipv4_address> | <ipv6_address> )
-            [ port <integer> ]; ... };
+        forwarders [ port <integer> ] [ dscp <integer> ] { ( <ipv4_address>
+            | <ipv6_address> ) [ port <integer> ] [ dscp <integer> ]; ... };
         inline-signing <boolean>;
         ixfr-base <quoted_string>; // obsolete
         ixfr-from-differences <boolean>;
@@ -642,9 +665,9 @@ zone <string> <optional_class> {
         key-directory <quoted_string>;
         maintain-ixfr-base <boolean>; // obsolete
         masterfile-format ( text | raw | map );
-        masters [ port <integer> ] { ( <masters> | <ipv4_address> [ port
-            <integer> ] | <ipv6_address> [ port <integer> ] ) [ key
-            <string> ]; ... };
+        masters [ port <integer> ] [ dscp <integer> ] { ( <masters> |
+            <ipv4_address> [ port <integer> ] | <ipv6_address> [ port
+            <integer> ] ) [ key <string> ]; ... };
         max-ixfr-log-size <size>; // obsolete
         max-journal-size <size_no_default>;
         max-refresh-time <integer>;
@@ -658,8 +681,10 @@ zone <string> <optional_class> {
         multi-master <boolean>;
         notify <notifytype>;
         notify-delay <integer>;
-        notify-source ( <ipv4_address> | * ) [ port ( <integer> | * ) ];
-        notify-source-v6 ( <ipv6_address> | * ) [ port ( <integer> | * ) ];
+        notify-source ( <ipv4_address> | * ) [ port ( <integer> | * ) ] [
+            dscp <integer> ];
+        notify-source-v6 ( <ipv6_address> | * ) [ port ( <integer> | * ) ]
+            [ dscp <integer> ];
         notify-to-soa <boolean>;
         nsec3-test-zone <boolean>; // test only
         pubkey <integer> <integer> <integer> <quoted_string>; // obsolete
@@ -672,8 +697,10 @@ zone <string> <optional_class> {
         sig-signing-signatures <integer>;
         sig-signing-type <integer>;
         sig-validity-interval <integer> [ <integer> ];
-        transfer-source ( <ipv4_address> | * ) [ port ( <integer> | * ) ];
-        transfer-source-v6 ( <ipv6_address> | * ) [ port ( <integer> | * ) ];
+        transfer-source ( <ipv4_address> | * ) [ port ( <integer> | * ) ] [
+            dscp <integer> ];
+        transfer-source-v6 ( <ipv6_address> | * ) [ port ( <integer> | * )
+            ] [ dscp <integer> ];
         try-tcp-refresh <boolean>;
         type ( master | slave | stub | static-stub | hint | forward |
             delegation-only | redirect );
index a7041ff2f84760d9e89e92f63643dd55a325fe4a..b5658a192c57d50262270171b9c1fed0d5db7366 100644 (file)
@@ -747,6 +747,28 @@ typedef enum {
        optlevel_zone
 } optlevel_t;
 
+static isc_result_t
+check_dscp(const cfg_obj_t *options, isc_log_t *logctx) {
+       isc_result_t result = ISC_R_SUCCESS;
+       const cfg_obj_t *obj = NULL;
+
+       /*
+       * Check that DSCP setting is within range
+       */
+       obj = NULL;
+       (void)cfg_map_get(options, "dscp", &obj);
+       if (obj != NULL) {
+              isc_uint32_t dscp = cfg_obj_asuint32(obj);
+              if (dscp >= 64) {
+                      cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
+                                  "'dscp' out of range (0-63)");
+                      result = ISC_R_FAILURE;
+              }
+       }
+
+       return (result);
+}
+
 static isc_result_t
 check_options(const cfg_obj_t *options, isc_log_t *logctx, isc_mem_t *mctx,
              optlevel_t optlevel)
@@ -1128,6 +1150,10 @@ check_options(const cfg_obj_t *options, isc_log_t *logctx, isc_mem_t *mctx,
                result = ISC_R_FAILURE;
        }
 
+       tresult = check_dscp(options, logctx);
+       if (tresult != ISC_R_SUCCESS)
+               result = tresult;
+
        return (result);
 }
 
index f3ab6d3e9872885cf27a27b04ece7ccfe47857f7..8c10f99be1ec88cef5d34a3213c6d8de09e26f94 100644 (file)
@@ -1946,6 +1946,7 @@ new_adbaddrinfo(dns_adb_t *adb, dns_adbentry_t *entry, in_port_t port) {
        ai->srtt = entry->srtt;
        ai->flags = entry->flags;
        ai->entry = entry;
+       ai->dscp = -1;
        ISC_LINK_INIT(ai, publink);
 
        return (ai);
index 96684a379f1e40edf56f14134999c45939d9de01..bf9597048537c89816edcfb0112b021ec3ae18fc 100644 (file)
@@ -228,6 +228,7 @@ struct dns_dispatch {
        isc_socket_t           *socket;         /*%< isc socket attached to */
        isc_sockaddr_t          local;          /*%< local address */
        in_port_t               localport;      /*%< local UDP port */
+       isc_dscp_t              dscp;           /*%< "listen-on" DSCP value */
        unsigned int            maxrequests;    /*%< max requests */
        isc_event_t            *ctlevent;
 
@@ -2624,6 +2625,7 @@ dispatch_allocate(dns_dispatchmgr_t *mgr, unsigned int maxrequests,
        dispatch_initrandom(&disp->arc4ctx, mgr->entropy, NULL);
        disp->port_table = NULL;
        disp->portpool = NULL;
+       disp->dscp = -1;
 
        result = isc_mutex_init(&disp->lock);
        if (result != ISC_R_SUCCESS)
@@ -3863,6 +3865,18 @@ dns_dispatchset_destroy(dns_dispatchset_t **dsetp) {
        *dsetp = NULL;
 }
 
+void
+dns_dispatch_setdscp(dns_dispatch_t *disp, isc_dscp_t dscp) {
+       REQUIRE(VALID_DISPATCH(disp));
+       disp->dscp = dscp;
+}
+
+isc_dscp_t
+dns_dispatch_getdscp(dns_dispatch_t *disp) {
+       REQUIRE(VALID_DISPATCH(disp));
+       return (disp->dscp);
+}
+
 #if 0
 void
 dns_dispatchmgr_dump(dns_dispatchmgr_t *mgr) {
index 7ec4e5c9debbc25f3812d8836cf4f5b7d5d11ba9..9a3105b642c6acd79a206af5d5f123591276c141 100644 (file)
@@ -83,13 +83,63 @@ dns_fwdtable_create(isc_mem_t *mctx, dns_fwdtable_t **fwdtablep) {
        return (result);
 }
 
+isc_result_t
+dns_fwdtable_addfwd(dns_fwdtable_t *fwdtable, dns_name_t *name,
+                   dns_forwarderlist_t *fwdrs, dns_fwdpolicy_t fwdpolicy)
+{
+       isc_result_t result;
+       dns_forwarders_t *forwarders;
+       dns_forwarder_t *fwd, *nfwd;
+
+       REQUIRE(VALID_FWDTABLE(fwdtable));
+
+       forwarders = isc_mem_get(fwdtable->mctx, sizeof(dns_forwarders_t));
+       if (forwarders == NULL)
+               return (ISC_R_NOMEMORY);
+
+       ISC_LIST_INIT(forwarders->fwdrs);
+       for (fwd = ISC_LIST_HEAD(*fwdrs);
+            fwd != NULL;
+            fwd = ISC_LIST_NEXT(fwd, link))
+       {
+               nfwd = isc_mem_get(fwdtable->mctx, sizeof(dns_forwarder_t));
+               if (nfwd == NULL) {
+                       result = ISC_R_NOMEMORY;
+                       goto cleanup;
+               }
+               *nfwd = *fwd;
+               ISC_LINK_INIT(nfwd, link);
+               ISC_LIST_APPEND(forwarders->fwdrs, nfwd, link);
+       }
+       forwarders->fwdpolicy = fwdpolicy;
+
+       RWLOCK(&fwdtable->rwlock, isc_rwlocktype_write);
+       result = dns_rbt_addname(fwdtable->table, name, forwarders);
+       RWUNLOCK(&fwdtable->rwlock, isc_rwlocktype_write);
+
+       if (result != ISC_R_SUCCESS)
+               goto cleanup;
+
+       return (ISC_R_SUCCESS);
+
+ cleanup:
+       while (!ISC_LIST_EMPTY(forwarders->fwdrs)) {
+               fwd = ISC_LIST_HEAD(forwarders->fwdrs);
+               ISC_LIST_UNLINK(forwarders->fwdrs, fwd, link);
+               isc_mem_put(fwdtable->mctx, fwd, sizeof(isc_sockaddr_t));
+       }
+       isc_mem_put(fwdtable->mctx, forwarders, sizeof(dns_forwarders_t));
+       return (result);
+}
+
 isc_result_t
 dns_fwdtable_add(dns_fwdtable_t *fwdtable, dns_name_t *name,
                 isc_sockaddrlist_t *addrs, dns_fwdpolicy_t fwdpolicy)
 {
        isc_result_t result;
        dns_forwarders_t *forwarders;
-       isc_sockaddr_t *sa, *nsa;
+       dns_forwarder_t *fwd;
+       isc_sockaddr_t *sa;
 
        REQUIRE(VALID_FWDTABLE(fwdtable));
 
@@ -97,19 +147,20 @@ dns_fwdtable_add(dns_fwdtable_t *fwdtable, dns_name_t *name,
        if (forwarders == NULL)
                return (ISC_R_NOMEMORY);
 
-       ISC_LIST_INIT(forwarders->addrs);
+       ISC_LIST_INIT(forwarders->fwdrs);
        for (sa = ISC_LIST_HEAD(*addrs);
             sa != NULL;
             sa = ISC_LIST_NEXT(sa, link))
        {
-               nsa = isc_mem_get(fwdtable->mctx, sizeof(isc_sockaddr_t));
-               if (nsa == NULL) {
+               fwd = isc_mem_get(fwdtable->mctx, sizeof(dns_forwarder_t));
+               if (fwd == NULL) {
                        result = ISC_R_NOMEMORY;
                        goto cleanup;
                }
-               *nsa = *sa;
-               ISC_LINK_INIT(nsa, link);
-               ISC_LIST_APPEND(forwarders->addrs, nsa, link);
+               fwd->addr = *sa;
+               fwd->dscp = -1;
+               ISC_LINK_INIT(fwd, link);
+               ISC_LIST_APPEND(forwarders->fwdrs, fwd, link);
        }
        forwarders->fwdpolicy = fwdpolicy;
 
@@ -123,10 +174,10 @@ dns_fwdtable_add(dns_fwdtable_t *fwdtable, dns_name_t *name,
        return (ISC_R_SUCCESS);
 
  cleanup:
-       while (!ISC_LIST_EMPTY(forwarders->addrs)) {
-               sa = ISC_LIST_HEAD(forwarders->addrs);
-               ISC_LIST_UNLINK(forwarders->addrs, sa, link);
-               isc_mem_put(fwdtable->mctx, sa, sizeof(isc_sockaddr_t));
+       while (!ISC_LIST_EMPTY(forwarders->fwdrs)) {
+               fwd = ISC_LIST_HEAD(forwarders->fwdrs);
+               ISC_LIST_UNLINK(forwarders->fwdrs, fwd, link);
+               isc_mem_put(fwdtable->mctx, fwd, sizeof(dns_forwarder_t));
        }
        isc_mem_put(fwdtable->mctx, forwarders, sizeof(dns_forwarders_t));
        return (result);
@@ -202,14 +253,14 @@ static void
 auto_detach(void *data, void *arg) {
        dns_forwarders_t *forwarders = data;
        dns_fwdtable_t *fwdtable = arg;
-       isc_sockaddr_t *sa;
+       dns_forwarder_t *fwd;
 
        UNUSED(arg);
 
-       while (!ISC_LIST_EMPTY(forwarders->addrs)) {
-               sa = ISC_LIST_HEAD(forwarders->addrs);
-               ISC_LIST_UNLINK(forwarders->addrs, sa, link);
-               isc_mem_put(fwdtable->mctx, sa, sizeof(isc_sockaddr_t));
+       while (!ISC_LIST_EMPTY(forwarders->fwdrs)) {
+               fwd = ISC_LIST_HEAD(forwarders->fwdrs);
+               ISC_LIST_UNLINK(forwarders->fwdrs, fwd, link);
+               isc_mem_put(fwdtable->mctx, fwd, sizeof(dns_forwarder_t));
        }
        isc_mem_put(fwdtable->mctx, forwarders, sizeof(dns_forwarders_t));
 }
index a5a312406affad0eaa7f0cf392b0a7e7e5f41223..92a46d4ba2e6006a7ea6cf2a6e05814c9817eeff 100644 (file)
@@ -214,7 +214,9 @@ struct dns_adbaddrinfo {
        unsigned int                    magic;          /*%< private */
 
        isc_sockaddr_t                  sockaddr;       /*%< [rw] */
-       unsigned int                    srtt;           /*%< [rw] microseconds */
+       unsigned int                    srtt;           /*%< [rw] microsecs */
+       isc_dscp_t                      dscp;
+
        unsigned int                    flags;          /*%< [rw] */
        dns_adbentry_t                 *entry;          /*%< private */
        ISC_LINK(dns_adbaddrinfo_t)     publink;
index 1235f7ca40f3952e638d3944e0189f618efd5877..d369c9cf649eedc3877c63707761623cd5abd9b7 100644 (file)
@@ -558,6 +558,18 @@ dns_dispatchset_destroy(dns_dispatchset_t **dsetp);
  *\li  dset is valid
  */
 
+void
+dns_dispatch_setdscp(dns_dispatch_t *disp, isc_dscp_t dscp);
+isc_dscp_t
+dns_dispatch_getdscp(dns_dispatch_t *disp);
+/*%<
+ * Set/get the DSCP value to be used when sending responses to clients,
+ * as defined in the "listen-on" or "listen-on-v6" statements.
+ *
+ * Requires:
+ *\li  disp is valid.
+ */
+
 ISC_LANG_ENDDECLS
 
 #endif /* DNS_DISPATCH_H */
index 23e94be7894e7a887509a9ed6ccffd9327eb54d4..b666d01ce79831185e692d632066bd71b839af28 100644 (file)
 
 ISC_LANG_BEGINDECLS
 
+struct dns_forwarder {
+       isc_sockaddr_t                  addr;
+       isc_dscp_t                      dscp;
+       ISC_LINK(dns_forwarder_t)       link;
+};
+
+typedef ISC_LIST(struct dns_forwarder) dns_forwarderlist_t;
+
 struct dns_forwarders {
-       isc_sockaddrlist_t      addrs;
+       dns_forwarderlist_t     fwdrs;
        dns_fwdpolicy_t         fwdpolicy;
 };
 
@@ -49,17 +57,22 @@ dns_fwdtable_create(isc_mem_t *mctx, dns_fwdtable_t **fwdtablep);
  */
 
 isc_result_t
+dns_fwdtable_addfwd(dns_fwdtable_t *fwdtable, dns_name_t *name,
+                   dns_forwarderlist_t *fwdrs, dns_fwdpolicy_t policy);
+isc_result_t
 dns_fwdtable_add(dns_fwdtable_t *fwdtable, dns_name_t *name,
                 isc_sockaddrlist_t *addrs, dns_fwdpolicy_t policy);
 /*%<
  * Adds an entry to the forwarding table.  The entry associates
  * a domain with a list of forwarders and a forwarding policy.  The
- * addrs list is copied if not empty, so the caller should free its copy.
+ * addrs/fwdrs list is copied if not empty, so the caller should free
+ * its copy.
  *
  * Requires:
  * \li fwdtable is a valid forwarding table.
  * \li name is a valid name
- * \li addrs is a valid list of sockaddrs, which may be empty.
+ * \li addrs/fwdrs is a valid list of isc_sockaddr/dns_forwarder
+ *      structures, which may be empty.
  *
  * Returns:
  * \li #ISC_R_SUCCESS
index 86324a3d70217c4606cb9423361fb5faaf3f392b..6665174bb43d550c76036b97b599865b1e99ee2d 100644 (file)
@@ -76,8 +76,11 @@ struct dns_peer {
        isc_boolean_t           request_nsid;
        dns_name_t             *key;
        isc_sockaddr_t         *transfer_source;
+       isc_dscp_t              transfer_dscp;
        isc_sockaddr_t         *notify_source;
+       isc_dscp_t              notify_dscp;
        isc_sockaddr_t         *query_source;
+       isc_dscp_t              query_dscp;
        isc_uint16_t            udpsize;                /* receive size */
        isc_uint16_t            maxudp;                 /* transmit size */
 
@@ -214,6 +217,23 @@ dns_peer_setquerysource(dns_peer_t *peer, const isc_sockaddr_t *query_source);
 isc_result_t
 dns_peer_getquerysource(dns_peer_t *peer, isc_sockaddr_t *query_source);
 
+isc_result_t
+dns_peer_setnotifydscp(dns_peer_t *peer, isc_dscp_t dscp);
+
+isc_result_t
+dns_peer_getnotifydscp(dns_peer_t *peer, isc_dscp_t *dscpp);
+
+isc_result_t
+dns_peer_settransferdscp(dns_peer_t *peer, isc_dscp_t dscp);
+
+isc_result_t
+dns_peer_gettransferdscp(dns_peer_t *peer, isc_dscp_t *dscpp);
+
+isc_result_t
+dns_peer_setquerydscp(dns_peer_t *peer, isc_dscp_t dscp);
+
+isc_result_t
+dns_peer_getquerydscp(dns_peer_t *peer, isc_dscp_t *dscpp);
 ISC_LANG_ENDDECLS
 
 #endif /* DNS_PEER_H */
index 8c792ddd57747cf34291ddc1554697d7a35b5be1..43cec7e56b7e5fb835a1bcdda91b5d8e16c4c133 100644 (file)
@@ -195,7 +195,7 @@ dns_request_create(dns_requestmgr_t *requestmgr, dns_message_t *message,
  *\li  requestp != NULL && *requestp == NULL
  */
 
-/*% See dns_request_createvia3() */
+/*% See dns_request_createvia4() */
 isc_result_t
 dns_request_createvia(dns_requestmgr_t *requestmgr, dns_message_t *message,
                      isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
@@ -204,7 +204,7 @@ dns_request_createvia(dns_requestmgr_t *requestmgr, dns_message_t *message,
                      isc_taskaction_t action, void *arg,
                      dns_request_t **requestp);
 
-/*% See dns_request_createvia3() */
+/*% See dns_request_createvia4() */
 isc_result_t
 dns_request_createvia2(dns_requestmgr_t *requestmgr, dns_message_t *message,
                       isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
@@ -213,6 +213,7 @@ dns_request_createvia2(dns_requestmgr_t *requestmgr, dns_message_t *message,
                       isc_task_t *task, isc_taskaction_t action, void *arg,
                       dns_request_t **requestp);
 
+/*% See dns_request_createvia4() */
 isc_result_t
 dns_request_createvia3(dns_requestmgr_t *requestmgr, dns_message_t *message,
                       isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
@@ -221,6 +222,15 @@ dns_request_createvia3(dns_requestmgr_t *requestmgr, dns_message_t *message,
                       unsigned int udpretries, isc_task_t *task,
                       isc_taskaction_t action, void *arg,
                       dns_request_t **requestp);
+
+isc_result_t
+dns_request_createvia4(dns_requestmgr_t *requestmgr, dns_message_t *message,
+                      isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
+                      isc_dscp_t dscp, unsigned int options,
+                      dns_tsigkey_t *key, unsigned int timeout,
+                      unsigned int udptimeout, unsigned int udpretries, 
+                      isc_task_t *task, isc_taskaction_t action, void *arg,
+                      dns_request_t **requestp);
 /*%<
  * Create and send a request.
  *
@@ -254,7 +264,7 @@ dns_request_createvia3(dns_requestmgr_t *requestmgr, dns_message_t *message,
  *\li  requestp != NULL && *requestp == NULL
  */
 
-/*% See dns_request_createraw3() */
+/*% See dns_request_createraw4() */
 isc_result_t
 dns_request_createraw(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf,
                      isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
@@ -262,7 +272,7 @@ dns_request_createraw(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf,
                      isc_task_t *task, isc_taskaction_t action, void *arg,
                      dns_request_t **requestp);
 
-/*% See dns_request_createraw3() */
+/*% See dns_request_createraw4() */
 isc_result_t
 dns_request_createraw2(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf,
                       isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
@@ -271,6 +281,7 @@ dns_request_createraw2(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf,
                       isc_taskaction_t action, void *arg,
                       dns_request_t **requestp);
 
+/*% See dns_request_createraw4() */
 isc_result_t
 dns_request_createraw3(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf,
                       isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
@@ -278,6 +289,15 @@ dns_request_createraw3(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf,
                       unsigned int udptimeout, unsigned int udpretries,
                       isc_task_t *task, isc_taskaction_t action, void *arg,
                       dns_request_t **requestp);
+
+isc_result_t
+dns_request_createraw4(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf,
+                      isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
+                      isc_dscp_t dscp, unsigned int options,
+                      unsigned int timeout, unsigned int udptimeout,
+                      unsigned int udpretries, isc_task_t *task,
+                      isc_taskaction_t action, void *arg,
+                      dns_request_t **requestp);
 /*!<
  * \brief Create and send a request.
  *
index b96724fb75bc09760a0f026e85216c66c4976c38..9c03be7ad67a8c91fd1d491173a62d1d0b453c8b 100644 (file)
@@ -598,6 +598,23 @@ dns_resolver_printbadcache(dns_resolver_t *resolver, FILE *fp);
  * \li resolver to be valid.
  */
 
+void
+dns_resolver_setquerydscp4(dns_resolver_t *resolver, isc_dscp_t dscp);
+isc_dscp_t
+dns_resolver_getquerydscp4(dns_resolver_t *resolver);
+
+void
+dns_resolver_setquerydscp6(dns_resolver_t *resolver, isc_dscp_t dscp);
+isc_dscp_t
+dns_resolver_getquerydscp6(dns_resolver_t *resolver);
+/*%
+ * Get and set the DSCP values for the resolver's IPv4 and IPV6 query
+ * sources.
+ *
+ * Requires:
+ * \li resolver to be valid.
+ */
+
 ISC_LANG_ENDDECLS
 
 #endif /* DNS_RESOLVER_H */
index c5bda694ae23fdf06405b448ef34b7590d1607b0..894dc17b0d32c0ce1ad54dbac60802a7f9d8d7c7 100644 (file)
@@ -80,6 +80,7 @@ typedef struct dns_dumpctx                    dns_dumpctx_t;
 typedef struct dns_fetch                       dns_fetch_t;
 typedef struct dns_fixedname                   dns_fixedname_t;
 typedef struct dns_forwarders                  dns_forwarders_t;
+typedef struct dns_forwarder                   dns_forwarder_t;
 typedef struct dns_fwdtable                    dns_fwdtable_t;
 typedef struct dns_iptable                     dns_iptable_t;
 typedef isc_uint32_t                           dns_iterations_t;
index 2f20c35f4d05bcb0030d24b34ef58e27ca406eac..8ec42c4332ac75eefb2755cf89f1b699ddaa95c2 100644 (file)
@@ -67,6 +67,14 @@ dns_xfrin_create2(dns_zone_t *zone, dns_rdatatype_t xfrtype,
                  isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr,
                  isc_task_t *task, dns_xfrindone_t done,
                  dns_xfrin_ctx_t **xfrp);
+
+isc_result_t
+dns_xfrin_create3(dns_zone_t *zone, dns_rdatatype_t xfrtype,
+                 isc_sockaddr_t *masteraddr, isc_sockaddr_t *sourceaddr,
+                 isc_dscp_t dscp, dns_tsigkey_t *tsigkey, isc_mem_t *mctx,
+                 isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr,
+                 isc_task_t *task, dns_xfrindone_t done,
+                 dns_xfrin_ctx_t **xfrp);
 /*%<
  * Attempt to start an incoming zone transfer of 'zone'
  * from 'masteraddr', creating a dns_xfrin_ctx_t object to
index e6806e8df595aea3f91a1c5bf96600a2ff403b54..4c6198203b853b943bfcd2e28240be8d67328fe6 100644 (file)
@@ -597,7 +597,11 @@ dns_zone_setalsonotify(dns_zone_t *zone, const isc_sockaddr_t *notify,
                       isc_uint32_t count);
 isc_result_t
 dns_zone_setalsonotifywithkeys(dns_zone_t *zone, const isc_sockaddr_t *notify,
-                                                          dns_name_t **keynames, isc_uint32_t count);
+                              dns_name_t **keynames, isc_uint32_t count);
+isc_result_t
+dns_zone_setalsonotifydscpkeys(dns_zone_t *zone, const isc_sockaddr_t *notify,
+                              const isc_dscp_t *dscps, dns_name_t **keynames,
+                              isc_uint32_t count);
 /*%<
  *     Set the list of additional servers to be notified when
  *     a zone changes.  To clear the list use 'count = 0'.
@@ -730,6 +734,32 @@ dns_zone_getaltxfrsource4(dns_zone_t *zone);
  *\li  'zone' to be a valid zone.
  */
 
+isc_result_t
+dns_zone_setxfrsource4dscp(dns_zone_t *zone, isc_dscp_t dscp);
+isc_result_t
+dns_zone_setaltxfrsource4dscp(dns_zone_t *zone, isc_dscp_t dscp);
+/*%<
+ * Set the DSCP value associated with the transfer/alt-transfer source.
+ *
+ * Require:
+ *\li  'zone' to be a valid zone.
+ *
+ * Returns:
+ *\li  #ISC_R_SUCCESS
+ */
+
+isc_dscp_t
+dns_zone_getxfrsource4dscp(dns_zone_t *zone);
+isc_dscp_t
+dns_zone_getaltxfrsource4dscp(dns_zone_t *zone);
+/*%/
+ * Get the DSCP value associated with the transfer/alt-transfer source.
+ *
+ * Require:
+ *\li  'zone' to be a valid zone.
+ */
+
+
 isc_result_t
 dns_zone_setxfrsource6(dns_zone_t *zone, const isc_sockaddr_t *xfrsource);
 isc_result_t
@@ -758,6 +788,31 @@ dns_zone_getaltxfrsource6(dns_zone_t *zone);
  *\li  'zone' to be a valid zone.
  */
 
+isc_dscp_t
+dns_zone_getxfrsource6dscp(dns_zone_t *zone);
+isc_dscp_t
+dns_zone_getaltxfrsource6dscp(dns_zone_t *zone);
+/*%/
+ * Get the DSCP value associated with the transfer/alt-transfer source.
+ *
+ * Require:
+ *\li  'zone' to be a valid zone.
+ */
+
+isc_result_t
+dns_zone_setxfrsource6dscp(dns_zone_t *zone, isc_dscp_t dscp);
+isc_result_t
+dns_zone_setaltxfrsource6dscp(dns_zone_t *zone, isc_dscp_t dscp);
+/*%<
+ * Set the DSCP value associated with the transfer/alt-transfer source.
+ *
+ * Require:
+ *\li  'zone' to be a valid zone.
+ *
+ * Returns:
+ *\li  #ISC_R_SUCCESS
+ */
+
 isc_result_t
 dns_zone_setnotifysrc4(dns_zone_t *zone, const isc_sockaddr_t *notifysrc);
 /*%<
@@ -781,6 +836,36 @@ dns_zone_getnotifysrc4(dns_zone_t *zone);
  *\li  'zone' to be a valid zone.
  */
 
+isc_dscp_t
+dns_zone_getnotifysrc4dscp(dns_zone_t *zone);
+/*%/
+ * Get the DCSP value associated with the notify source.
+ *
+ * Require:
+ *\li  'zone' to be a valid zone.
+ */
+
+isc_result_t
+dns_zone_setnotifysrc4dscp(dns_zone_t *zone, isc_dscp_t dscp);
+/*%<
+ * Set the DSCP value associated with the notify source.
+ *
+ * Require:
+ *\li  'zone' to be a valid zone.
+ *
+ * Returns:
+ *\li  #ISC_R_SUCCESS
+ */
+
+isc_dscp_t
+dns_zone_getnotifysrc4dscp(dns_zone_t *zone);
+/*%/
+ * Get the DSCP value associated with the notify source.
+ *
+ * Require:
+ *\li  'zone' to be a valid zone.
+ */
+
 isc_result_t
 dns_zone_setnotifysrc6(dns_zone_t *zone, const isc_sockaddr_t *notifysrc);
 /*%<
@@ -804,6 +889,36 @@ dns_zone_getnotifysrc6(dns_zone_t *zone);
  *\li  'zone' to be a valid zone.
  */
 
+isc_dscp_t
+dns_zone_getnotifysrc6dscp(dns_zone_t *zone);
+/*%/
+ * Get the DCSP value associated with the notify source.
+ *
+ * Require:
+ *\li  'zone' to be a valid zone.
+ */
+
+isc_result_t
+dns_zone_setnotifysrc6dscp(dns_zone_t *zone, isc_dscp_t dscp);
+/*%<
+ * Set the DSCP value associated with the notify source.
+ *
+ * Require:
+ *\li  'zone' to be a valid zone.
+ *
+ * Returns:
+ *\li  #ISC_R_SUCCESS
+ */
+
+isc_dscp_t
+dns_zone_getnotifysrc6dscp(dns_zone_t *zone);
+/*%/
+ * Get the DSCP value associated with the notify source.
+ *
+ * Require:
+ *\li  'zone' to be a valid zone.
+ */
+
 void
 dns_zone_setnotifyacl(dns_zone_t *zone, dns_acl_t *acl);
 /*%<
index ec9e08cb27b7616ea0cf85dd4ae7d982ca92a2f2..9c75b13b9df94c8f13855f59b0ac8c07cf1df814 100644 (file)
@@ -710,3 +710,57 @@ dns_peer_getmaxudp(dns_peer_t *peer, isc_uint16_t *maxudp) {
                return (ISC_R_NOTFOUND);
        }
 }
+
+isc_result_t
+dns_peer_setnotifydscp(dns_peer_t *peer, isc_dscp_t dscp) {
+       REQUIRE(DNS_PEER_VALID(peer));
+       REQUIRE(dscp < 64);
+
+       peer->notify_dscp = dscp;
+       return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_peer_getnotifydscp(dns_peer_t *peer, isc_dscp_t *dscpp) {
+       REQUIRE(DNS_PEER_VALID(peer));
+       REQUIRE(dscpp != NULL);
+
+       *dscpp = peer->notify_dscp;
+       return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_peer_settransferdscp(dns_peer_t *peer, isc_dscp_t dscp) {
+       REQUIRE(DNS_PEER_VALID(peer));
+       REQUIRE(dscp < 64);
+
+       peer->transfer_dscp = dscp;
+       return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_peer_gettransferdscp(dns_peer_t *peer, isc_dscp_t *dscpp) {
+       REQUIRE(DNS_PEER_VALID(peer));
+       REQUIRE(dscpp != NULL);
+
+       *dscpp = peer->transfer_dscp;
+       return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_peer_setquerydscp(dns_peer_t *peer, isc_dscp_t dscp) {
+       REQUIRE(DNS_PEER_VALID(peer));
+       REQUIRE(dscp < 64);
+
+       peer->query_dscp = dscp;
+       return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_peer_getquerydscp(dns_peer_t *peer, isc_dscp_t *dscpp) {
+       REQUIRE(DNS_PEER_VALID(peer));
+       REQUIRE(dscpp != NULL);
+
+       *dscpp = peer->query_dscp;
+       return (ISC_R_SUCCESS);
+}
index 1316e69941106ee7e9b665a047763d3596be1f72..9b32a41506cc459298bb92a9d321e07f023c0113 100644 (file)
@@ -89,6 +89,7 @@ struct dns_request {
        isc_boolean_t                   canceling; /* ctlevent outstanding */
        isc_sockaddr_t                  destaddr;
        unsigned int                    udpcount;
+       isc_dscp_t                      dscp;
 };
 
 #define DNS_REQUEST_F_CONNECTING 0x0001
@@ -427,6 +428,7 @@ static inline isc_result_t
 req_send(dns_request_t *request, isc_task_t *task, isc_sockaddr_t *address) {
        isc_region_t r;
        isc_socket_t *socket;
+       isc_socketevent_t *sendevent;
        isc_result_t result;
 
        req_log(ISC_LOG_DEBUG(3), "req_send: request %p", request);
@@ -439,8 +441,19 @@ req_send(dns_request_t *request, isc_task_t *task, isc_sockaddr_t *address) {
         * as we do in resolver.c, but we prefer implementation simplicity
         * at this moment.
         */
-       result = isc_socket_sendto(socket, &r, task, req_senddone,
-                                 request, address, NULL);
+       sendevent = isc_socket_socketevent(request->mctx, socket,
+                                          ISC_SOCKEVENT_SENDDONE,
+                                          req_senddone, request);
+       if (request->dscp == -1) {
+               sendevent->attributes &= ~ISC_SOCKEVENTATTR_DSCP;
+               sendevent->dscp = 0;
+       } else {
+               sendevent->attributes |= ISC_SOCKEVENTATTR_DSCP;
+               sendevent->dscp = request->dscp;
+       }
+
+       result = isc_socket_sendto2(socket, &r, task, address, NULL,
+                                   sendevent, 0);
        if (result == ISC_R_SUCCESS)
                request->flags |= DNS_REQUEST_F_SENDING;
        return (result);
@@ -471,6 +484,7 @@ new_request(isc_mem_t *mctx, dns_request_t **requestp)
        request->requestmgr = NULL;
        request->tsig = NULL;
        request->tsigkey = NULL;
+       request->dscp = -1;
        ISC_EVENT_INIT(&request->ctlevent, sizeof(request->ctlevent), 0, NULL,
                       DNS_EVENT_REQUESTCONTROL, do_cancel, request, NULL,
                       NULL, NULL);
@@ -510,7 +524,8 @@ isblackholed(dns_dispatchmgr_t *dispatchmgr, isc_sockaddr_t *destaddr) {
 
 static isc_result_t
 create_tcp_dispatch(dns_requestmgr_t *requestmgr, isc_sockaddr_t *srcaddr,
-                   isc_sockaddr_t *destaddr, dns_dispatch_t **dispatchp)
+                   isc_sockaddr_t *destaddr, isc_dscp_t dscp,
+                   dns_dispatch_t **dispatchp)
 {
        isc_result_t result;
        isc_socket_t *socket = NULL;
@@ -536,6 +551,7 @@ create_tcp_dispatch(dns_requestmgr_t *requestmgr, isc_sockaddr_t *srcaddr,
        if (result != ISC_R_SUCCESS)
                goto cleanup;
 #endif
+
        attrs = 0;
        attrs |= DNS_DISPATCHATTR_TCP;
        attrs |= DNS_DISPATCHATTR_PRIVATE;
@@ -544,6 +560,8 @@ create_tcp_dispatch(dns_requestmgr_t *requestmgr, isc_sockaddr_t *srcaddr,
        else
                attrs |= DNS_DISPATCHATTR_IPV6;
        attrs |= DNS_DISPATCHATTR_MAKEQUERY;
+
+       isc_socket_dscp(socket, dscp);
        result = dns_dispatch_createtcp(requestmgr->dispatchmgr,
                                        socket, requestmgr->taskmgr,
                                        4096, 2, 1, 1, 3, attrs,
@@ -609,12 +627,12 @@ find_udp_dispatch(dns_requestmgr_t *requestmgr, isc_sockaddr_t *srcaddr,
 static isc_result_t
 get_dispatch(isc_boolean_t tcp, dns_requestmgr_t *requestmgr,
             isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
-            dns_dispatch_t **dispatchp)
+            isc_dscp_t dscp, dns_dispatch_t **dispatchp)
 {
        isc_result_t result;
        if (tcp)
                result = create_tcp_dispatch(requestmgr, srcaddr,
-                                            destaddr, dispatchp);
+                                            destaddr, dscp, dispatchp);
        else
                result = find_udp_dispatch(requestmgr, srcaddr,
                                           destaddr, dispatchp);
@@ -646,8 +664,8 @@ dns_request_createraw(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf,
                      isc_task_t *task, isc_taskaction_t action, void *arg,
                      dns_request_t **requestp)
 {
-       return(dns_request_createraw3(requestmgr, msgbuf, srcaddr, destaddr,
-                                     options, timeout, 0, 0, task, action,
+       return(dns_request_createraw4(requestmgr, msgbuf, srcaddr, destaddr,
+                                     0, options, timeout, 0, 0, task, action,
                                      arg, requestp));
 }
 
@@ -664,8 +682,8 @@ dns_request_createraw2(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf,
        if (udptimeout != 0)
                udpretries = timeout / udptimeout;
 
-       return (dns_request_createraw3(requestmgr, msgbuf, srcaddr, destaddr,
-                                      options, timeout, udptimeout,
+       return (dns_request_createraw4(requestmgr, msgbuf, srcaddr, destaddr,
+                                      0, options, timeout, udptimeout,
                                       udpretries, task, action, arg,
                                       requestp));
 }
@@ -677,6 +695,21 @@ dns_request_createraw3(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf,
                       unsigned int udptimeout, unsigned int udpretries,
                       isc_task_t *task, isc_taskaction_t action, void *arg,
                       dns_request_t **requestp)
+{
+       return (dns_request_createraw4(requestmgr, msgbuf, srcaddr, destaddr,
+                                      0, options, timeout, udptimeout,
+                                      udpretries, task, action, arg,
+                                      requestp));
+}
+
+isc_result_t
+dns_request_createraw4(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf,
+                      isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
+                      isc_dscp_t dscp, unsigned int options,
+                      unsigned int timeout, unsigned int udptimeout,
+                      unsigned int udpretries, isc_task_t *task,
+                      isc_taskaction_t action, void *arg,
+                      dns_request_t **requestp)
 {
        dns_request_t *request = NULL;
        isc_task_t *tclone = NULL;
@@ -715,6 +748,7 @@ dns_request_createraw3(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf,
                        udptimeout = 1;
        }
        request->udpcount = udpretries;
+       request->dscp = dscp;
 
        /*
         * Create timer now.  We will set it below once.
@@ -746,7 +780,7 @@ dns_request_createraw3(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf,
        if ((options & DNS_REQUESTOPT_TCP) != 0 || r.length > 512)
                tcp = ISC_TRUE;
 
-       result = get_dispatch(tcp, requestmgr, srcaddr, destaddr,
+       result = get_dispatch(tcp, requestmgr, srcaddr, destaddr, dscp,
                              &request->dispatch);
        if (result != ISC_R_SUCCESS)
                goto cleanup;
@@ -833,8 +867,8 @@ dns_request_create(dns_requestmgr_t *requestmgr, dns_message_t *message,
                   isc_taskaction_t action, void *arg,
                   dns_request_t **requestp)
 {
-       return (dns_request_createvia3(requestmgr, message, NULL, address,
-                                      options, key, timeout, 0, 0, task,
+       return (dns_request_createvia4(requestmgr, message, NULL, address,
+                                      0, options, key, timeout, 0, 0, task,
                                       action, arg, requestp));
 }
 
@@ -846,8 +880,8 @@ dns_request_createvia(dns_requestmgr_t *requestmgr, dns_message_t *message,
                      isc_taskaction_t action, void *arg,
                      dns_request_t **requestp)
 {
-       return(dns_request_createvia3(requestmgr, message, srcaddr, destaddr,
-                                     options, key, timeout, 0, 0, task,
+       return(dns_request_createvia4(requestmgr, message, srcaddr, destaddr,
+                                     0, options, key, timeout, 0, 0, task,
                                      action, arg, requestp));
 }
 
@@ -863,8 +897,8 @@ dns_request_createvia2(dns_requestmgr_t *requestmgr, dns_message_t *message,
 
        if (udptimeout != 0)
                udpretries = timeout / udptimeout;
-       return (dns_request_createvia3(requestmgr, message, srcaddr, destaddr,
-                                      options, key, timeout, udptimeout,
+       return (dns_request_createvia4(requestmgr, message, srcaddr, destaddr,
+                                      0, options, key, timeout, udptimeout,
                                       udpretries, task, action, arg,
                                       requestp));
 }
@@ -877,6 +911,21 @@ dns_request_createvia3(dns_requestmgr_t *requestmgr, dns_message_t *message,
                       unsigned int udpretries, isc_task_t *task,
                       isc_taskaction_t action, void *arg,
                       dns_request_t **requestp)
+{
+       return (dns_request_createvia4(requestmgr, message, srcaddr, destaddr,
+                                      0, options, key, timeout, udptimeout,
+                                      udpretries, task, action, arg,
+                                      requestp));
+}
+
+isc_result_t
+dns_request_createvia4(dns_requestmgr_t *requestmgr, dns_message_t *message,
+                      isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
+                      isc_dscp_t dscp, unsigned int options,
+                      dns_tsigkey_t *key, unsigned int timeout,
+                      unsigned int udptimeout, unsigned int udpretries, 
+                      isc_task_t *task, isc_taskaction_t action, void *arg,
+                      dns_request_t **requestp)
 {
        dns_request_t *request = NULL;
        isc_task_t *tclone = NULL;
@@ -917,6 +966,7 @@ dns_request_createvia3(dns_requestmgr_t *requestmgr, dns_message_t *message,
                        udptimeout = 1;
        }
        request->udpcount = udpretries;
+       request->dscp = dscp;
 
        /*
         * Create timer now.  We will set it below once.
@@ -943,7 +993,7 @@ dns_request_createvia3(dns_requestmgr_t *requestmgr, dns_message_t *message,
 
  use_tcp:
        tcp = ISC_TF((options & DNS_REQUESTOPT_TCP) != 0);
-       result = get_dispatch(tcp, requestmgr, srcaddr, destaddr,
+       result = get_dispatch(tcp, requestmgr, srcaddr, destaddr, dscp,
                              &request->dispatch);
        if (result != ISC_R_SUCCESS)
                goto cleanup;
index 232709a049cb92638eb1ad1ef56f083549335ca8..5c220b7b320abaf72af2cd5bedcf7056b7687d88 100644 (file)
@@ -161,6 +161,7 @@ typedef struct query {
        isc_buffer_t                    *tsig;
        dns_tsigkey_t                   *tsigkey;
        isc_socketevent_t               sendevent;
+       isc_dscp_t                      dscp;
        unsigned int                    options;
        unsigned int                    attributes;
        unsigned int                    sends;
@@ -226,7 +227,7 @@ struct fetchctx {
        dns_adbfind_t *                 altfind;
        dns_adbaddrinfolist_t           forwaddrs;
        dns_adbaddrinfolist_t           altaddrs;
-       isc_sockaddrlist_t              forwarders;
+       dns_forwarderlist_t             forwarders;
        dns_fwdpolicy_t                 fwdpolicy;
        isc_sockaddrlist_t              bad;
        isc_sockaddrlist_t              edns;
@@ -397,6 +398,8 @@ struct dns_resolver {
        dns_dispatchset_t *             dispatches4;
        isc_boolean_t                   exclusivev4;
        dns_dispatchset_t *             dispatches6;
+       isc_dscp_t                      querydscp4;
+       isc_dscp_t                      querydscp6;
        isc_boolean_t                   exclusivev6;
        unsigned int                    nbuckets;
        fctxbucket_t *                  buckets;
@@ -1402,6 +1405,7 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
        isc_sockaddr_t addr;
        isc_boolean_t have_addr = ISC_FALSE;
        unsigned int srtt;
+       isc_dscp_t dscp = -1;
 
        FCTXTRACE("query");
 
@@ -1436,6 +1440,7 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
        query->attributes = 0;
        query->sends = 0;
        query->connects = 0;
+       query->dscp = addrinfo->dscp;
        /*
         * Note that the caller MUST guarantee that 'addrinfo' will remain
         * valid until this query is canceled.
@@ -1462,9 +1467,13 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
                        result = dns_peer_getquerysource(peer, &addr);
                        if (result == ISC_R_SUCCESS)
                                have_addr = ISC_TRUE;
+                       result = dns_peer_getquerydscp(peer, &dscp);
+                       if (result == ISC_R_SUCCESS)
+                               query->dscp = dscp;
                }
        }
 
+       dscp = -1;
        if ((query->options & DNS_FETCHOPT_TCP) != 0) {
                int pf;
 
@@ -1475,11 +1484,13 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
                                result = dns_dispatch_getlocaladdress(
                                              res->dispatches4->dispatches[0],
                                              &addr);
+                               dscp = dns_resolver_getquerydscp4(fctx->res);
                                break;
                        case PF_INET6:
                                result = dns_dispatch_getlocaladdress(
                                              res->dispatches6->dispatches[0],
                                              &addr);
+                               dscp = dns_resolver_getquerydscp6(fctx->res);
                                break;
                        default:
                                result = ISC_R_NOTIMPLEMENTED;
@@ -1489,6 +1500,8 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
                                goto cleanup_query;
                }
                isc_sockaddr_setport(&addr, 0);
+               if (query->dscp == -1)
+                       query->dscp = dscp;
 
                result = isc_socket_create(res->socketmgr, pf,
                                           isc_sockettype_tcp,
@@ -1501,7 +1514,6 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
                if (result != ISC_R_SUCCESS)
                        goto cleanup_socket;
 #endif
-
                /*
                 * A dispatch will be created once the connect succeeds.
                 */
@@ -1512,9 +1524,11 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
                        switch (isc_sockaddr_pf(&addr)) {
                        case AF_INET:
                                attrs |= DNS_DISPATCHATTR_IPV4;
+                               dscp = dns_resolver_getquerydscp4(fctx->res);
                                break;
                        case AF_INET6:
                                attrs |= DNS_DISPATCHATTR_IPV6;
+                               dscp = dns_resolver_getquerydscp6(fctx->res);
                                break;
                        default:
                                result = ISC_R_NOTIMPLEMENTED;
@@ -1539,18 +1553,23 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
                                    dns_resolver_dispatchv4(res),
                                    &query->dispatch);
                                query->exclusivesocket = res->exclusivev4;
+                               dscp = dns_resolver_getquerydscp4(fctx->res);
                                break;
                        case PF_INET6:
                                dns_dispatch_attach(
                                    dns_resolver_dispatchv6(res),
                                    &query->dispatch);
                                query->exclusivesocket = res->exclusivev6;
+                               dscp = dns_resolver_getquerydscp6(fctx->res);
                                break;
                        default:
                                result = ISC_R_NOTIMPLEMENTED;
                                goto cleanup_query;
                        }
                }
+
+               if (query->dscp == -1)
+                       query->dscp = dscp;
                /*
                 * We should always have a valid dispatcher here.  If we
                 * don't support a protocol family, then its dispatcher
@@ -1574,6 +1593,8 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
                 *
                 * XXXRTH  Should we attach to the socket?
                 */
+               if (query->dscp != -1)
+                       isc_socket_dscp(query->tcpsocket, query->dscp);
                result = isc_socket_connect(query->tcpsocket,
                                            &addrinfo->sockaddr, task,
                                            resquery_connected, query);
@@ -2027,9 +2048,21 @@ resquery_send(resquery_t *query) {
         * XXXRTH  Make sure we don't send to ourselves!  We should probably
         *              prune out these addresses when we get them from the ADB.
         */
+       memset(&query->sendevent, 0, sizeof(query->sendevent));
        ISC_EVENT_INIT(&query->sendevent, sizeof(query->sendevent), 0, NULL,
                       ISC_SOCKEVENT_SENDDONE, resquery_senddone, query,
                       NULL, NULL, NULL);
+
+       if (query->dscp == -1) {
+               query->sendevent.attributes &= ~ISC_SOCKEVENTATTR_DSCP;
+               query->sendevent.dscp = 0;
+       } else {
+               query->sendevent.attributes |= ISC_SOCKEVENTATTR_DSCP;
+               query->sendevent.dscp = query->dscp;
+               if ((query->options & DNS_FETCHOPT_TCP) != 0)
+                       isc_socket_dscp(socket, query->dscp);
+       }
+
        result = isc_socket_sendto2(socket, &r, task, address, NULL,
                                    &query->sendevent, 0);
        if (result != ISC_R_SUCCESS) {
@@ -2609,7 +2642,7 @@ fctx_getaddresses(fetchctx_t *fctx, isc_boolean_t badcache) {
        dns_resolver_t *res;
        isc_stdtime_t now;
        unsigned int stdoptions = 0;
-       isc_sockaddr_t *sa;
+       dns_forwarder_t *fwd;
        dns_adbaddrinfo_t *ai;
        isc_boolean_t all_bad;
        dns_rdata_ns_t ns;
@@ -2640,8 +2673,8 @@ fctx_getaddresses(fetchctx_t *fctx, isc_boolean_t badcache) {
         * selective forwarders specified in the view; otherwise use the
         * resolver's forwarders (if any).
         */
-       sa = ISC_LIST_HEAD(fctx->forwarders);
-       if (sa == NULL) {
+       fwd = ISC_LIST_HEAD(fctx->forwarders);
+       if (fwd == NULL) {
                dns_forwarders_t *forwarders = NULL;
                dns_name_t *name = &fctx->name;
                dns_name_t suffix;
@@ -2666,7 +2699,7 @@ fctx_getaddresses(fetchctx_t *fctx, isc_boolean_t badcache) {
                result = dns_fwdtable_find2(fctx->res->view->fwdtable, name,
                                            domain, &forwarders);
                if (result == ISC_R_SUCCESS) {
-                       sa = ISC_LIST_HEAD(forwarders->addrs);
+                       fwd = ISC_LIST_HEAD(forwarders->fwdrs);
                        fctx->fwdpolicy = forwarders->fwdpolicy;
                        if (fctx->fwdpolicy == dns_fwdpolicy_only &&
                            isstrictsubdomain(domain, &fctx->domain)) {
@@ -2680,20 +2713,20 @@ fctx_getaddresses(fetchctx_t *fctx, isc_boolean_t badcache) {
                }
        }
 
-       while (sa != NULL) {
-               if ((isc_sockaddr_pf(sa) == AF_INET &&
+       while (fwd != NULL) {
+               if ((isc_sockaddr_pf(&fwd->addr) == AF_INET &&
                         fctx->res->dispatches4 == NULL) ||
-                   (isc_sockaddr_pf(sa) == AF_INET6 &&
+                   (isc_sockaddr_pf(&fwd->addr) == AF_INET6 &&
                        fctx->res->dispatches6 == NULL)) {
-                               sa = ISC_LIST_NEXT(sa, link);
+                               fwd = ISC_LIST_NEXT(fwd, link);
                                continue;
                }
                ai = NULL;
-               result = dns_adb_findaddrinfo(fctx->adb,
-                                             sa, &ai, 0);  /* XXXMLG */
+               result = dns_adb_findaddrinfo(fctx->adb, &fwd->addr, &ai, 0);
                if (result == ISC_R_SUCCESS) {
                        dns_adbaddrinfo_t *cur;
                        ai->flags |= FCTX_ADDRINFO_FORWARDER;
+                       ai->dscp = fwd->dscp;
                        cur = ISC_LIST_HEAD(fctx->forwaddrs);
                        while (cur != NULL && cur->srtt < ai->srtt)
                                cur = ISC_LIST_NEXT(cur, publink);
@@ -2703,7 +2736,7 @@ fctx_getaddresses(fetchctx_t *fctx, isc_boolean_t badcache) {
                        else
                                ISC_LIST_APPEND(fctx->forwaddrs, ai, publink);
                }
-               sa = ISC_LIST_NEXT(sa, link);
+               fwd = ISC_LIST_NEXT(fwd, link);
        }
 
        /*
@@ -2852,8 +2885,7 @@ fctx_getaddresses(fetchctx_t *fctx, isc_boolean_t badcache) {
 }
 
 static inline void
-possibly_mark(fetchctx_t *fctx, dns_adbaddrinfo_t *addr)
-{
+possibly_mark(fetchctx_t *fctx, dns_adbaddrinfo_t *addr) {
        isc_netaddr_t na;
        char buf[ISC_NETADDR_FORMATSIZE];
        isc_sockaddr_t *sa;
@@ -9129,3 +9161,30 @@ dns_resolver_settimeout(dns_resolver_t *resolver, unsigned int seconds) {
 
        resolver->query_timeout = seconds;
 }
+
+void
+dns_resolver_setquerydscp4(dns_resolver_t *resolver, isc_dscp_t dscp) {
+       REQUIRE(VALID_RESOLVER(resolver));
+
+       resolver->querydscp4 = dscp;
+}
+
+isc_dscp_t
+dns_resolver_getquerydscp4(dns_resolver_t *resolver) {
+       REQUIRE(VALID_RESOLVER(resolver));
+       return (resolver->querydscp4);
+}
+
+void
+dns_resolver_setquerydscp6(dns_resolver_t *resolver, isc_dscp_t dscp) {
+       REQUIRE(VALID_RESOLVER(resolver));
+
+       resolver->querydscp6 = dscp;
+}
+
+isc_dscp_t
+dns_resolver_getquerydscp6(dns_resolver_t *resolver) {
+       REQUIRE(VALID_RESOLVER(resolver));
+       return (resolver->querydscp6);
+}
+
index a663f912ee5b79afd2baf7c9df229e6f9b1f6e4f..48fe2b6df81d1754e51899c4e1a9a5971c4344d8 100644 (file)
@@ -180,12 +180,14 @@ dns_dispatch_cancel
 dns_dispatch_changeattributes
 dns_dispatch_createtcp
 dns_dispatch_detach
+dns_dispatch_getdscp
 dns_dispatch_getlocaladdress
 dns_dispatch_getsocket
 dns_dispatch_getudp
 dns_dispatch_getudp_dup
 dns_dispatch_importrecv
 dns_dispatch_removeresponse
+dns_dispatch_setdscp
 dns_dispatch_starttcp
 dns_dispatchmgr_create
 dns_dispatchmgr_destroy
@@ -456,11 +458,17 @@ dns_peer_detach
 dns_peer_getbogus
 dns_peer_getkey
 dns_peer_getmaxudp
+dns_peer_getnotifysource
+dns_peer_getnotifydscp
 dns_peer_getprovideixfr
+dns_peer_getquerysource
+dns_peer_getquerydscp
 dns_peer_getrequestixfr
 dns_peer_getsupportedns
 dns_peer_gettransferformat
 dns_peer_gettransfers
+dns_peer_gettransfersource
+dns_peer_gettransferdscp
 dns_peer_new
 dns_peer_newprefix
 dns_peer_setbogus
@@ -468,14 +476,17 @@ dns_peer_setkey
 dns_peer_setkeybycharp
 dns_peer_setmaxudp
 dns_peer_setnotifysource
+dns_peer_setnotifydscp
 dns_peer_setprovideixfr
 dns_peer_setquerysource
+dns_peer_setquerydscp
 dns_peer_setrequestixfr
 dns_peer_setrequestnsid
 dns_peer_setsupportedns
 dns_peer_settransferformat
 dns_peer_settransfers
 dns_peer_settransfersource
+dns_peer_settransferdscp
 dns_peer_setudpsize
 dns_peerlist_addpeer
 dns_peerlist_attach
@@ -825,6 +836,8 @@ dns_zone_forwardupdate
 dns_zone_fulldumptostream
 dns_zone_get_rpz_num
 dns_zone_getadded
+dns_zone_getaltxfrsource4dscp
+dns_zone_getaltxfrsource6dscp
 dns_zone_getchecknames
 dns_zone_getclass
 dns_zone_getdb
@@ -843,7 +856,9 @@ dns_zone_getmctx
 dns_zone_getmgr
 dns_zone_getnotifyacl
 dns_zone_getnotifysrc4
+dns_zone_getnotifysrc4dscp
 dns_zone_getnotifysrc6
+dns_zone_getnotifysrc6dscp
 dns_zone_getoptions
 dns_zone_getorigin
 dns_zone_getprivatetype
@@ -867,7 +882,9 @@ dns_zone_getupdatedisabled
 dns_zone_getview
 dns_zone_getxfracl
 dns_zone_getxfrsource4
+dns_zone_getxfrsource4dscp
 dns_zone_getxfrsource6
+dns_zone_getxfrsource6dscp
 dns_zone_getzeronosoattl
 dns_zone_iattach
 dns_zone_idetach
@@ -896,7 +913,9 @@ dns_zone_setadded
 dns_zone_setalsonotify
 dns_zone_setalsonotifywithkeys
 dns_zone_setaltxfrsource4
+dns_zone_setaltxfrsource4dscp
 dns_zone_setaltxfrsource6
+dns_zone_setaltxfrsource6dscp
 dns_zone_setcheckmx
 dns_zone_setchecknames
 dns_zone_setcheckns
@@ -928,7 +947,9 @@ dns_zone_setnodes
 dns_zone_setnotifyacl
 dns_zone_setnotifydelay
 dns_zone_setnotifysrc4
+dns_zone_setnotifysrc4dscp
 dns_zone_setnotifysrc6
+dns_zone_setnotifysrc6dscp
 dns_zone_setnotifytype
 dns_zone_setnsec3param
 dns_zone_setoption
@@ -955,7 +976,9 @@ dns_zone_setupdatedisabled
 dns_zone_setview
 dns_zone_setxfracl
 dns_zone_setxfrsource4
+dns_zone_setxfrsource4dscp
 dns_zone_setxfrsource6
+dns_zone_setxfrsource6dscp
 dns_zone_setzeronosoattl
 dns_zone_signwithkey
 dns_zone_synckeyzone
index 66e3fae329034b73c635107c963cf978ffcf676a..ad676b74d070478a0ba01b8b6138d36ac0c874c6 100644 (file)
@@ -121,6 +121,7 @@ struct dns_xfrin_ctx {
         * may differ due to IXFR->AXFR fallback.
         */
        dns_rdatatype_t         reqtype;
+       isc_dscp_t              dscp;
 
        isc_sockaddr_t          masteraddr;
        isc_sockaddr_t          sourceaddr;
@@ -192,6 +193,7 @@ xfrin_create(isc_mem_t *mctx,
             dns_rdatatype_t reqtype,
             isc_sockaddr_t *masteraddr,
             isc_sockaddr_t *sourceaddr,
+            isc_dscp_t dscp,
             dns_tsigkey_t *tsigkey,
             dns_xfrin_ctx_t **xfrp);
 
@@ -606,20 +608,23 @@ dns_xfrin_create(dns_zone_t *zone, dns_rdatatype_t xfrtype,
                 dns_xfrindone_t done, dns_xfrin_ctx_t **xfrp)
 {
        isc_sockaddr_t sourceaddr;
+       isc_dscp_t dscp;
 
        switch (isc_sockaddr_pf(masteraddr)) {
        case PF_INET:
                sourceaddr = *dns_zone_getxfrsource4(zone);
+               dscp = dns_zone_getxfrsource4dscp(zone);
                break;
        case PF_INET6:
                sourceaddr = *dns_zone_getxfrsource6(zone);
+               dscp = dns_zone_getxfrsource6dscp(zone);
                break;
        default:
                INSIST(0);
        }
 
-       return(dns_xfrin_create2(zone, xfrtype, masteraddr, &sourceaddr,
-                                tsigkey, mctx, timermgr, socketmgr,
+       return(dns_xfrin_create3(zone, xfrtype, masteraddr, &sourceaddr,
+                                dscp, tsigkey, mctx, timermgr, socketmgr,
                                 task, done, xfrp));
 }
 
@@ -630,6 +635,19 @@ dns_xfrin_create2(dns_zone_t *zone, dns_rdatatype_t xfrtype,
                  isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr,
                  isc_task_t *task, dns_xfrindone_t done,
                  dns_xfrin_ctx_t **xfrp)
+{
+       return (dns_xfrin_create3(zone, xfrtype, masteraddr, sourceaddr, -1,
+                                 tsigkey, mctx, timermgr, socketmgr, task,
+                                 done, xfrp));
+}
+
+isc_result_t
+dns_xfrin_create3(dns_zone_t *zone, dns_rdatatype_t xfrtype,
+                 isc_sockaddr_t *masteraddr, isc_sockaddr_t *sourceaddr,
+                 isc_dscp_t dscp, dns_tsigkey_t *tsigkey, isc_mem_t *mctx,
+                 isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr,
+                 isc_task_t *task, dns_xfrindone_t done,
+                 dns_xfrin_ctx_t **xfrp)
 {
        dns_name_t *zonename = dns_zone_getorigin(zone);
        dns_xfrin_ctx_t *xfr = NULL;
@@ -645,7 +663,7 @@ dns_xfrin_create2(dns_zone_t *zone, dns_rdatatype_t xfrtype,
 
        CHECK(xfrin_create(mctx, zone, db, task, timermgr, socketmgr, zonename,
                           dns_zone_getclass(zone), xfrtype, masteraddr,
-                          sourceaddr, tsigkey, &xfr));
+                          sourceaddr, dscp, tsigkey, &xfr));
 
        CHECK(xfrin_start(xfr));
 
@@ -768,6 +786,7 @@ xfrin_create(isc_mem_t *mctx,
             dns_rdatatype_t reqtype,
             isc_sockaddr_t *masteraddr,
             isc_sockaddr_t *sourceaddr,
+            isc_dscp_t dscp,
             dns_tsigkey_t *tsigkey,
             dns_xfrin_ctx_t **xfrp)
 {
@@ -800,6 +819,7 @@ xfrin_create(isc_mem_t *mctx,
        xfr->checkid = ISC_TRUE;
        xfr->id = (isc_uint16_t)(tmp & 0xffff);
        xfr->reqtype = reqtype;
+       xfr->dscp = dscp;
 
        /* sockaddr */
        xfr->socket = NULL;
@@ -891,6 +911,7 @@ xfrin_start(dns_xfrin_ctx_t *xfr) {
        CHECK(isc_socket_bind(xfr->socket, &xfr->sourceaddr,
                              ISC_SOCKET_REUSEADDRESS));
 #endif
+       isc_socket_dscp(xfr->socket, xfr->dscp);
        CHECK(isc_socket_connect(xfr->socket, &xfr->masteraddr, xfr->task,
                                 xfrin_connect_done, xfr));
        xfr->connects++;
index d69f5118a372f542349c4ebfdfb29487a245092f..27af000884c8c5a01cf6dca6791bedf447ee6cf4 100644 (file)
@@ -243,6 +243,7 @@ struct dns_zone {
        isc_uint32_t            minretry;
 
        isc_sockaddr_t          *masters;
+       isc_dscp_t              *masterdscps;
        dns_name_t              **masterkeynames;
        isc_boolean_t           *mastersok;
        unsigned int            masterscnt;
@@ -251,6 +252,7 @@ struct dns_zone {
        dns_notifytype_t        notifytype;
        isc_sockaddr_t          *notify;
        dns_name_t              **notifykeynames;
+       isc_dscp_t              *notifydscp;
        unsigned int            notifycnt;
        isc_sockaddr_t          notifyfrom;
        isc_task_t              *task;
@@ -262,6 +264,12 @@ struct dns_zone {
        isc_sockaddr_t          altxfrsource4;
        isc_sockaddr_t          altxfrsource6;
        isc_sockaddr_t          sourceaddr;
+       isc_dscp_t              notifysrc4dscp;
+       isc_dscp_t              notifysrc6dscp;
+       isc_dscp_t              xfrsource4dscp;
+       isc_dscp_t              xfrsource6dscp;
+       isc_dscp_t              altxfrsource4dscp;
+       isc_dscp_t              altxfrsource6dscp;
        dns_xfrin_ctx_t         *xfr;           /* task locked */
        dns_tsigkey_t           *tsigkey;       /* key used for xfr */
        /* Access Control Lists */
@@ -512,6 +520,7 @@ struct dns_notify {
        dns_name_t              ns;
        isc_sockaddr_t          dst;
        dns_tsigkey_t           *key;
+       isc_dscp_t              dscp;
        ISC_LINK(dns_notify_t)  link;
 };
 
@@ -869,12 +878,14 @@ dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
        zone->maxretry = DNS_ZONE_MAXRETRY;
        zone->minretry = DNS_ZONE_MINRETRY;
        zone->masters = NULL;
+       zone->masterdscps = NULL;
        zone->masterkeynames = NULL;
        zone->mastersok = NULL;
        zone->masterscnt = 0;
        zone->curmaster = 0;
        zone->notify = NULL;
        zone->notifykeynames = NULL;
+       zone->notifydscp = NULL;
        zone->notifytype = dns_notifytype_yes;
        zone->notifycnt = 0;
        zone->task = NULL;
@@ -904,6 +915,12 @@ dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
        isc_sockaddr_any6(&zone->xfrsource6);
        isc_sockaddr_any(&zone->altxfrsource4);
        isc_sockaddr_any6(&zone->altxfrsource6);
+       zone->notifysrc4dscp = -1;
+       zone->notifysrc6dscp = -1;
+       zone->xfrsource4dscp = -1;
+       zone->xfrsource6dscp = -1;
+       zone->altxfrsource4dscp = -1;
+       zone->altxfrsource6dscp = -1;
        zone->xfr = NULL;
        zone->tsigkey = NULL;
        zone->maxxfrin = MAX_XFER_TIME;
@@ -4778,6 +4795,23 @@ dns_zone_getxfrsource4(dns_zone_t *zone) {
        return (&zone->xfrsource4);
 }
 
+isc_result_t
+dns_zone_setxfrsource4dscp(dns_zone_t *zone, isc_dscp_t dscp) {
+       REQUIRE(DNS_ZONE_VALID(zone));
+
+       LOCK_ZONE(zone);
+       zone->xfrsource4dscp = dscp;
+       UNLOCK_ZONE(zone);
+
+       return (ISC_R_SUCCESS);
+}
+
+isc_dscp_t
+dns_zone_getxfrsource4dscp(dns_zone_t *zone) {
+       REQUIRE(DNS_ZONE_VALID(zone));
+       return (zone->xfrsource4dscp);
+}
+
 isc_result_t
 dns_zone_setxfrsource6(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
        REQUIRE(DNS_ZONE_VALID(zone));
@@ -4795,6 +4829,23 @@ dns_zone_getxfrsource6(dns_zone_t *zone) {
        return (&zone->xfrsource6);
 }
 
+isc_dscp_t
+dns_zone_getxfrsource6dscp(dns_zone_t *zone) {
+       REQUIRE(DNS_ZONE_VALID(zone));
+       return (zone->xfrsource6dscp);
+}
+
+isc_result_t
+dns_zone_setxfrsource6dscp(dns_zone_t *zone, isc_dscp_t dscp) {
+       REQUIRE(DNS_ZONE_VALID(zone));
+
+       LOCK_ZONE(zone);
+       zone->xfrsource6dscp = dscp;
+       UNLOCK_ZONE(zone);
+
+       return (ISC_R_SUCCESS);
+}
+
 isc_result_t
 dns_zone_setaltxfrsource4(dns_zone_t *zone,
                          const isc_sockaddr_t *altxfrsource)
@@ -4814,6 +4865,23 @@ dns_zone_getaltxfrsource4(dns_zone_t *zone) {
        return (&zone->altxfrsource4);
 }
 
+isc_result_t
+dns_zone_setaltxfrsource4dscp(dns_zone_t *zone, isc_dscp_t dscp) {
+       REQUIRE(DNS_ZONE_VALID(zone));
+
+       LOCK_ZONE(zone);
+       zone->altxfrsource4dscp = dscp;
+       UNLOCK_ZONE(zone);
+
+       return (ISC_R_SUCCESS);
+}
+
+isc_dscp_t
+dns_zone_getaltxfrsource4dscp(dns_zone_t *zone) {
+       REQUIRE(DNS_ZONE_VALID(zone));
+       return (zone->altxfrsource4dscp);
+}
+
 isc_result_t
 dns_zone_setaltxfrsource6(dns_zone_t *zone,
                          const isc_sockaddr_t *altxfrsource)
@@ -4833,6 +4901,23 @@ dns_zone_getaltxfrsource6(dns_zone_t *zone) {
        return (&zone->altxfrsource6);
 }
 
+isc_result_t
+dns_zone_setaltxfrsource6dscp(dns_zone_t *zone, isc_dscp_t dscp) {
+       REQUIRE(DNS_ZONE_VALID(zone));
+
+       LOCK_ZONE(zone);
+       zone->altxfrsource6dscp = dscp;
+       UNLOCK_ZONE(zone);
+
+       return (ISC_R_SUCCESS);
+}
+
+isc_dscp_t
+dns_zone_getaltxfrsource6dscp(dns_zone_t *zone) {
+       REQUIRE(DNS_ZONE_VALID(zone));
+       return (zone->altxfrsource6dscp);
+}
+
 isc_result_t
 dns_zone_setnotifysrc4(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
        REQUIRE(DNS_ZONE_VALID(zone));
@@ -4850,6 +4935,23 @@ dns_zone_getnotifysrc4(dns_zone_t *zone) {
        return (&zone->notifysrc4);
 }
 
+isc_result_t
+dns_zone_setnotifysrc4dscp(dns_zone_t *zone, isc_dscp_t dscp) {
+       REQUIRE(DNS_ZONE_VALID(zone));
+
+       LOCK_ZONE(zone);
+       zone->notifysrc4dscp = dscp;
+       UNLOCK_ZONE(zone);
+
+       return (ISC_R_SUCCESS);
+}
+
+isc_dscp_t
+dns_zone_getnotifysrc4dscp(dns_zone_t *zone) {
+       REQUIRE(DNS_ZONE_VALID(zone));
+       return (zone->notifysrc4dscp);
+}
+
 isc_result_t
 dns_zone_setnotifysrc6(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
        REQUIRE(DNS_ZONE_VALID(zone));
@@ -4899,25 +5001,33 @@ same_keynames(dns_name_t **old, dns_name_t **new, isc_uint32_t count) {
 }
 
 static void
-clear_addresskeylist(isc_sockaddr_t **addrsp, dns_name_t ***keynamesp,
-                    unsigned int *countp, isc_mem_t *mctx)
+clear_addresskeylist(isc_sockaddr_t **addrsp, isc_dscp_t **dscpsp,
+                    dns_name_t ***keynamesp, unsigned int *countp,
+                    isc_mem_t *mctx)
 {
        unsigned int count;
        isc_sockaddr_t *addrs;
+       isc_dscp_t *dscps;
        dns_name_t **keynames;
 
-       REQUIRE(countp != NULL && addrsp != NULL && keynamesp != NULL);
+       REQUIRE(countp != NULL && addrsp != NULL && dscpsp != NULL &&
+               keynamesp != NULL);
 
        count = *countp;
        *countp = 0;
        addrs = *addrsp;
        *addrsp = NULL;
+       dscps = *dscpsp;
+       *dscpsp = NULL;
        keynames = *keynamesp;
        *keynamesp = NULL;
 
        if (addrs != NULL)
                isc_mem_put(mctx, addrs, count * sizeof(isc_sockaddr_t));
 
+       if (dscps != NULL)
+               isc_mem_put(mctx, dscps, count * sizeof(isc_dscp_t));
+
        if (keynames != NULL) {
                unsigned int i;
                for (i = 0; i < count; i++) {
@@ -4935,15 +5045,18 @@ clear_addresskeylist(isc_sockaddr_t **addrsp, dns_name_t ***keynamesp,
 static isc_result_t
 set_addrkeylist(unsigned int count,
                const isc_sockaddr_t *addrs, isc_sockaddr_t **newaddrsp,
+               const isc_dscp_t *dscp, isc_dscp_t **newdscpp,
                dns_name_t **names, dns_name_t ***newnamesp,
                isc_mem_t *mctx)
 {
        isc_result_t result;
        isc_sockaddr_t *newaddrs = NULL;
+       isc_dscp_t *newdscp = NULL;
        dns_name_t **newnames = NULL;
        unsigned int i;
 
        REQUIRE(newaddrsp != NULL && *newaddrsp == NULL);
+       REQUIRE(newdscpp != NULL && *newdscpp == NULL);
        REQUIRE(newnamesp != NULL && *newnamesp == NULL);
 
        newaddrs = isc_mem_get(mctx, count * sizeof(*newaddrs));
@@ -4951,10 +5064,22 @@ set_addrkeylist(unsigned int count,
                return (ISC_R_NOMEMORY);
        memcpy(newaddrs, addrs, count * sizeof(*newaddrs));
 
-       newnames = NULL;
+       if (dscp != NULL) {
+               newdscp = isc_mem_get(mctx, count * sizeof(*newdscp));
+               if (newdscp == NULL) {
+                       isc_mem_put(mctx, newaddrs, count * sizeof(*newaddrs));
+                       return (ISC_R_NOMEMORY);
+               }
+               memcpy(newdscp, dscp, count * sizeof(*newdscp));
+       } else
+               newdscp = NULL;
+
        if (names != NULL) {
                newnames = isc_mem_get(mctx, count * sizeof(*newnames));
                if (newnames == NULL) {
+                       if (newdscp != NULL)
+                               isc_mem_put(mctx, newdscp,
+                                           count * sizeof(*newdscp));
                        isc_mem_put(mctx, newaddrs, count * sizeof(*newaddrs));
                        return (ISC_R_NOMEMORY);
                }
@@ -4978,32 +5103,64 @@ set_addrkeylist(unsigned int count,
                                                               mctx);
                                        isc_mem_put(mctx, newaddrs,
                                                    count * sizeof(*newaddrs));
+                                       isc_mem_put(mctx, newdscp,
+                                                   count * sizeof(*newdscp));
                                        isc_mem_put(mctx, newnames,
                                                    count * sizeof(*newnames));
                                        return (ISC_R_NOMEMORY);
                                }
                        }
                }
-       }
+       } else
+               newnames = NULL;
 
+       *newdscpp = newdscp;
        *newaddrsp = newaddrs;
        *newnamesp = newnames;
        return (ISC_R_SUCCESS);
 }
 
+isc_result_t
+dns_zone_setnotifysrc6dscp(dns_zone_t *zone, isc_dscp_t dscp) {
+       REQUIRE(DNS_ZONE_VALID(zone));
+
+       LOCK_ZONE(zone);
+       zone->notifysrc6dscp = dscp;
+       UNLOCK_ZONE(zone);
+
+       return (ISC_R_SUCCESS);
+}
+
+isc_dscp_t
+dns_zone_getnotifysrc6dscp(dns_zone_t *zone) {
+       REQUIRE(DNS_ZONE_VALID(zone));
+       return (zone->notifysrc6dscp);
+}
+
 isc_result_t
 dns_zone_setalsonotify(dns_zone_t *zone, const isc_sockaddr_t *notify,
                       isc_uint32_t count)
 {
-       return (dns_zone_setalsonotifywithkeys(zone, notify, NULL, count));
+       return (dns_zone_setalsonotifydscpkeys(zone, notify, NULL, NULL,
+                                              count));
 }
 
 isc_result_t
 dns_zone_setalsonotifywithkeys(dns_zone_t *zone, const isc_sockaddr_t *notify,
                               dns_name_t **keynames, isc_uint32_t count)
+{
+       return (dns_zone_setalsonotifydscpkeys(zone, notify, NULL, keynames,
+                                              count));
+}
+
+isc_result_t
+dns_zone_setalsonotifydscpkeys(dns_zone_t *zone, const isc_sockaddr_t *notify,
+                              const isc_dscp_t *dscps, dns_name_t **keynames,
+                              isc_uint32_t count)
 {
        isc_result_t result;
        isc_sockaddr_t *newaddrs = NULL;
+       isc_dscp_t *newdscps = NULL;
        dns_name_t **newnames = NULL;
 
        REQUIRE(DNS_ZONE_VALID(zone));
@@ -5018,8 +5175,9 @@ dns_zone_setalsonotifywithkeys(dns_zone_t *zone, const isc_sockaddr_t *notify,
            same_keynames(zone->notifykeynames, keynames, count))
                goto unlock;
 
-       clear_addresskeylist(&zone->notify, &zone->notifykeynames,
-                            &zone->notifycnt, zone->mctx);
+       clear_addresskeylist(&zone->notify, &zone->notifydscp,
+                            &zone->notifykeynames, &zone->notifycnt,
+                            zone->mctx);
 
        if (count == 0)
                goto unlock;
@@ -5027,7 +5185,7 @@ dns_zone_setalsonotifywithkeys(dns_zone_t *zone, const isc_sockaddr_t *notify,
        /*
         * Set up the notify and notifykey lists
         */
-       result = set_addrkeylist(count, notify, &newaddrs,
+       result = set_addrkeylist(count, notify, &newaddrs, dscps, &newdscps,
                                 keynames, &newnames, zone->mctx);
        if (result != ISC_R_SUCCESS)
                goto unlock;
@@ -5036,6 +5194,7 @@ dns_zone_setalsonotifywithkeys(dns_zone_t *zone, const isc_sockaddr_t *notify,
         * Everything is ok so attach to the zone.
         */
        zone->notify = newaddrs;
+       zone->notifydscp = newdscps;
        zone->notifykeynames = newnames;
        zone->notifycnt = count;
  unlock:
@@ -5061,6 +5220,7 @@ dns_zone_setmasterswithkeys(dns_zone_t *zone,
 {
        isc_result_t result = ISC_R_SUCCESS;
        isc_sockaddr_t *newaddrs = NULL;
+       isc_dscp_t *newdscps = NULL;
        dns_name_t **newnames = NULL;
        isc_boolean_t *newok;
        unsigned int i;
@@ -5095,8 +5255,9 @@ dns_zone_setmasterswithkeys(dns_zone_t *zone,
                            zone->masterscnt * sizeof(isc_boolean_t));
                zone->mastersok = NULL;
        }
-       clear_addresskeylist(&zone->masters, &zone->masterkeynames,
-                            &zone->masterscnt, zone->mctx);
+       clear_addresskeylist(&zone->masters, &zone->masterdscps,
+                            &zone->masterkeynames, &zone->masterscnt,
+                            zone->mctx);
        /*
         * If count == 0, don't allocate any space for masters, mastersok or
         * keynames so internally, those pointers are NULL if count == 0
@@ -5119,8 +5280,9 @@ dns_zone_setmasterswithkeys(dns_zone_t *zone,
        /*
         * Now set up the masters and masterkey lists
         */
-       result = set_addrkeylist(count, masters, &newaddrs,
+       result = set_addrkeylist(count, masters, &newaddrs, NULL, &newdscps,
                                 keynames, &newnames, zone->mctx);
+       INSIST(newdscps == NULL);
        if (result != ISC_R_SUCCESS) {
                isc_mem_put(zone->mctx, newok, count * sizeof(*newok));
                goto unlock;
@@ -5132,6 +5294,7 @@ dns_zone_setmasterswithkeys(dns_zone_t *zone,
        zone->curmaster = 0;
        zone->mastersok = newok;
        zone->masters = newaddrs;
+       zone->masterdscps = newdscps;
        zone->masterkeynames = newnames;
        zone->masterscnt = count;
        DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOMASTERS);
@@ -9626,6 +9789,8 @@ notify_send_toaddr(isc_task_t *task, isc_event_t *event) {
        isc_sockaddr_t src;
        int timeout;
        isc_boolean_t have_notifysource = ISC_FALSE;
+       isc_boolean_t have_notifydscp = ISC_FALSE;
+       isc_dscp_t dscp = -1;
 
        notify = event->ev_arg;
        REQUIRE(DNS_NOTIFY_VALID(notify));
@@ -9692,16 +9857,23 @@ notify_send_toaddr(isc_task_t *task, isc_event_t *event) {
                        result = dns_peer_getnotifysource(peer, &src);
                        if (result == ISC_R_SUCCESS)
                                have_notifysource = ISC_TRUE;
+                       dns_peer_getnotifydscp(peer, &dscp);
+                       if (dscp != -1)
+                               have_notifydscp = ISC_TRUE;
                }
        }
        switch (isc_sockaddr_pf(&notify->dst)) {
        case PF_INET:
                if (!have_notifysource)
                        src = notify->zone->notifysrc4;
+               if (!have_notifydscp)
+                       dscp = notify->zone->notifysrc4dscp;
                break;
        case PF_INET6:
                if (!have_notifysource)
                        src = notify->zone->notifysrc6;
+               if (!have_notifydscp)
+                       dscp = notify->zone->notifysrc6dscp;
                break;
        default:
                result = ISC_R_NOTIMPLEMENTED;
@@ -9710,9 +9882,9 @@ notify_send_toaddr(isc_task_t *task, isc_event_t *event) {
        timeout = 15;
        if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_DIALNOTIFY))
                timeout = 30;
-       result = dns_request_createvia2(notify->zone->view->requestmgr,
-                                       message, &src, &notify->dst, 0, key,
-                                       timeout * 3, timeout,
+       result = dns_request_createvia4(notify->zone->view->requestmgr,
+                                       message, &src, &notify->dst, dscp,
+                                       0, key, timeout * 3, timeout, 0,
                                        notify->zone->task, notify_done,
                                        notify, &notify->request);
        if (result == ISC_R_SUCCESS) {
@@ -10897,8 +11069,9 @@ soa_query(isc_task_t *task, isc_event_t *event) {
        isc_uint32_t options;
        isc_boolean_t cancel = ISC_TRUE;
        int timeout;
-       isc_boolean_t have_xfrsource, reqnsid;
+       isc_boolean_t have_xfrsource, have_xfrdscp, reqnsid;
        isc_uint16_t udpsize = SEND_BUFFER_SIZE;
+       isc_dscp_t dscp = -1;
 
        REQUIRE(DNS_ZONE_VALID(zone));
 
@@ -10957,7 +11130,7 @@ soa_query(isc_task_t *task, isc_event_t *event) {
                }
        }
 
-       have_xfrsource = ISC_FALSE;
+       have_xfrsource = have_xfrdscp = ISC_FALSE;
        reqnsid = zone->view->requestnsid;
        if (zone->view->peers != NULL) {
                dns_peer_t *peer = NULL;
@@ -10972,6 +11145,9 @@ soa_query(isc_task_t *task, isc_event_t *event) {
                                                            &zone->sourceaddr);
                        if (result == ISC_R_SUCCESS)
                                have_xfrsource = ISC_TRUE;
+                       dns_peer_gettransferdscp(peer, &dscp);
+                       if (dscp != -1)
+                               have_xfrdscp = ISC_TRUE;
                        if (zone->view->resolver != NULL)
                                udpsize =
                                  dns_resolver_getudpsize(zone->view->resolver);
@@ -10987,8 +11163,13 @@ soa_query(isc_task_t *task, isc_event_t *event) {
                                               &zone->xfrsource4))
                                goto skip_master;
                        zone->sourceaddr = zone->altxfrsource4;
-               } else if (!have_xfrsource)
+                       if (!have_xfrdscp)
+                               dscp = zone->altxfrsource4dscp;
+               } else if (!have_xfrsource) {
                        zone->sourceaddr = zone->xfrsource4;
+                       if (!have_xfrdscp)
+                               dscp = zone->xfrsource4dscp;
+               }
                break;
        case PF_INET6:
                if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
@@ -10996,8 +11177,13 @@ soa_query(isc_task_t *task, isc_event_t *event) {
                                               &zone->xfrsource6))
                                goto skip_master;
                        zone->sourceaddr = zone->altxfrsource6;
-               } else if (!have_xfrsource)
+                       if (!have_xfrdscp)
+                               dscp = zone->altxfrsource6dscp;
+               } else if (!have_xfrsource) {
                        zone->sourceaddr = zone->xfrsource6;
+                       if (!have_xfrdscp)
+                               dscp = zone->xfrsource6dscp;
+               }
                break;
        default:
                result = ISC_R_NOTIMPLEMENTED;
@@ -11019,11 +11205,11 @@ soa_query(isc_task_t *task, isc_event_t *event) {
        timeout = 15;
        if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
                timeout = 30;
-       result = dns_request_createvia2(zone->view->requestmgr, message,
+       result = dns_request_createvia4(zone->view->requestmgr, message,
                                        &zone->sourceaddr, &zone->masteraddr,
-                                       options, key, timeout * 3, timeout,
-                                       zone->task, refresh_callback, zone,
-                                       &zone->request);
+                                       dscp, options, key, timeout * 3,
+                                       timeout, 0, zone->task,
+                                       refresh_callback, zone, &zone->request);
        if (result != ISC_R_SUCCESS) {
                zone_idetach(&dummy);
                zone_debuglog(zone, me, 1,
@@ -11077,8 +11263,10 @@ ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
        dns_tsigkey_t *key = NULL;
        dns_dbnode_t *node = NULL;
        int timeout;
-       isc_boolean_t have_xfrsource = ISC_FALSE, reqnsid;
-       isc_uint16_t udpsize = SEND_BUFFER_SIZE;
+       isc_boolean_t have_xfrsource = ISC_FALSE, have_xfrdscp = ISC_FALSE;
+       isc_boolean_t reqnsid;
+       isc_uint16_t udpsize = SEND_BUFFER_SIZE;
+       isc_dscp_t dscp = -1;
 
        REQUIRE(DNS_ZONE_VALID(zone));
        REQUIRE(LOCKED_ZONE(zone));
@@ -11209,6 +11397,9 @@ ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
                                                            &zone->sourceaddr);
                        if (result == ISC_R_SUCCESS)
                                have_xfrsource = ISC_TRUE;
+                       result = dns_peer_gettransferdscp(peer, &dscp);
+                       if (dscp != -1)
+                               have_xfrdscp = ISC_TRUE;
                        if (zone->view->resolver != NULL)
                                udpsize =
                                  dns_resolver_getudpsize(zone->view->resolver);
@@ -11230,16 +11421,26 @@ ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
         */
        switch (isc_sockaddr_pf(&zone->masteraddr)) {
        case PF_INET:
-               if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC))
+               if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
                        zone->sourceaddr = zone->altxfrsource4;
-               else if (!have_xfrsource)
+                       if (!have_xfrdscp)
+                               dscp = zone->altxfrsource4dscp;
+               } else if (!have_xfrsource) {
                        zone->sourceaddr = zone->xfrsource4;
+                       if (!have_xfrdscp)
+                               dscp = zone->xfrsource4dscp;
+               }
                break;
        case PF_INET6:
-               if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC))
+               if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
                        zone->sourceaddr = zone->altxfrsource6;
-               else if (!have_xfrsource)
+                       if (!have_xfrdscp)
+                               dscp = zone->altxfrsource6dscp;
+               } else if (!have_xfrsource) {
                        zone->sourceaddr = zone->xfrsource6;
+                       if (!have_xfrdscp)
+                               dscp = zone->xfrsource6dscp;
+               }
                break;
        default:
                result = ISC_R_NOTIMPLEMENTED;
@@ -11249,11 +11450,11 @@ ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
        timeout = 15;
        if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
                timeout = 30;
-       result = dns_request_createvia2(zone->view->requestmgr, message,
+       result = dns_request_createvia4(zone->view->requestmgr, message,
                                        &zone->sourceaddr, &zone->masteraddr,
-                                       DNS_REQUESTOPT_TCP, key, timeout * 3,
-                                       timeout, zone->task, stub_callback,
-                                       stub, &zone->request);
+                                       dscp, DNS_REQUESTOPT_TCP, key,
+                                       timeout * 3, timeout, 0, zone->task,
+                                       stub_callback, stub, &zone->request);
        if (result != ISC_R_SUCCESS) {
                zone_debuglog(zone, me, 1,
                              "dns_request_createvia() failed: %s",
@@ -13668,6 +13869,7 @@ got_transfer_quota(isc_task_t *task, isc_event_t *event) {
        isc_sockaddr_t masteraddr;
        isc_time_t now;
        const char *soa_before = "";
+       isc_dscp_t dscp = -1;
 
        UNUSED(task);
 
@@ -13744,6 +13946,7 @@ got_transfer_quota(isc_task_t *task, isc_event_t *event) {
         * Determine if we should attempt to sign the request with TSIG.
         */
        result = ISC_R_NOTFOUND;
+
        /*
         * First, look for a tsig key in the master statement, then
         * try for a server key.
@@ -13764,13 +13967,28 @@ got_transfer_quota(isc_task_t *task, isc_event_t *event) {
                             isc_result_totext(result));
        }
 
+       if (zone->masterdscps != NULL)
+           dscp = zone->masterdscps[zone->curmaster];
+
        LOCK_ZONE(zone);
        masteraddr = zone->masteraddr;
        sourceaddr = zone->sourceaddr;
+       switch (isc_sockaddr_pf(&masteraddr)) {
+       case PF_INET:
+               if (dscp == -1)
+                       dscp = zone->xfrsource4dscp;
+               break;
+       case PF_INET6:
+               if (dscp == -1)
+                       dscp = zone->xfrsource6dscp;
+               break;
+       default:
+               INSIST(0);
+       };
        UNLOCK_ZONE(zone);
        INSIST(isc_sockaddr_pf(&masteraddr) == isc_sockaddr_pf(&sourceaddr));
-       result = dns_xfrin_create2(zone, xfrtype, &masteraddr, &sourceaddr,
-                                  zone->tsigkey, zone->mctx,
+       result = dns_xfrin_create3(zone, xfrtype, &masteraddr, &sourceaddr,
+                                  dscp, zone->tsigkey, zone->mctx,
                                   zone->zmgr->timermgr, zone->zmgr->socketmgr,
                                   zone->task, zone_xfrdone, &zone->xfr);
        if (result == ISC_R_SUCCESS) {
@@ -13826,6 +14044,7 @@ static isc_result_t
 sendtomaster(dns_forward_t *forward) {
        isc_result_t result;
        isc_sockaddr_t src;
+       isc_dscp_t dscp = -1;
 
        LOCK_ZONE(forward->zone);
 
@@ -13849,21 +14068,23 @@ sendtomaster(dns_forward_t *forward) {
        switch (isc_sockaddr_pf(&forward->addr)) {
        case PF_INET:
                src = forward->zone->xfrsource4;
+               dscp = forward->zone->xfrsource4dscp;
                break;
        case PF_INET6:
                src = forward->zone->xfrsource6;
+               dscp = forward->zone->xfrsource6dscp;
                break;
        default:
                result = ISC_R_NOTIMPLEMENTED;
                goto unlock;
        }
-       result = dns_request_createraw(forward->zone->view->requestmgr,
-                                      forward->msgbuf,
-                                      &src, &forward->addr,
-                                      DNS_REQUESTOPT_TCP, 15 /* XXX */,
-                                      forward->zone->task,
-                                      forward_callback, forward,
-                                      &forward->request);
+       result = dns_request_createraw4(forward->zone->view->requestmgr,
+                                      forward->msgbuf,
+                                      &src, &forward->addr, dscp,
+                                      DNS_REQUESTOPT_TCP, 15 /* XXX */,
+                                      0, 0, forward->zone->task,
+                                      forward_callback, forward,
+                                      &forward->request);
        if (result == ISC_R_SUCCESS) {
                if (!ISC_LINK_LINKED(forward, link))
                        ISC_LIST_APPEND(forward->zone->forwards, forward, link);
index b3a863e182d9aa74b04c50bfb600cf946ea8d2ea..a8bccbcd609e2e659d8432a301e192a8bbc169a4 100644 (file)
 #define isc_socket_gettype isc__socket_gettype
 #define isc_socket_isbound isc__socket_isbound
 #define isc_socket_ipv6only isc__socket_ipv6only
+#define isc_socket_dscp isc__socket_dscp
 #define isc_socket_setname isc__socket_setname
 #define isc_socketmgr_getmaxsockets isc__socketmgr_getmaxsockets
 #define isc_socketmgr_setstats isc__socketmgr_setstats
index 53291c656bf8381d23b6cb304954c8b18a12dcdf..80e0351bcc864f5c28a8f5ef613ec67b36d7fdea 100644 (file)
@@ -177,6 +177,7 @@ struct isc_socketevent {
        struct in6_pktinfo      pktinfo;        /*%< ipv6 pktinfo */
        isc_uint32_t            attributes;     /*%< see below */
        isc_eventdestructor_t   destroy;        /*%< original destructor */
+       unsigned int            dscp;           /*%< UDP dscp value */
 };
 
 typedef struct isc_socket_newconnev isc_socket_newconnev_t;
@@ -203,6 +204,7 @@ struct isc_socket_connev {
  * _TIMESTAMP: The timestamp member is valid.
  * _PKTINFO:   The pktinfo member is valid.
  * _MULTICAST: The UDP packet was received via a multicast transmission.
+ * _DSCP:      The UDP DSCP value is valid.
  */
 #define ISC_SOCKEVENTATTR_ATTACHED             0x80000000U /* internal */
 #define ISC_SOCKEVENTATTR_TRUNC                        0x00800000U /* public */
@@ -210,6 +212,7 @@ struct isc_socket_connev {
 #define ISC_SOCKEVENTATTR_TIMESTAMP            0x00200000U /* public */
 #define ISC_SOCKEVENTATTR_PKTINFO              0x00100000U /* public */
 #define ISC_SOCKEVENTATTR_MULTICAST            0x00080000U /* public */
+#define ISC_SOCKEVENTATTR_DSCP                 0x00040000U /* public */
 /*@}*/
 
 #define ISC_SOCKEVENT_ANYEVENT  (0)
@@ -314,6 +317,7 @@ typedef struct isc_socketmethods {
        isc_result_t            (*dup)(isc_socket_t *socket,
                                  isc_socket_t **socketp);
        int             (*getfd)(isc_socket_t *socket);
+       void            (*dscp)(isc_socket_t *socket, isc_dscp_t dscp);
 } isc_socketmethods_t;
 
 /*%
@@ -1073,6 +1077,24 @@ isc_socket_ipv6only(isc_socket_t *sock, isc_boolean_t yes);
  */
 /*@}*/
 
+void
+isc_socket_dscp(isc_socket_t *sock, isc_dscp_t dscp);
+/*%<
+ * Sets the Differentiated Services Code Point (DSCP) field for packets
+ * transmitted on this socket.  If 'dscp' is -1, return immediately.
+ *
+ * Requires:
+ *\li  'sock' is a valid socket.
+ */
+
+isc_socketevent_t *
+isc_socket_socketevent(isc_mem_t *mctx, void *sender,
+                      isc_eventtype_t eventtype, isc_taskaction_t action,
+                      const void *arg);
+/*%<
+ * Get a isc_socketevent_t to be used with isc_socket_sendto2(), etc.
+ */
+
 void
 isc_socket_cleanunix(isc_sockaddr_t *addr, isc_boolean_t active);
 
index a082dd59e184604a97b040f2d01e5039613aacc8..bbd664434d22e3126e3fee0cf454d403a707b3a5 100644 (file)
@@ -50,6 +50,7 @@ typedef struct isc_buffer             isc_buffer_t;           /*%< Buffer */
 typedef ISC_LIST(isc_buffer_t)         isc_bufferlist_t;       /*%< Buffer List */
 typedef struct isc_constregion         isc_constregion_t;      /*%< Const region */
 typedef struct isc_consttextregion     isc_consttextregion_t;  /*%< Const Text Region */
+typedef isc_int16_t                    isc_dscp_t;             /*%< Diffserv code point */
 typedef struct isc_entropy             isc_entropy_t;          /*%< Entropy */
 typedef struct isc_entropysource       isc_entropysource_t;    /*%< Entropy Source */
 typedef struct isc_event               isc_event_t;            /*%< Event */
index 1fba3e0ac19ace1a918b5a20cba42bd8726c4c71..3c6422ad734f34d3172d29bcfa68e522ed69ea26 100644 (file)
@@ -202,6 +202,13 @@ isc_socket_ipv6only(isc_socket_t *sock, isc_boolean_t yes) {
        sock->methods->ipv6only(sock, yes);
 }
 
+void
+isc_socket_dscp(isc_socket_t *sock, isc_dscp_t dscp) {
+       REQUIRE(ISCAPI_SOCKET_VALID(sock));
+
+       sock->methods->dscp(sock, dscp);
+}
+
 isc_sockettype_t
 isc_socket_gettype(isc_socket_t *sock) {
        REQUIRE(ISCAPI_SOCKET_VALID(sock));
index 89e115769c4b297c615921a8e1978268f79d7670..cc5dca0ee40cde234360fd0dbd5b62b83d32bb9d 100644 (file)
@@ -37,13 +37,13 @@ LIBS =              @LIBS@ @ATFLIBS@
 OBJS =         isctest.@O@
 SRCS =         isctest.c taskpool_test.c socket_test.c hash_test.c \
                sockaddr_test.c symtab_test.c task_test.c queue_test.c \
-               parse_test.c pool_test.c regex_test.c
+               parse_test.c pool_test.c regex_test.c socket_test.c
 
 SUBDIRS =
 TARGETS =      taskpool_test@EXEEXT@ socket_test@EXEEXT@ hash_test@EXEEXT@ \
                sockaddr_test@EXEEXT@ symtab_test@EXEEXT@ task_test@EXEEXT@ \
                queue_test@EXEEXT@ parse_test@EXEEXT@ pool_test@EXEEXT@ \
-               regex_test@EXEEXT@
+               regex_test@EXEEXT@ socket_test@EXEEXT@
 
 @BIND9_MAKE_RULES@
 
index 41b09fce6e0b3d13e4be15631599983f52e44760..d8ef00996a913200c7a78ebdc6b24e33cc346933 100644 (file)
@@ -91,7 +91,7 @@ create_managers() {
        CHECK(isc_socketmgr_create(mctx, &socketmgr));
        return (ISC_R_SUCCESS);
 
 cleanup:
+ cleanup:
        cleanup_managers();
        return (result);
 }
index 724d79df2bd1fe4c46fa93dead3ecf22a6af48cd..f316c610275bd3e83b666e06a921ced2d3453b98 100644 (file)
 #include "../task_p.h"
 #include "isctest.h"
 
+static isc_boolean_t recv_dscp;
+static unsigned int recv_dscp_value;
+
 /*
  * Helper functions
  */
+
 typedef struct {
        isc_boolean_t done;
        isc_result_t result;
+       isc_socket_t *socket;
 } completion_t;
 
 static void
 completion_init(completion_t *completion) {
        completion->done = ISC_FALSE;
+       completion->socket = NULL;
+}
+
+static void
+accept_done(isc_task_t *task, isc_event_t *event) {
+       isc_socket_newconnev_t *nevent = (isc_socket_newconnev_t *)event;
+       completion_t *completion = event->ev_arg;
+
+       UNUSED(task);
+
+       completion->result = nevent->result;
+       completion->done = ISC_TRUE;
+       if (completion->result == ISC_R_SUCCESS)
+               completion->socket = nevent->newsocket;
+       
+       isc_event_free(&event);
 }
 
 static void
@@ -53,6 +74,11 @@ event_done(isc_task_t *task, isc_event_t *event) {
        dev = (isc_socketevent_t *) event;
        completion->result = dev->result;
        completion->done = ISC_TRUE;
+       if ((dev->attributes & ISC_SOCKEVENTATTR_DSCP) != 0) {
+               recv_dscp = ISC_TRUE;
+               recv_dscp_value = dev->dscp;;
+       } else
+               recv_dscp = ISC_FALSE;
        isc_event_free(&event);
 }
 
@@ -71,6 +97,49 @@ waitfor(completion_t *completion) {
        return (ISC_R_FAILURE);
 }
 
+#if 0
+static isc_result_t
+waitfor(completion_t *completion) {
+       int i = 0;
+       while (!completion->done && i++ < 5000) {
+               waitbody();
+       }
+       if (completion->done)
+               return (ISC_R_SUCCESS);
+       return (ISC_R_FAILURE);
+}
+#endif
+
+static void
+waitbody() {
+#ifndef ISC_PLATFORM_USETHREADS
+       struct timeval tv;
+       isc_socketwait_t *swait = NULL;
+
+       while (isc__taskmgr_ready(taskmgr))
+               isc__taskmgr_dispatch(taskmgr);
+       if (socketmgr != NULL) {
+               tv.tv_sec = 0;
+               tv.tv_usec = 1000 ;
+               if (isc__socketmgr_waitevents(socketmgr, &tv, &swait) > 0)
+                       isc__socketmgr_dispatch(socketmgr, swait);
+       } else
+#endif
+               isc_test_nap(1000);
+}
+
+static isc_result_t
+waitfor2(completion_t *c1, completion_t *c2) {
+       int i = 0;
+
+       while (!(c1->done && c2->done) && i++ < 5000) {
+               waitbody();
+       }
+       if (c1->done && c2->done)
+               return (ISC_R_SUCCESS);
+       return (ISC_R_FAILURE);
+}
+
 /*
  * Individual unit tests
  */
@@ -243,13 +312,454 @@ ATF_TC_BODY(udp_dup, tc) {
        isc_test_end();
 }
 
+/* Test TCP sendto/recv (IPv4) */
+ATF_TC(udp_dscp_v4);
+ATF_TC_HEAD(udp_dscp_v4, tc) {
+       atf_tc_set_md_var(tc, "descr", "UDP DSCP IPV4");
+}
+ATF_TC_BODY(udp_dscp_v4, tc) {
+       isc_result_t result;
+       isc_sockaddr_t addr1, addr2;
+       struct in_addr in;
+       isc_socket_t *s1 = NULL, *s2 = NULL;
+       isc_task_t *task = NULL;
+       char sendbuf[BUFSIZ], recvbuf[BUFSIZ];
+       completion_t completion;
+       isc_region_t r;
+       isc_socketevent_t *socketevent;
+
+       UNUSED(tc);
+
+       result = isc_test_begin(NULL, ISC_TRUE);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+       /*
+        * Create two sockets: 127.0.0.1/5444 and 127.0.0.1/5445, talking to
+        * each other.
+        */
+       in.s_addr = inet_addr("127.0.0.1");
+       isc_sockaddr_fromin(&addr1, &in, 5444);
+       isc_sockaddr_fromin(&addr2, &in, 5445);
+
+       result = isc_socket_create(socketmgr, PF_INET, isc_sockettype_udp, &s1);
+       ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS, "%s",
+                          isc_result_totext(result));
+       result = isc_socket_bind(s1, &addr1, ISC_SOCKET_REUSEADDRESS);
+       ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS, "%s",
+                          isc_result_totext(result));
+
+       result = isc_socket_create(socketmgr, PF_INET, isc_sockettype_udp, &s2);
+       ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS, "%s",
+                          isc_result_totext(result));
+       result = isc_socket_bind(s2, &addr2, ISC_SOCKET_REUSEADDRESS);
+       ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS, "%s",
+                          isc_result_totext(result));
+
+       result = isc_task_create(taskmgr, 0, &task);
+       ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS, "%s",
+                          isc_result_totext(result));
+
+       strcpy(sendbuf, "Hello");
+       r.base = (void *) sendbuf;
+       r.length = strlen(sendbuf) + 1;
+
+       completion_init(&completion);
+       
+       socketevent = isc_socket_socketevent(mctx, s1, ISC_SOCKEVENT_SENDDONE,
+                                            event_done, &completion);
+       ATF_REQUIRE(socketevent != NULL);
+
+       if ((isc_net_probedscp() & ISC_NET_DSCPPKTV4) != 0) {
+               socketevent->dscp = 056; /* EF */
+               socketevent->attributes |= ISC_SOCKEVENTATTR_DSCP;
+       } else if ((isc_net_probedscp() & ISC_NET_DSCPSETV4) != 0) {
+               isc_socket_dscp(s1, 056);  /* EF */
+               socketevent->dscp = 0;
+               socketevent->attributes &= ~ISC_SOCKEVENTATTR_DSCP;
+       }
+
+       recv_dscp = ISC_FALSE;
+       recv_dscp_value = 0;
+
+       result = isc_socket_sendto2(s1, &r, task, &addr2, NULL, socketevent, 0);
+       ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS, "%s",
+                          isc_result_totext(result));
+       waitfor(&completion);
+       ATF_CHECK(completion.done);
+       ATF_CHECK_EQ(completion.result, ISC_R_SUCCESS);
+
+       r.base = (void *) recvbuf;
+       r.length = BUFSIZ;
+       completion_init(&completion);
+       result = isc_socket_recv(s2, &r, 1, task, event_done, &completion);
+       ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+       waitfor(&completion);
+       ATF_CHECK(completion.done);
+       ATF_CHECK_EQ(completion.result, ISC_R_SUCCESS);
+       ATF_CHECK_STREQ(recvbuf, "Hello");
+
+       if ((isc_net_probedscp() & ISC_NET_DSCPRECVV4) != 0) {
+               ATF_CHECK(recv_dscp);
+               ATF_CHECK_EQ(recv_dscp_value, 056);
+       } else 
+               ATF_CHECK(!recv_dscp);
+       isc_task_detach(&task);
+
+       isc_socket_detach(&s1);
+       isc_socket_detach(&s2);
+
+       isc_test_end();
+}
+
+/* Test TCP sendto/recv (IPv4) */
+ATF_TC(udp_dscp_v6);
+ATF_TC_HEAD(udp_dscp_v6, tc) {
+       atf_tc_set_md_var(tc, "descr", "udp dscp ipv6");
+}
+ATF_TC_BODY(udp_dscp_v6, tc) {
+       isc_result_t result;
+       isc_sockaddr_t addr1, addr2;
+       struct in6_addr in6;
+       isc_socket_t *s1 = NULL, *s2 = NULL;
+       isc_task_t *task = NULL;
+       char sendbuf[BUFSIZ], recvbuf[BUFSIZ];
+       completion_t completion;
+       isc_region_t r;
+       isc_socketevent_t *socketevent;
+
+       UNUSED(tc);
+
+       result = isc_test_begin(NULL, ISC_TRUE);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+       /*
+        * Create two sockets: ::1/5444 and ::1/5445, talking to
+        * each other.
+        */
+       inet_pton(AF_INET6, "::1", &in6.s6_addr);
+       isc_sockaddr_fromin6(&addr1, &in6, 5444);
+       isc_sockaddr_fromin6(&addr2, &in6, 5445);
+
+       result = isc_socket_create(socketmgr, PF_INET6, isc_sockettype_udp,
+                                  &s1);
+       ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS, "%s",
+                        isc_result_totext(result));
+       result = isc_socket_bind(s1, &addr1, ISC_SOCKET_REUSEADDRESS);
+       ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS, "%s",
+                        isc_result_totext(result));
+
+       result = isc_socket_create(socketmgr, PF_INET6, isc_sockettype_udp,
+                                  &s2);
+       ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS, "%s",
+                        isc_result_totext(result));
+       result = isc_socket_bind(s2, &addr2, ISC_SOCKET_REUSEADDRESS);
+       ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS, "%s",
+                        isc_result_totext(result));
+
+       result = isc_task_create(taskmgr, 0, &task);
+       ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS, "%s",
+                        isc_result_totext(result));
+
+       strcpy(sendbuf, "Hello");
+       r.base = (void *) sendbuf;
+       r.length = strlen(sendbuf) + 1;
+
+       completion_init(&completion);
+       
+       socketevent = isc_socket_socketevent(mctx, s1, ISC_SOCKEVENT_SENDDONE,
+                                            event_done, &completion);
+       ATF_REQUIRE(socketevent != NULL);
+
+       if ((isc_net_probedscp() & ISC_NET_DSCPPKTV6) != 0) {
+               socketevent->dscp = 056; /* EF */
+               socketevent->attributes = ISC_SOCKEVENTATTR_DSCP;
+       } else if ((isc_net_probedscp() & ISC_NET_DSCPSETV6) != 0)
+               isc_socket_dscp(s1, 056);  /* EF */
+
+       recv_dscp = ISC_FALSE;
+       recv_dscp_value = 0;
+
+       result = isc_socket_sendto2(s1, &r, task, &addr2, NULL, socketevent, 0);
+       ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+       waitfor(&completion);
+       ATF_CHECK(completion.done);
+       ATF_CHECK_EQ(completion.result, ISC_R_SUCCESS);
+
+       r.base = (void *) recvbuf;
+       r.length = BUFSIZ;
+       completion_init(&completion);
+       result = isc_socket_recv(s2, &r, 1, task, event_done, &completion);
+       ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+       waitfor(&completion);
+       ATF_CHECK(completion.done);
+       ATF_CHECK_EQ(completion.result, ISC_R_SUCCESS);
+       ATF_CHECK_STREQ(recvbuf, "Hello");
+       if ((isc_net_probedscp() & ISC_NET_DSCPRECVV6) != 0) {
+               ATF_CHECK(recv_dscp);
+               ATF_CHECK_EQ(recv_dscp_value, 056);
+       } else
+               ATF_CHECK(!recv_dscp);
+
+       isc_task_detach(&task);
+
+       isc_socket_detach(&s1);
+       isc_socket_detach(&s2);
+
+       isc_test_end();
+}
+
+/* Test TCP sendto/recv (IPv4) */
+ATF_TC(tcp_dscp_v4);
+ATF_TC_HEAD(tcp_dscp_v4, tc) {
+       atf_tc_set_md_var(tc, "descr", "tcp dscp ipv4");
+}
+ATF_TC_BODY(tcp_dscp_v4, tc) {
+       isc_result_t result;
+       isc_sockaddr_t addr1;
+       struct in_addr in;
+       isc_socket_t *s1 = NULL, *s2 = NULL, *s3 = NULL;
+       isc_task_t *task = NULL;
+       char sendbuf[BUFSIZ], recvbuf[BUFSIZ];
+       completion_t completion, completion2;
+       isc_region_t r;
+
+       UNUSED(tc);
+
+       result = isc_test_begin(NULL, ISC_TRUE);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+       /*
+        * Create two sockets: 127.0.0.1/5444, talking to each other.
+        */
+       in.s_addr = inet_addr("127.0.0.1");
+       isc_sockaddr_fromin(&addr1, &in, 5444);
+
+       result = isc_socket_create(socketmgr, PF_INET, isc_sockettype_tcp, &s1);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+       result = isc_socket_bind(s1, &addr1, ISC_SOCKET_REUSEADDRESS);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+       result = isc_socket_listen(s1, 3);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+       result = isc_socket_create(socketmgr, PF_INET, isc_sockettype_tcp, &s2);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+       result = isc_task_create(taskmgr, 0, &task);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+       completion_init(&completion2);
+       result = isc_socket_accept(s1, task, accept_done, &completion2);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+       completion_init(&completion);
+       result = isc_socket_connect(s2, &addr1, task, event_done, &completion);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+       waitfor2(&completion, &completion2);
+       ATF_CHECK(completion.done);
+       ATF_CHECK_EQ(completion.result, ISC_R_SUCCESS);
+       ATF_CHECK(completion2.done);
+       ATF_CHECK_EQ(completion2.result, ISC_R_SUCCESS);
+       s3 = completion2.socket;
+
+       isc_socket_dscp(s2, 056);  /* EF */
+
+       strcpy(sendbuf, "Hello");
+       r.base = (void *) sendbuf;
+       r.length = strlen(sendbuf) + 1;
+
+       recv_dscp = ISC_FALSE;
+       recv_dscp_value = 0;
+
+       completion_init(&completion);
+       result = isc_socket_sendto(s2, &r, task, event_done, &completion,
+                                  NULL, NULL);
+       ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+       waitfor(&completion);
+       ATF_CHECK(completion.done);
+       ATF_CHECK_EQ(completion.result, ISC_R_SUCCESS);
+
+       r.base = (void *) recvbuf;
+       r.length = BUFSIZ;
+       completion_init(&completion);
+       result = isc_socket_recv(s3, &r, 1, task, event_done, &completion);
+       ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+       waitfor(&completion);
+       ATF_CHECK(completion.done);
+       ATF_CHECK_EQ(completion.result, ISC_R_SUCCESS);
+       ATF_CHECK_STREQ(recvbuf, "Hello");
+
+       if ((isc_net_probedscp() & ISC_NET_DSCPRECVV4) != 0) {
+               if (recv_dscp)
+                       ATF_CHECK_EQ(recv_dscp_value, 056);
+       } else
+               ATF_CHECK(!recv_dscp);
+
+       isc_task_detach(&task);
+
+       isc_socket_detach(&s1);
+       isc_socket_detach(&s2);
+       isc_socket_detach(&s3);
+
+       isc_test_end();
+}
+
+/* Test TCP sendto/recv (IPv6) */
+ATF_TC(tcp_dscp_v6);
+ATF_TC_HEAD(tcp_dscp_v6, tc) {
+       atf_tc_set_md_var(tc, "descr", "tcp dscp ipv6");
+}
+ATF_TC_BODY(tcp_dscp_v6, tc) {
+       isc_result_t result;
+       isc_sockaddr_t addr1;
+       struct in6_addr in6;
+       isc_socket_t *s1 = NULL, *s2 = NULL, *s3 = NULL;
+       isc_task_t *task = NULL;
+       char sendbuf[BUFSIZ], recvbuf[BUFSIZ];
+       completion_t completion, completion2;
+       isc_region_t r;
+
+       UNUSED(tc);
+
+       result = isc_test_begin(NULL, ISC_TRUE);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+       /*
+        * Create two sockets: ::1/5444, talking to each other.
+        */
+       inet_pton(AF_INET6, "::1", &in6.s6_addr);
+       isc_sockaddr_fromin6(&addr1, &in6, 5444);
+
+       result = isc_socket_create(socketmgr, PF_INET6, isc_sockettype_tcp,
+                                  &s1);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+       result = isc_socket_bind(s1, &addr1, ISC_SOCKET_REUSEADDRESS);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+       result = isc_socket_listen(s1, 3);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+       result = isc_socket_create(socketmgr, PF_INET6, isc_sockettype_tcp,
+                                  &s2);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+       result = isc_task_create(taskmgr, 0, &task);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+       completion_init(&completion2);
+       result = isc_socket_accept(s1, task, accept_done, &completion2);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+       completion_init(&completion);
+       result = isc_socket_connect(s2, &addr1, task, event_done, &completion);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+       waitfor2(&completion, &completion2);
+       ATF_CHECK(completion.done);
+       ATF_CHECK_EQ(completion.result, ISC_R_SUCCESS);
+       ATF_CHECK(completion2.done);
+       ATF_CHECK_EQ(completion2.result, ISC_R_SUCCESS);
+       s3 = completion2.socket;
+
+       isc_socket_dscp(s2, 056);  /* EF */
+
+       strcpy(sendbuf, "Hello");
+       r.base = (void *) sendbuf;
+       r.length = strlen(sendbuf) + 1;
+
+       recv_dscp = ISC_FALSE;
+       recv_dscp_value = 0;
+
+       completion_init(&completion);
+       result = isc_socket_sendto(s2, &r, task, event_done, &completion,
+                                  NULL, NULL);
+       ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+       waitfor(&completion);
+       ATF_CHECK(completion.done);
+       ATF_CHECK_EQ(completion.result, ISC_R_SUCCESS);
+
+       r.base = (void *) recvbuf;
+       r.length = BUFSIZ;
+       completion_init(&completion);
+       result = isc_socket_recv(s3, &r, 1, task, event_done, &completion);
+       ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+       waitfor(&completion);
+       ATF_CHECK(completion.done);
+       ATF_CHECK_EQ(completion.result, ISC_R_SUCCESS);
+       ATF_CHECK_STREQ(recvbuf, "Hello");
+
+       if ((isc_net_probedscp() & ISC_NET_DSCPRECVV6) != 0) {
+               /*
+                * IPV6_RECVTCLASS is undefined for TCP however
+                * if we do get it should be the the value we set.
+                */
+               if (recv_dscp)
+                       ATF_CHECK_EQ(recv_dscp_value, 056);
+       } else
+               ATF_CHECK(!recv_dscp);
+
+       isc_task_detach(&task);
+
+       isc_socket_detach(&s1);
+       isc_socket_detach(&s2);
+       isc_socket_detach(&s3);
+
+       isc_test_end();
+}
+
+ATF_TC(net_probedscp);
+ATF_TC_HEAD(net_probedscp, tc) {
+       atf_tc_set_md_var(tc, "descr", "probe dscp capabilities");
+}
+ATF_TC_BODY(net_probedscp, tc) {
+       unsigned int n;
+
+       UNUSED(tc);
+
+       n = isc_net_probedscp();
+       ATF_CHECK((n & ~ISC_NET_DSCPALL) == 0);
+
+       /* ISC_NET_DSCPSETV4 MUST be set if any is set. */
+       if (n & (ISC_NET_DSCPSETV4|ISC_NET_DSCPPKTV4|ISC_NET_DSCPRECVV4))
+               ATF_CHECK_MSG((n & ISC_NET_DSCPSETV4) != 0,
+                             "IPv4:%s%s%s\n",
+                             (n & ISC_NET_DSCPSETV4) ? " set" : " none",
+                             (n & ISC_NET_DSCPPKTV4) ? " packet" : "",
+                             (n & ISC_NET_DSCPRECVV4) ? " receive" : "");
+
+       /* ISC_NET_DSCPSETV6 MUST be set if any is set. */
+       if (n & (ISC_NET_DSCPSETV6|ISC_NET_DSCPPKTV4|ISC_NET_DSCPRECVV4))
+               ATF_CHECK_MSG((n & ISC_NET_DSCPSETV6) != 0,
+                             "IPv6:%s%s%s\n",
+                             (n & ISC_NET_DSCPSETV6) ? " set" : " none",
+                             (n & ISC_NET_DSCPPKTV6) ? " packet" : "",
+                             (n & ISC_NET_DSCPRECVV6) ? " receive" : "");
+
+#if 0
+       fprintf(stdout, "IPv4:%s%s%s\n",
+               (n & ISC_NET_DSCPSETV4) ? " set" : "none",
+               (n & ISC_NET_DSCPPKTV4) ? " packet" : "",
+               (n & ISC_NET_DSCPRECVV4) ? " receive" : "");
+
+       printf(stdout, "IPv6:%s%s%s\n",
+               (n & ISC_NET_DSCPSETV6) ? " set" : "none",
+               (n & ISC_NET_DSCPPKTV6) ? " packet" : "",
+               (n & ISC_NET_DSCPRECVV6) ? " receive" : "");
+#endif
+}
+
 /*
  * Main
  */
 ATF_TP_ADD_TCS(tp) {
        ATF_TP_ADD_TC(tp, udp_sendto);
        ATF_TP_ADD_TC(tp, udp_dup);
+       ATF_TP_ADD_TC(tp, tcp_dscp_v4);
+       ATF_TP_ADD_TC(tp, tcp_dscp_v6);
+       ATF_TP_ADD_TC(tp, udp_dscp_v4);
+       ATF_TP_ADD_TC(tp, udp_dscp_v6);
+       ATF_TP_ADD_TC(tp, net_probedscp);
 
        return (atf_no_error());
 }
-
index efa67c223bef893e0f080c118f80f6f16edaaaad..93b8497088fb9cc1eb9274ddddffccc29303df45 100644 (file)
@@ -324,6 +324,21 @@ isc_net_probeunix(void);
  * Returns whether UNIX domain sockets are supported.
  */
 
+#define ISC_NET_DSCPRECVV4     0x01    /* Can receive sent DSCP value IPv4 */
+#define ISC_NET_DSCPRECVV6     0x02    /* Can receive sent DSCP value IPv6 */
+#define ISC_NET_DSCPSETV4      0x04    /* Can set DSCP on socket IPv4 */
+#define ISC_NET_DSCPSETV6      0x08    /* Can set DSCP on socket IPv6 */
+#define ISC_NET_DSCPPKTV4      0x10    /* Can set DSCP on per packet IPv4 */
+#define ISC_NET_DSCPPKTV6      0x20    /* Can set DSCP on per packet IPv6 */
+#define ISC_NET_DSCPALL                0x3f    /* All valid flags */
+
+unsigned int
+isc_net_probedscp(void);
+/*%<
+ * Probe the level of DSCP support.
+ */
+
 isc_result_t
 isc_net_getudpportrange(int af, in_port_t *low, in_port_t *high);
 /*%<
index 1fedbc438dedabd8ab44a091dd081f1602f799f3..9cca372f1121ee0650fcd67c24a6d6e4913edcd2 100644 (file)
 #include <isc/log.h>
 #include <isc/msgs.h>
 #include <isc/net.h>
+#include <isc/netdb.h>
 #include <isc/once.h>
 #include <isc/strerror.h>
 #include <isc/string.h>
 #include <isc/util.h>
 
+#ifndef ISC_SOCKADDR_LEN_T
+#define ISC_SOCKADDR_LEN_T unsigned int
+#endif
+
 /*%
  * Definitions about UDP port range specification.  This is a total mess of
  * portability variants: some use sysctl (but the sysctl names vary), some use
@@ -111,12 +116,14 @@ static isc_once_t         once_ipv6pktinfo = ISC_ONCE_INIT;
 #endif /* ISC_PLATFORM_HAVEIPV6 */
 
 static isc_once_t      once = ISC_ONCE_INIT;
+static isc_once_t      once_dscp = 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    unix_result = ISC_R_NOTFOUND;
 static isc_result_t    ipv6only_result = ISC_R_NOTFOUND;
 static isc_result_t    ipv6pktinfo_result = ISC_R_NOTFOUND;
+static unsigned int    dscp_result = 0;
 
 static isc_result_t
 try_proto(int domain) {
@@ -397,6 +404,259 @@ isc_net_probe_ipv6pktinfo(void) {
        return (ipv6pktinfo_result);
 }
 
+static inline ISC_SOCKADDR_LEN_T
+cmsg_len(ISC_SOCKADDR_LEN_T len) {
+#ifdef CMSG_LEN
+        return (CMSG_LEN(len));
+#else
+        ISC_SOCKADDR_LEN_T hdrlen;
+
+        /*
+         * Cast NULL so that any pointer arithmetic performed by CMSG_DATA
+         * is correct.
+         */
+        hdrlen = (ISC_SOCKADDR_LEN_T)CMSG_DATA(((struct cmsghdr *)NULL));
+        return (hdrlen + len);
+#endif
+}
+
+static inline ISC_SOCKADDR_LEN_T
+cmsg_space(ISC_SOCKADDR_LEN_T len) {
+#ifdef CMSG_SPACE
+        return (CMSG_SPACE(len));
+#else
+        struct msghdr msg;
+        struct cmsghdr *cmsgp;
+        /*
+         * XXX: The buffer length is an ad-hoc value, but should be enough
+         * in a practical sense.
+         */
+        char dummybuf[sizeof(struct cmsghdr) + 1024];
+
+        memset(&msg, 0, sizeof(msg));
+        msg.msg_control = dummybuf;
+        msg.msg_controllen = sizeof(dummybuf);
+
+        cmsgp = (struct cmsghdr *)dummybuf;
+        cmsgp->cmsg_len = cmsg_len(len);
+
+        cmsgp = CMSG_NXTHDR(&msg, cmsgp);
+        if (cmsgp != NULL)
+                return ((char *)cmsgp - (char *)msg.msg_control);
+        else
+                return (0);
+#endif
+}
+
+#ifdef ISC_NET_BSD44MSGHDR
+static isc_boolean_t
+cmsgsend(int s, int level, int type, struct addrinfo *res) {
+       char strbuf[ISC_STRERRORSIZE];
+       struct sockaddr_storage ss;
+       ISC_SOCKADDR_LEN_T len = sizeof(ss);
+       struct msghdr msg;
+       union {
+               struct cmsghdr h;
+               unsigned char b[256];
+       } control;
+       struct cmsghdr *cmsgp;
+       int dscp = 46;
+       struct iovec iovec = { &iovec, sizeof(iovec) };
+
+       if (bind(s, res->ai_addr, res->ai_addrlen) < 0) {
+               isc__strerror(errno, strbuf, sizeof(strbuf));
+               isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
+                             ISC_LOGMODULE_SOCKET, ISC_LOG_DEBUG(10),
+                             "bind: %s", strbuf);
+               return (ISC_FALSE);
+       }
+
+       if (getsockname(s, (struct sockaddr *)&ss, &len) < 0) {
+               isc__strerror(errno, strbuf, sizeof(strbuf));
+               isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
+                             ISC_LOGMODULE_SOCKET, ISC_LOG_DEBUG(10),
+                             "getsockname: %s", strbuf);
+               return (ISC_FALSE);
+       }
+
+       memset(&msg, 0, sizeof(msg));
+       msg.msg_name = (struct sockaddr *)&ss;
+       msg.msg_namelen = len;
+       msg.msg_iov = &iovec;
+       msg.msg_iovlen = 1;
+        msg.msg_control = (void*)&control;
+        msg.msg_controllen = cmsg_space(sizeof(int));
+        msg.msg_flags = 0;
+
+       cmsgp = msg.msg_control;
+       cmsgp->cmsg_level = level;
+       cmsgp->cmsg_type = type;
+       if (cmsgp->cmsg_type == IP_TOS) {
+               cmsgp->cmsg_len = cmsg_len(sizeof(char));
+               *(unsigned char*)CMSG_DATA(cmsgp) = dscp;
+       } else {
+               cmsgp->cmsg_len = cmsg_len(sizeof(dscp));
+               memcpy(CMSG_DATA(cmsgp), &dscp, sizeof(dscp));
+       }
+
+       if (sendmsg(s, &msg, 0) < 0) {
+               int debug = ISC_LOG_DEBUG(10);
+#ifdef ENOPROTOOPT
+               if (errno != ENOPROTOOPT && errno != EINVAL)
+                       debug = ISC_LOG_NOTICE;
+#endif
+               isc__strerror(errno, strbuf, sizeof(strbuf));
+               if (debug != ISC_LOG_NOTICE) {
+                       isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
+                                     ISC_LOGMODULE_SOCKET, ISC_LOG_DEBUG(10),
+                                     "sendmsg: %s", strbuf);
+               } else {
+                       UNEXPECTED_ERROR(__FILE__, __LINE__,
+                                        "sendmsg() %s: %s",
+                                        isc_msgcat_get(isc_msgcat,
+                                                       ISC_MSGSET_GENERAL,
+                                                       ISC_MSG_FAILED,
+                                                       "failed"),
+                                        strbuf);
+               }
+               return (ISC_FALSE);
+       }
+       
+       return (ISC_TRUE);
+}
+#endif
+
+static void
+try_dscp_v4(void) {
+#ifdef IP_TOS
+       char strbuf[ISC_STRERRORSIZE];
+       struct addrinfo hints, *res0;
+       int s, dscp = 0, n;
+#ifdef IP_RECVTOS
+       int on = 1;
+#endif
+
+       memset(&hints, 0, sizeof(hints));
+       hints.ai_family = AF_INET;
+       hints.ai_socktype = SOCK_DGRAM;
+       hints.ai_protocol = IPPROTO_UDP;
+       hints.ai_flags = AI_PASSIVE;
+
+       n = getaddrinfo("127.0.0.1", NULL, &hints, &res0);
+       if (n != 0 || res0 == NULL) {
+               isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
+                             ISC_LOGMODULE_SOCKET, ISC_LOG_DEBUG(10),
+                             "getaddrinfo(127.0.0.1): %s", gai_strerror(n));
+               return;
+       }
+
+       s = socket(res0->ai_family, res0->ai_socktype, res0->ai_protocol);
+       if (s == -1) {
+               isc__strerror(errno, strbuf, sizeof(strbuf));
+               isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
+                             ISC_LOGMODULE_SOCKET, ISC_LOG_DEBUG(10),
+                             "socket: %s", strbuf);
+               freeaddrinfo(res0);
+               close(s);
+               return;
+       }
+       if (setsockopt(s, IPPROTO_IP, IP_TOS, &dscp, sizeof(dscp)) == 0)
+               dscp_result |= ISC_NET_DSCPSETV4;
+       
+#ifdef IP_RECVTOS
+       on = 1;
+       if (setsockopt(s, IPPROTO_IP, IP_RECVTOS, &on, sizeof(on)) == 0)
+               dscp_result |= ISC_NET_DSCPRECVV4;
+#endif
+#ifdef ISC_NET_BSD44MSGHDR
+#ifndef ISC_CMSG_IP_TOS
+#ifdef __APPLE__
+#define ISC_CMSG_IP_TOS 0      /* As of 10.8.2. */
+#else
+#define ISC_CMSG_IP_TOS 1
+#endif
+#endif
+#if ISC_CMSG_IP_TOS
+       if (cmsgsend(s, IPPROTO_IP, IP_TOS, res0))
+               dscp_result |= ISC_NET_DSCPPKTV4;
+#endif
+#endif
+       freeaddrinfo(res0);
+       close(s);
+#endif
+}
+
+static void
+try_dscp_v6(void) {
+#ifdef ISC_PLATFORM_HAVEIPV6
+#ifdef WANT_IPV6
+#ifdef IPV6_TCLASS
+       char strbuf[ISC_STRERRORSIZE];
+       struct addrinfo hints, *res0;
+       int s, dscp = 0, n;
+#if defined(IPV6_RECVTCLASS)
+       int on = 1;
+#endif
+       
+       memset(&hints, 0, sizeof(hints));
+       hints.ai_family = AF_INET6;
+       hints.ai_socktype = SOCK_DGRAM;
+       hints.ai_protocol = IPPROTO_UDP;
+       hints.ai_flags = AI_PASSIVE;
+
+       n = getaddrinfo("::1", NULL, &hints, &res0);
+       if (n != 0 || res0 == NULL) {
+               isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
+                             ISC_LOGMODULE_SOCKET, ISC_LOG_DEBUG(10),
+                             "getaddrinfo(::1): %s", gai_strerror(n));
+               return;
+       }
+
+       s = socket(res0->ai_family, res0->ai_socktype, res0->ai_protocol);
+       if (s == -1) {
+               isc__strerror(errno, strbuf, sizeof(strbuf));
+               isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
+                             ISC_LOGMODULE_SOCKET, ISC_LOG_DEBUG(10),
+                             "socket: %s", strbuf);
+               freeaddrinfo(res0);
+               return;
+       }
+       if (setsockopt(s, IPPROTO_IPV6, IPV6_TCLASS, &dscp, sizeof(dscp)) == 0)
+               dscp_result |= ISC_NET_DSCPSETV6;
+       
+#ifdef IPV6_RECVTCLASS
+       on = 1;
+       if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVTCLASS, &on, sizeof(on)) == 0)
+               dscp_result |= ISC_NET_DSCPRECVV6;
+#endif
+#ifdef ISC_NET_BSD44MSGHDR
+       if (cmsgsend(s, IPPROTO_IPV6, IPV6_TCLASS, res0))
+               dscp_result |= ISC_NET_DSCPPKTV6;
+#endif
+       freeaddrinfo(res0);
+       close(s);
+#endif
+#endif
+#endif
+}
+
+static void
+try_dscp() {
+       try_dscp_v4();
+       try_dscp_v6();
+}
+
+static void
+initialize_dscp() {
+       RUNTIME_CHECK(isc_once_do(&once_dscp, try_dscp) == ISC_R_SUCCESS);
+}
+
+unsigned int
+isc_net_probedscp(void) {
+       initialize_dscp();
+       return (dscp_result);
+}
+
 #if defined(USE_SYSCTL_PORTRANGE)
 #if defined(HAVE_SYSCTLBYNAME)
 static isc_result_t
index f2efd48bb4dd440801776222106c5c9c6767589d..f4c0c48b838ec8bce2b7bb0727ee16481ea20cff 100644 (file)
@@ -127,6 +127,13 @@ struct isc_socketwait {
 #endif /* USE_KQUEUE */
 #endif /* !USE_WATCHER_THREAD */
 
+/*
+ * Set by the -T dscp option on the command line. If set to a value
+ * other than -1, we check to make sure DSCP values match it, and
+ * assert if not.
+ */
+int isc_dscp_check_value = -1;
+
 /*%
  * Maximum number of allowable open sockets.  This is also the maximum
  * allowable socket file descriptor.
@@ -352,6 +359,7 @@ struct isc__socket {
        isc_sockfdwatch_t       fdwatchcb;
        int                     fdwatchflags;
        isc_task_t              *fdwatchtask;
+       int                     dscp;
 };
 
 #define SOCKET_MANAGER_MAGIC   ISC_MAGIC('I', 'O', 'm', 'g')
@@ -455,6 +463,7 @@ static void build_msghdr_recv(isc__socket_t *, isc_socketevent_t *,
 #ifdef USE_WATCHER_THREAD
 static isc_boolean_t process_ctlfd(isc__socketmgr_t *manager);
 #endif
+static void setdscp(isc__socket_t *sock, isc_dscp_t dscp);
 
 /*%
  * The following can be either static or public, depending on build environment.
@@ -511,6 +520,11 @@ isc__socket_sendto2(isc_socket_t *sock, isc_region_t *region,
                    isc_task_t *task,
                    isc_sockaddr_t *address, struct in6_pktinfo *pktinfo,
                    isc_socketevent_t *event, unsigned int flags);
+isc_socketevent_t *
+isc_socket_socketevent(isc_mem_t *mctx, void *sender,
+                      isc_eventtype_t eventtype, isc_taskaction_t action,
+                      const void *arg);
+
 ISC_SOCKETFUNC_SCOPE void
 isc__socket_cleanunix(isc_sockaddr_t *sockaddr, isc_boolean_t active);
 ISC_SOCKETFUNC_SCOPE isc_result_t
@@ -542,6 +556,8 @@ ISC_SOCKETFUNC_SCOPE isc_boolean_t
 isc__socket_isbound(isc_socket_t *sock);
 ISC_SOCKETFUNC_SCOPE void
 isc__socket_ipv6only(isc_socket_t *sock, isc_boolean_t yes);
+ISC_SOCKETFUNC_SCOPE void
+isc__socket_dscp(isc_socket_t *sock, isc_dscp_t dscp);
 #ifdef BIND9
 #ifdef HAVE_LIBXML2
 ISC_SOCKETFUNC_SCOPE void
@@ -590,7 +606,8 @@ static struct {
                isc__socket_ipv6only,
                isc__socket_fdwatchpoke,
                isc__socket_dup,
-               isc__socket_getfd
+               isc__socket_getfd,
+               isc__socket_dscp
        }
 #ifndef BIND9
        ,
@@ -1308,6 +1325,25 @@ process_cmsg(isc__socket_t *sock, struct msghdr *msg, isc_socketevent_t *dev) {
                }
 #endif
 
+#ifdef IPV6_TCLASS
+               if (cmsgp->cmsg_level == IPPROTO_IPV6
+                   && cmsgp->cmsg_type == IPV6_TCLASS) {
+                       dev->dscp = *(int *)CMSG_DATA(cmsgp);
+                       dev->dscp >>= 2;
+                       dev->attributes |= ISC_SOCKEVENTATTR_DSCP;
+                       goto next;
+               }
+#endif
+
+#ifdef IP_TOS
+               if (cmsgp->cmsg_level == IPPROTO_IP
+                   && cmsgp->cmsg_type == IP_TOS) {
+                       dev->dscp = (int) *(uint8_t *)CMSG_DATA(cmsgp);
+                       dev->dscp >>= 2;
+                       dev->attributes |= ISC_SOCKEVENTATTR_DSCP;
+                       goto next;
+               }
+#endif
        next:
                cmsgp = CMSG_NXTHDR(msg, cmsgp);
        }
@@ -1337,6 +1373,9 @@ build_msghdr_send(isc__socket_t *sock, isc_socketevent_t *dev,
        isc_region_t used;
        size_t write_count;
        size_t skip_count;
+#ifdef ISC_NET_BSD44MSGHDR
+       struct cmsghdr *cmsgp;
+#endif
 
        memset(msg, 0, sizeof(*msg));
 
@@ -1409,7 +1448,6 @@ build_msghdr_send(isc__socket_t *sock, isc_socketevent_t *dev,
 #if defined(IPV6_USE_MIN_MTU)
                int use_min_mtu = 1;    /* -1, 0, 1 */
 #endif
-               struct cmsghdr *cmsgp;
                struct in6_pktinfo *pktinfop;
 
                socket_log(sock, NULL, TRACE,
@@ -1444,6 +1482,83 @@ build_msghdr_send(isc__socket_t *sock, isc_socketevent_t *dev,
                memcpy(CMSG_DATA(cmsgp), &use_min_mtu, sizeof(use_min_mtu));
 #endif
        }
+#ifdef BIND9
+       if (isc_dscp_check_value != -1) {
+               if (sock->type == isc_sockettype_udp)
+                       INSIST((int)dev->dscp == isc_dscp_check_value);
+               if (sock->type == isc_sockettype_tcp)
+                       INSIST(sock->dscp == isc_dscp_check_value);
+       }
+
+       if ((sock->type == isc_sockettype_udp)
+           && ((dev->attributes & ISC_SOCKEVENTATTR_DSCP) != 0)) {
+               int dscp = (dev->dscp << 2) & 0xff;
+
+#ifdef IP_TOS
+               if (sock->pf == AF_INET && 
+                   ((isc_net_probedscp() & ISC_NET_DSCPPKTV4) != 0))
+               {
+                       cmsgp = (struct cmsghdr *)(sock->sendcmsgbuf +
+                                                  msg->msg_controllen);
+                       msg->msg_control = (void *)sock->sendcmsgbuf;
+                       msg->msg_controllen += cmsg_space(sizeof(dscp));
+                       INSIST(msg->msg_controllen <= sock->sendcmsgbuflen);
+
+                       cmsgp->cmsg_level = IPPROTO_IP;
+                       cmsgp->cmsg_type = IP_TOS;
+                       cmsgp->cmsg_len = cmsg_len(sizeof(char));
+                       *(unsigned char*)CMSG_DATA(cmsgp) = dscp;
+               } else if (sock->pf == AF_INET) {
+                       if (setsockopt(sock->fd, IPPROTO_IP, IP_TOS,
+                              (void *)&dscp, sizeof(int)) < 0)
+                       {
+                               char strbuf[ISC_STRERRORSIZE];
+                               isc__strerror(errno, strbuf, sizeof(strbuf));
+                               UNEXPECTED_ERROR(__FILE__, __LINE__,
+                                                "setsockopt(%d, IP_TOS, %.02x)"
+                                                " %s: %s",
+                                                sock->fd, dscp >> 2,
+                                                isc_msgcat_get(isc_msgcat,
+                                                       ISC_MSGSET_GENERAL,
+                                                       ISC_MSG_FAILED,
+                                                       "failed"),
+                                                strbuf);
+                       }
+               }
+#endif
+#ifdef IPPROTO_IPV6
+               if (sock->pf == AF_INET6 && 
+                   ((isc_net_probedscp() & ISC_NET_DSCPPKTV6) != 0))
+               {
+                       cmsgp = (struct cmsghdr *)(sock->sendcmsgbuf +
+                                                  msg->msg_controllen);
+                       msg->msg_control = (void *)sock->sendcmsgbuf;
+                       msg->msg_controllen += cmsg_space(sizeof(dscp));
+                       INSIST(msg->msg_controllen <= sock->sendcmsgbuflen);
+
+                       cmsgp->cmsg_level = IPPROTO_IPV6;
+                       cmsgp->cmsg_type = IPV6_TCLASS;
+                       cmsgp->cmsg_len = cmsg_len(sizeof(dscp));
+                       memcpy(CMSG_DATA(cmsgp), &dscp, sizeof(dscp));
+               } else if (sock->pf == AF_INET6) {
+                       if (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_TCLASS,
+                                      (void *)&dscp, sizeof(int)) < 0) {
+                               char strbuf[ISC_STRERRORSIZE];
+                               isc__strerror(errno, strbuf, sizeof(strbuf));
+                               UNEXPECTED_ERROR(__FILE__, __LINE__,
+                                                "setsockopt(%d, IPV6_TCLASS, "
+                                                "%.02x) %s: %s",
+                                                sock->fd, dscp >> 2,
+                                                isc_msgcat_get(isc_msgcat,
+                                                       ISC_MSGSET_GENERAL,
+                                                       ISC_MSG_FAILED,
+                                                       "failed"),
+                                                strbuf);
+                       }
+               }
+#endif
+       }
+#endif
 #endif /* USE_CMSG && ISC_PLATFORM_HAVEIPV6 */
 #else /* ISC_NET_BSD44MSGHDR */
        msg->msg_accrights = NULL;
@@ -1573,10 +1688,8 @@ build_msghdr_recv(isc__socket_t *sock, isc_socketevent_t *dev,
        msg->msg_controllen = 0;
        msg->msg_flags = 0;
 #if defined(USE_CMSG)
-       if (sock->type == isc_sockettype_udp) {
-               msg->msg_control = sock->recvcmsgbuf;
-               msg->msg_controllen = sock->recvcmsgbuflen;
-       }
+       msg->msg_control = sock->recvcmsgbuf;
+       msg->msg_controllen = sock->recvcmsgbuflen;
 #endif /* USE_CMSG */
 #else /* ISC_NET_BSD44MSGHDR */
        msg->msg_accrights = NULL;
@@ -1612,14 +1725,14 @@ destroy_socketevent(isc_event_t *event) {
 }
 
 static isc_socketevent_t *
-allocate_socketevent(isc__socket_t *sock, isc_eventtype_t eventtype,
-                    isc_taskaction_t action, const void *arg)
+allocate_socketevent(isc_mem_t *mctx, void *sender,
+                    isc_eventtype_t eventtype, isc_taskaction_t action,
+                    const void *arg)
 {
        isc_socketevent_t *ev;
 
-       ev = (isc_socketevent_t *)isc_event_allocate(sock->manager->mctx,
-                                                    sock, eventtype,
-                                                    action, arg,
+       ev = (isc_socketevent_t *)isc_event_allocate(mctx, sender,
+                                                    eventtype, action, arg,
                                                     sizeof(*ev));
 
        if (ev == NULL)
@@ -1634,6 +1747,7 @@ allocate_socketevent(isc__socket_t *sock, isc_eventtype_t eventtype,
        ev->attributes = 0;
        ev->destroy = ev->ev_destroy;
        ev->ev_destroy = destroy_socketevent;
+       ev->dscp = 0;
 
        return (ev);
 }
@@ -1801,8 +1915,7 @@ doio_recv(isc__socket_t *sock, isc_socketevent_t *dev) {
         * If there are control messages attached, run through them and pull
         * out the interesting bits.
         */
-       if (sock->type == isc_sockettype_udp)
-               process_cmsg(sock, &msghdr, dev);
+       process_cmsg(sock, &msghdr, dev);
 
        /*
         * update the buffers (if any) and the i/o count
@@ -2095,6 +2208,7 @@ allocate_socket(isc__socketmgr_t *manager, isc_sockettype_t type,
        sock->manager = manager;
        sock->type = type;
        sock->fd = -1;
+       sock->dscp = -1;
        sock->dupped = 0;
        sock->statsindex = NULL;
 
@@ -2112,6 +2226,9 @@ allocate_socket(isc__socketmgr_t *manager, isc_sockettype_t type,
 #endif
 #if defined(USE_CMSG) && defined(SO_TIMESTAMP)
        cmsgbuflen += cmsg_space(sizeof(struct timeval));
+#endif
+#if defined(USE_CMSG) && (defined(IPV6_TCLASS) || defined(IP_TOS))
+       cmsgbuflen += cmsg_space(sizeof(int));
 #endif
        sock->recvcmsgbuflen = cmsgbuflen;
        if (sock->recvcmsgbuflen != 0U) {
@@ -2132,6 +2249,9 @@ allocate_socket(isc__socketmgr_t *manager, isc_sockettype_t type,
         */
        cmsgbuflen += cmsg_space(sizeof(int));
 #endif
+#endif
+#if defined(USE_CMSG) && (defined(IP_TOS) || defined(IPV6_TCLASS))
+       cmsgbuflen += cmsg_space(sizeof(int));
 #endif
        sock->sendcmsgbuflen = cmsgbuflen;
        if (sock->sendcmsgbuflen != 0U) {
@@ -2589,6 +2709,32 @@ opensocket(isc__socketmgr_t *manager, isc__socket_t *sock,
                }
 #endif
        }
+#ifdef IPV6_RECVTCLASS
+       if ((sock->pf == AF_INET6)
+           && (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_RECVTCLASS,
+                          (void *)&on, sizeof(on)) < 0)) {
+               isc__strerror(errno, strbuf, sizeof(strbuf));
+               UNEXPECTED_ERROR(__FILE__, __LINE__,
+                                "setsockopt(%d, IPV6_RECVTCLASS) "
+                                "%s: %s", sock->fd,
+                                isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+                                               ISC_MSG_FAILED, "failed"),
+                                strbuf);
+       }
+#endif
+#ifdef IP_RECVTOS
+       if ((sock->pf == AF_INET)
+           && (setsockopt(sock->fd, IPPROTO_IP, IP_RECVTOS,
+                          (void *)&on, sizeof(on)) < 0)) {
+               isc__strerror(errno, strbuf, sizeof(strbuf));
+               UNEXPECTED_ERROR(__FILE__, __LINE__,
+                                "setsockopt(%d, IP_RECVTOS) "
+                                "%s: %s", sock->fd,
+                                isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+                                               ISC_MSG_FAILED, "failed"),
+                                strbuf);
+       }
+#endif
 #endif /* defined(USE_CMSG) || defined(SO_RCVBUF) */
 
 setup_done:
@@ -3339,6 +3485,12 @@ internal_accept(isc_task_t *me, isc_event_t *ev) {
                 */
                use_min_mtu(NEWCONNSOCK(dev));
 
+               /*
+                * Ensure DSCP settings are inherited across accept.
+                */
+               if (sock->dscp != -1)
+                       setdscp(NEWCONNSOCK(dev), sock->dscp);
+
                /*
                 * Save away the remote address
                 */
@@ -4617,7 +4769,8 @@ isc__socket_recvv(isc_socket_t *sock0, isc_bufferlist_t *buflist,
 
        INSIST(sock->bound);
 
-       dev = allocate_socketevent(sock, ISC_SOCKEVENT_RECVDONE, action, arg);
+       dev = allocate_socketevent(manager->mctx, sock,
+                                  ISC_SOCKEVENT_RECVDONE, action, arg);
        if (dev == NULL)
                return (ISC_R_NOMEMORY);
 
@@ -4663,7 +4816,8 @@ isc__socket_recv(isc_socket_t *sock0, isc_region_t *region,
 
        INSIST(sock->bound);
 
-       dev = allocate_socketevent(sock, ISC_SOCKEVENT_RECVDONE, action, arg);
+       dev = allocate_socketevent(manager->mctx, sock,
+                                  ISC_SOCKEVENT_RECVDONE, action, arg);
        if (dev == NULL)
                return (ISC_R_NOMEMORY);
 
@@ -4822,7 +4976,8 @@ isc__socket_sendto(isc_socket_t *sock0, isc_region_t *region,
 
        INSIST(sock->bound);
 
-       dev = allocate_socketevent(sock, ISC_SOCKEVENT_SENDDONE, action, arg);
+       dev = allocate_socketevent(manager->mctx, sock,
+                                  ISC_SOCKEVENT_SENDDONE, action, arg);
        if (dev == NULL)
                return (ISC_R_NOMEMORY);
 
@@ -4862,7 +5017,8 @@ isc__socket_sendtov(isc_socket_t *sock0, isc_bufferlist_t *buflist,
        iocount = isc_bufferlist_usedcount(buflist);
        REQUIRE(iocount > 0);
 
-       dev = allocate_socketevent(sock, ISC_SOCKEVENT_SENDDONE, action, arg);
+       dev = allocate_socketevent(manager->mctx, sock,
+                                  ISC_SOCKEVENT_SENDDONE, action, arg);
        if (dev == NULL)
                return (ISC_R_NOMEMORY);
 
@@ -4897,7 +5053,7 @@ isc__socket_sendto2(isc_socket_t *sock0, isc_region_t *region,
        event->region = *region;
        event->n = 0;
        event->offset = 0;
-       event->attributes = 0;
+       event->attributes &= ~ISC_SOCKEVENTATTR_ATTACHED;
 
        return (socket_send(sock, event, task, address, pktinfo, flags));
 }
@@ -5811,6 +5967,84 @@ isc__socket_ipv6only(isc_socket_t *sock0, isc_boolean_t yes) {
 #endif
 }
 
+static void
+setdscp(isc__socket_t *sock, isc_dscp_t dscp) {
+
+       sock->dscp = dscp;
+
+#if defined(IP_TOS) || defined(IPV6_TCLASS)
+       dscp <<= 2;
+#endif
+
+#ifdef IP_TOS
+       if (sock->pf == AF_INET) {
+               if (setsockopt(sock->fd, IPPROTO_IP, IP_TOS,
+                              (void *)&dscp, sizeof(int)) < 0) {
+                       char strbuf[ISC_STRERRORSIZE];
+                       isc__strerror(errno, strbuf, sizeof(strbuf));
+                       UNEXPECTED_ERROR(__FILE__, __LINE__,
+                                        "setsockopt(%d, IP_TOS, %.02x) "
+                                        "%s: %s", sock->fd, dscp >> 2,
+                                        isc_msgcat_get(isc_msgcat,
+                                                       ISC_MSGSET_GENERAL,
+                                                       ISC_MSG_FAILED,
+                                                       "failed"),
+                                        strbuf);
+               }
+       }
+#endif
+#ifdef IPV6_TCLASS
+       if (sock->pf == AF_INET6) {
+               if (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_TCLASS,
+                              (void *)&dscp, sizeof(int)) < 0) {
+                       char strbuf[ISC_STRERRORSIZE];
+                       isc__strerror(errno, strbuf, sizeof(strbuf));
+                       UNEXPECTED_ERROR(__FILE__, __LINE__,
+                                        "setsockopt(%d, IPV6_TCLASS, %.02x) "
+                                        "%s: %s", sock->fd, dscp >> 2,
+                                        isc_msgcat_get(isc_msgcat,
+                                                       ISC_MSGSET_GENERAL,
+                                                       ISC_MSG_FAILED,
+                                                       "failed"),
+                                        strbuf);
+               }
+       }
+#endif
+}
+
+ISC_SOCKETFUNC_SCOPE void
+isc__socket_dscp(isc_socket_t *sock0, isc_dscp_t dscp) {
+       isc__socket_t *sock = (isc__socket_t *)sock0;
+
+       REQUIRE(VALID_SOCKET(sock));
+       REQUIRE(dscp < 0x40);
+
+#if !defined(IP_TOS) && !defined(IPV6_TCLASS)
+       UNUSED(dscp);
+#else
+       if (dscp < 0)
+               return;
+
+       if (isc_dscp_check_value != -1)
+               INSIST(dscp == isc_dscp_check_value);
+#endif
+
+
+#ifdef notyet
+       REQUIRE(!sock->dupped);
+#endif
+
+       setdscp(sock, dscp);
+}
+
+isc_socketevent_t *
+isc_socket_socketevent(isc_mem_t *mctx, void *sender,
+                       isc_eventtype_t eventtype, isc_taskaction_t action,
+                       const void *arg)
+{
+       return (allocate_socketevent(mctx, sender, eventtype, action, arg));
+}
+
 #ifndef USE_WATCHER_THREAD
 /*
  * In our assumed scenario, we can simply use a single static object.
index 43e424d865360e98175c61f1e423a313290440cc..a6701c590d2eb861430b371f50e6e2d1ede0ab50 100644 (file)
@@ -269,6 +269,20 @@ isc_net_probeunix(void);
  *     ISC_R_NOTFOUND
  */
 
+#define ISC_NET_DSCPRECVV4      0x01    /* Can receive sent DSCP value IPv4 */
+#define ISC_NET_DSCPRECVV6      0x02    /* Can receive sent DSCP value IPv6 */
+#define ISC_NET_DSCPSETV4       0x04    /* Can set DSCP on socket IPv4 */
+#define ISC_NET_DSCPSETV6       0x08    /* Can set DSCP on socket IPv6 */
+#define ISC_NET_DSCPPKTV4       0x10    /* Can set DSCP on per packet IPv4 */
+#define ISC_NET_DSCPPKTV6       0x20    /* Can set DSCP on per packet IPv6 */
+#define ISC_NET_DSCPALL         0x3f    /* All valid flags */
+unsigned int
+isc_net_probedscp(void);
+/*%<
+ * Probe the level of DSCP support.
+ */
+
 isc_result_t
 isc_net_probe_ipv6only(void);
 /*
index 24341b8b430542feef0f38a2474c4d1c948836b4..18c093c571e6ad82304ebb24b6e1346c15c5e87a 100644 (file)
@@ -110,6 +110,7 @@ isc__socket_sendto2
 isc__socket_sendtov
 isc__socket_sendv
 isc__socket_setname
+isc__socket_socketevent
 isc__socketmgr_create
 isc__socketmgr_create2
 isc__socketmgr_destroy
@@ -387,6 +388,7 @@ isc_net_getudpportrange
 isc_net_ntop
 isc_net_probe_ipv6only
 isc_net_probe_ipv6pktinfo
+isc_net_probedscp
 isc_net_probeipv4
 isc_net_probeipv6
 isc_net_probeunix
@@ -517,6 +519,7 @@ isc_sockaddr_pf
 isc_sockaddr_setport
 isc_sockaddr_totext
 isc_sockaddr_v6fromin
+isc_socket_dscp
 isc_socketmgr_renderxml
 isc_stats_attach
 isc_stats_create
index a41641e62904edcdf92f5ec0743cf87cec3d87fd..1526fbfde269f5a369f72f32fabab9b312c88e2c 100644 (file)
@@ -331,3 +331,8 @@ isc_net_enableipv6(void) {
        if (ipv6_result == ISC_R_DISABLED)
                ipv6_result = ISC_R_SUCCESS;
 }
+
+unsigned int
+isc_net_probedscp() {
+       return (0);
+}
index f015974c596a4475e8cb1ec19758ab9ecd43501e..2c2c3976f43b3b74f33428cae3532886bc74dcdf 100644 (file)
@@ -1061,13 +1061,13 @@ destroy_socketevent(isc_event_t *event) {
 }
 
 static isc_socketevent_t *
-allocate_socketevent(isc_socket_t *sock, isc_eventtype_t eventtype,
-                    isc_taskaction_t action, const void *arg)
+allocate_socketevent(isc_mem_t *mctx, isc_socket_t *sock,
+                    isc_eventtype_t eventtype, isc_taskaction_t action,
+                    const void *arg)
 {
        isc_socketevent_t *ev;
 
-       ev = (isc_socketevent_t *)isc_event_allocate(sock->manager->mctx,
-                                                    sock, eventtype,
+       ev = (isc_socketevent_t *)isc_event_allocate(mctx, sock, eventtype,
                                                     action, arg,
                                                     sizeof(*ev));
        if (ev == NULL)
@@ -2840,7 +2840,8 @@ isc__socket_recvv(isc_socket_t *sock, isc_bufferlist_t *buflist,
 
        INSIST(sock->bound);
 
-       dev = allocate_socketevent(sock, ISC_SOCKEVENT_RECVDONE, action, arg);
+       dev = allocate_socketevent(manager->mctx, sock,
+                                  ISC_SOCKEVENT_RECVDONE, action, arg);
        if (dev == NULL) {
                UNLOCK(&sock->lock);
                return (ISC_R_NOMEMORY);
@@ -2901,7 +2902,8 @@ isc__socket_recv(isc_socket_t *sock, isc_region_t *region,
 
        INSIST(sock->bound);
 
-       dev = allocate_socketevent(sock, ISC_SOCKEVENT_RECVDONE, action, arg);
+       dev = allocate_socketevent(manager->mctx, sock,
+                                  ISC_SOCKEVENT_RECVDONE, action, arg);
        if (dev == NULL) {
                UNLOCK(&sock->lock);
                return (ISC_R_NOMEMORY);
@@ -3064,7 +3066,8 @@ isc__socket_sendto(isc_socket_t *sock, isc_region_t *region,
 
        INSIST(sock->bound);
 
-       dev = allocate_socketevent(sock, ISC_SOCKEVENT_SENDDONE, action, arg);
+       dev = allocate_socketevent(manager->mctx, sock,
+                                  ISC_SOCKEVENT_SENDDONE, action, arg);
        if (dev == NULL) {
                UNLOCK(&sock->lock);
                return (ISC_R_NOMEMORY);
@@ -3118,7 +3121,8 @@ isc__socket_sendtov(isc_socket_t *sock, isc_bufferlist_t *buflist,
        iocount = isc_bufferlist_usedcount(buflist);
        REQUIRE(iocount > 0);
 
-       dev = allocate_socketevent(sock, ISC_SOCKEVENT_SENDDONE, action, arg);
+       dev = allocate_socketevent(manager->mctx, sock,
+                                  ISC_SOCKEVENT_SENDDONE, action, arg);
        if (dev == NULL) {
                UNLOCK(&sock->lock);
                return (ISC_R_NOMEMORY);
@@ -3803,6 +3807,34 @@ isc__socket_ipv6only(isc_socket_t *sock, isc_boolean_t yes) {
 #endif
 }
 
+void
+isc__socket_dscp(isc_socket_t *sock, unsigned int dscp) {
+#if !defined(IP_TOS) && !defined(IPV6_TCLASS)
+       UNUSED(dscp);
+#else
+       if (dscp < 0)
+               return;
+
+       dscp <<= 2;
+       dscp &= 0xff;
+#endif
+
+       REQUIRE(VALID_SOCKET(sock));
+
+#ifdef IP_TOS
+       if (sock->pf == AF_INET) {
+               (void)setsockopt(sock->fd, IPPROTO_IP, IP_TOS,
+                                (char *)&dscp, sizeof(dscp));
+       }
+#endif
+#ifdef IPV6_TCLASS
+       if (sock->pf == AF_INET6) {
+               (void)setsockopt(sock->fd, IPPROTO_IPV6, IPV6_TCLASS,
+                                (char *)&dscp, sizeof(dscp));
+       }
+#endif
+}
+
 void
 isc__socket_cleanunix(isc_sockaddr_t *addr, isc_boolean_t active) {
        UNUSED(addr);
@@ -3864,6 +3896,14 @@ isc___socketmgr_maxudp(isc_socketmgr_t *manager, int maxudp) {
        UNUSED(maxudp);
 }
 
+isc_socketevent_t *
+isc__socket_socketevent(isc_mem_t *mctx, void *sender,
+                       isc_eventtype_t eventtype, isc_taskaction_t action,
+                       const void *arg)
+{
+        return (allocate_socketevent(mctx, sender, eventtype, action, arg));
+}
+
 #ifdef HAVE_LIBXML2
 
 static const char *
index b21a3d86babc6f5ea1f67242285bcfe6d9cba217..a68884b371223df85c06e233948beb268156c477 100644 (file)
@@ -303,6 +303,20 @@ cfg_obj_assockaddr(const cfg_obj_t *obj);
  *      if necessary.
  */
 
+isc_dscp_t
+cfg_obj_getdscp(const cfg_obj_t *obj);
+/*%<
+ * Returns the DSCP value of a configuration object representing a
+ * socket address.
+ *
+ * Requires:
+ * \li     'obj' points to a valid configuration object of a 
+ *         socket address type.
+ *
+ * Returns:
+ * \li     DSCP value associated with a sockaddr, or -1.
+ */
+
 isc_boolean_t
 cfg_obj_isnetprefix(const cfg_obj_t *obj);
 /*%<
index 2d7080c24c40054ed16fb4901e3e33a35d02de8b..a5d51bd1f4755a821dc958d7db94bd0d7dcd5798 100644 (file)
@@ -157,6 +157,10 @@ struct cfg_obj {
                cfg_list_t      list;
                cfg_obj_t **    tuple;
                isc_sockaddr_t  sockaddr;
+               struct {
+                       isc_sockaddr_t  sockaddr;
+                       isc_dscp_t      dscp;
+               } sockaddrdscp;
                cfg_netprefix_t netprefix;
        }               value;
        isc_refcount_t  references;     /*%< reference counter */
@@ -237,6 +241,7 @@ struct cfg_parser {
 #define CFG_ADDR_V4PREFIXOK    0x00000002
 #define CFG_ADDR_V6OK          0x00000004
 #define CFG_ADDR_WILDOK                0x00000008
+#define CFG_ADDR_DSCPOK                0x00000010
 #define CFG_ADDR_MASK          (CFG_ADDR_V6OK|CFG_ADDR_V4OK)
 /*@}*/
 
@@ -267,6 +272,7 @@ LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_qstring;
 LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_astring;
 LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_ustring;
 LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_sockaddr;
+LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_sockaddrdscp;
 LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_netaddr;
 LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_netaddr4;
 LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_netaddr4wild;
@@ -325,6 +331,9 @@ cfg_lookingat_netaddr(cfg_parser_t *pctx, unsigned int flags);
 isc_result_t
 cfg_parse_rawport(cfg_parser_t *pctx, unsigned int flags, in_port_t *port);
 
+isc_result_t
+cfg_parse_dscp(cfg_parser_t *pctx, isc_dscp_t *dscp);
+
 isc_result_t
 cfg_parse_sockaddr(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret);
 
index fe47334ef573381e53ccc1a5acbe66168877ee01..8b194c154f942ffc2639b6c46d2f2fd952e03d38 100644 (file)
@@ -97,6 +97,7 @@ static cfg_type_t cfg_type_acl;
 static cfg_type_t cfg_type_addrmatchelt;
 static cfg_type_t cfg_type_bracketed_aml;
 static cfg_type_t cfg_type_bracketed_namesockaddrkeylist;
+static cfg_type_t cfg_type_bracketed_dscpsockaddrlist;
 static cfg_type_t cfg_type_bracketed_sockaddrlist;
 static cfg_type_t cfg_type_bracketed_sockaddrnameportlist;
 static cfg_type_t cfg_type_controls;
@@ -118,6 +119,7 @@ static cfg_type_t cfg_type_optional_class;
 static cfg_type_t cfg_type_optional_facility;
 static cfg_type_t cfg_type_optional_keyref;
 static cfg_type_t cfg_type_optional_port;
+static cfg_type_t cfg_type_optional_dscp;
 static cfg_type_t cfg_type_options;
 static cfg_type_t cfg_type_portiplist;
 static cfg_type_t cfg_type_querysource4;
@@ -181,11 +183,15 @@ static cfg_type_t cfg_type_tkey_dhkey = {
 
 static cfg_tuplefielddef_t listenon_fields[] = {
        { "port", &cfg_type_optional_port, 0 },
+       { "dscp", &cfg_type_optional_dscp, 0 },
        { "acl", &cfg_type_bracketed_aml, 0 },
        { NULL, NULL, 0 }
 };
+
 static cfg_type_t cfg_type_listenon = {
-       "listenon", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, &cfg_rep_tuple, listenon_fields };
+       "listenon", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
+       &cfg_rep_tuple, listenon_fields
+};
 
 /*% acl */
 
@@ -202,6 +208,7 @@ static cfg_type_t cfg_type_acl = {
 static cfg_tuplefielddef_t masters_fields[] = {
        { "name", &cfg_type_astring, 0 },
        { "port", &cfg_type_optional_port, 0 },
+       { "dscp", &cfg_type_optional_dscp, 0 },
        { "addresses", &cfg_type_bracketed_namesockaddrkeylist, 0 },
        { NULL, NULL, 0 }
 };
@@ -234,6 +241,7 @@ static cfg_type_t cfg_type_bracketed_namesockaddrkeylist = {
 
 static cfg_tuplefielddef_t namesockaddrkeylist_fields[] = {
        { "port", &cfg_type_optional_port, 0 },
+       { "dscp", &cfg_type_optional_dscp, 0 },
        { "addresses", &cfg_type_bracketed_namesockaddrkeylist, 0 },
        { NULL, NULL, 0 }
 };
@@ -248,7 +256,8 @@ static cfg_type_t cfg_type_namesockaddrkeylist = {
  */
 static cfg_tuplefielddef_t portiplist_fields[] = {
        { "port", &cfg_type_optional_port, 0 },
-       { "addresses", &cfg_type_bracketed_sockaddrlist, 0 },
+       { "dscp", &cfg_type_optional_dscp, 0 },
+       { "addresses", &cfg_type_bracketed_dscpsockaddrlist, 0 },
        { NULL, NULL, 0 }
 };
 static cfg_type_t cfg_type_portiplist = {
@@ -547,13 +556,20 @@ static cfg_tuplefielddef_t checknames_fields[] = {
 };
 
 static cfg_type_t cfg_type_checknames = {
-       "checknames", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, &cfg_rep_tuple,
-       checknames_fields
+       "checknames", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
+       &cfg_rep_tuple, checknames_fields
+};
+
+static cfg_type_t cfg_type_bracketed_dscpsockaddrlist = {
+       "bracketed_sockaddrlist", cfg_parse_bracketed_list,
+       cfg_print_bracketed_list, cfg_doc_bracketed_list, &cfg_rep_list,
+       &cfg_type_sockaddrdscp
 };
 
 static cfg_type_t cfg_type_bracketed_sockaddrlist = {
-       "bracketed_sockaddrlist", cfg_parse_bracketed_list, cfg_print_bracketed_list, cfg_doc_bracketed_list,
-       &cfg_rep_list, &cfg_type_sockaddr
+       "bracketed_sockaddrlist", cfg_parse_bracketed_list,
+       cfg_print_bracketed_list, cfg_doc_bracketed_list, &cfg_rep_list,
+       &cfg_type_sockaddr
 };
 
 static const char *autodnssec_enums[] = { "allow", "maintain", "off", NULL };
@@ -592,8 +608,15 @@ static cfg_type_t cfg_type_zonestat = {
 };
 
 static cfg_type_t cfg_type_rrsetorder = {
-       "rrsetorder", cfg_parse_bracketed_list, cfg_print_bracketed_list, cfg_doc_bracketed_list,
-       &cfg_rep_list, &cfg_type_rrsetorderingelement
+       "rrsetorder", cfg_parse_bracketed_list, cfg_print_bracketed_list,
+       cfg_doc_bracketed_list, &cfg_rep_list, &cfg_type_rrsetorderingelement
+};
+
+static keyword_type_t dscp_kw = { "dscp", &cfg_type_uint32 };
+
+static cfg_type_t cfg_type_optional_dscp = {
+       "optional_dscp", parse_optional_keyvalue, print_keyvalue,
+       doc_optional_keyvalue, &cfg_rep_uint32, &dscp_kw
 };
 
 static keyword_type_t port_kw = { "port", &cfg_type_uint32 };
@@ -934,6 +957,7 @@ options_clauses[] = {
        { "session-keyalg", &cfg_type_astring, 0 },
        { "deallocate-on-exit", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE },
        { "directory", &cfg_type_qstring, CFG_CLAUSEFLAG_CALLBACK },
+       { "dscp", &cfg_type_uint32, 0 },
        { "dump-file", &cfg_type_qstring, 0 },
        { "fake-iquery", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE },
        { "files", &cfg_type_size, 0 },
@@ -2033,7 +2057,9 @@ parse_keyvalue(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
 }
 
 static isc_result_t
-parse_optional_keyvalue(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
+parse_optional_keyvalue(cfg_parser_t *pctx, const cfg_type_t *type,
+                       cfg_obj_t **ret)
+{
        return (parse_maybe_optional_keyvalue(pctx, type, ISC_TRUE, ret));
 }
 
@@ -2379,9 +2405,11 @@ parse_querysource(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
        isc_result_t result;
        cfg_obj_t *obj = NULL;
        isc_netaddr_t netaddr;
-       in_port_t port;
+       in_port_t port = 0;
+       isc_dscp_t dscp = -1;
        unsigned int have_address = 0;
        unsigned int have_port = 0;
+       unsigned int have_dscp = 0;
        const unsigned int *flagp = type->of;
 
        if ((*flagp & CFG_ADDR_V4OK) != 0)
@@ -2391,8 +2419,6 @@ parse_querysource(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
        else
                INSIST(0);
 
-       port = 0;
-
        for (;;) {
                CHECK(cfg_peektoken(pctx, 0));
                if (pctx->token.type == isc_tokentype_string) {
@@ -2412,11 +2438,20 @@ parse_querysource(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
                                                        CFG_ADDR_WILDOK,
                                                        &port));
                                have_port++;
-                       } else if (have_port == 0 && have_address == 0) {
+                       } else if (strcasecmp(TOKEN_STRING(pctx), "dscp") == 0)
+                       {
+                               /* read "dscp" */
+                               CHECK(cfg_gettoken(pctx, 0));
+                               CHECK(cfg_parse_dscp(pctx, &dscp));
+                               have_dscp++;
+                       } else if (have_port == 0 && have_dscp == 0 &&
+                                  have_address == 0)
+                       {
                                return (cfg_parse_sockaddr(pctx, type, ret));
                        } else {
                                cfg_parser_error(pctx, CFG_LOG_NEAR,
-                                            "expected 'address' or 'port'");
+                                            "expected 'address', 'port', "
+                                            "or 'dscp'");
                                return (ISC_R_UNEXPECTEDTOKEN);
                        }
                } else
@@ -2428,8 +2463,14 @@ parse_querysource(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
                return (ISC_R_UNEXPECTEDTOKEN);
        }
 
+       if (have_dscp > 1) {
+               cfg_parser_error(pctx, 0, "expected at most one dscp");
+               return (ISC_R_UNEXPECTEDTOKEN);
+       }
+
        CHECK(cfg_create_obj(pctx, &cfg_type_querysource, &obj));
        isc_sockaddr_fromnetaddr(&obj->value.sockaddr, &netaddr, port);
+       obj->value.sockaddrdscp.dscp = dscp;
        *ret = obj;
        return (ISC_R_SUCCESS);
 
@@ -2447,10 +2488,16 @@ print_querysource(cfg_printer_t *pctx, const cfg_obj_t *obj) {
        cfg_print_rawaddr(pctx, &na);
        cfg_print_cstr(pctx, " port ");
        cfg_print_rawuint(pctx, isc_sockaddr_getport(&obj->value.sockaddr));
+       if (obj->value.sockaddrdscp.dscp != -1) {
+               cfg_print_cstr(pctx, " dscp ");
+               cfg_print_rawuint(pctx, obj->value.sockaddrdscp.dscp);
+       }
 }
 
-static unsigned int sockaddr4wild_flags = CFG_ADDR_WILDOK | CFG_ADDR_V4OK;
-static unsigned int sockaddr6wild_flags = CFG_ADDR_WILDOK | CFG_ADDR_V6OK;
+static unsigned int sockaddr4wild_flags = CFG_ADDR_WILDOK | CFG_ADDR_V4OK |
+                                         CFG_ADDR_DSCPOK;
+static unsigned int sockaddr6wild_flags = CFG_ADDR_WILDOK | CFG_ADDR_V6OK |
+                                         CFG_ADDR_DSCPOK;
 
 static cfg_type_t cfg_type_querysource4 = {
        "querysource4", parse_querysource, NULL, cfg_doc_terminal,
@@ -2780,7 +2827,7 @@ static cfg_type_t cfg_type_logfile = {
        &cfg_rep_tuple, logfile_fields
 };
 
-/*% An IPv4 address with optional port, "*" accepted as wildcard. */
+/*% An IPv4 address with optional dscp and port, "*" accepted as wildcard. */
 static cfg_type_t cfg_type_sockaddr4wild = {
        "sockaddr4wild", cfg_parse_sockaddr, cfg_print_sockaddr,
        cfg_doc_sockaddr, &cfg_rep_sockaddr, &sockaddr4wild_flags
@@ -2923,8 +2970,10 @@ LIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_sessionkey = {
 static cfg_tuplefielddef_t nameport_fields[] = {
        { "name", &cfg_type_astring, 0 },
        { "port", &cfg_type_optional_port, 0 },
+       { "dscp", &cfg_type_optional_dscp, 0 },
        { NULL, NULL, 0 }
 };
+
 static cfg_type_t cfg_type_nameport = {
        "nameport", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
        &cfg_rep_tuple, nameport_fields
@@ -2937,14 +2986,20 @@ doc_sockaddrnameport(cfg_printer_t *pctx, const cfg_type_t *type) {
        cfg_print_cstr(pctx, "<quoted_string>");
        cfg_print_chars(pctx, " ", 1);
        cfg_print_cstr(pctx, "[ port <integer> ]");
+       cfg_print_chars(pctx, " ", 1);
+       cfg_print_cstr(pctx, "[ dscp <integer> ]");
        cfg_print_chars(pctx, " | ", 3);
        cfg_print_cstr(pctx, "<ipv4_address>");
        cfg_print_chars(pctx, " ", 1);
        cfg_print_cstr(pctx, "[ port <integer> ]");
+       cfg_print_chars(pctx, " ", 1);
+       cfg_print_cstr(pctx, "[ dscp <integer> ]");
        cfg_print_chars(pctx, " | ", 3);
        cfg_print_cstr(pctx, "<ipv6_address>");
        cfg_print_chars(pctx, " ", 1);
        cfg_print_cstr(pctx, "[ port <integer> ]");
+       cfg_print_chars(pctx, " ", 1);
+       cfg_print_cstr(pctx, "[ dscp <integer> ]");
        cfg_print_chars(pctx, " )", 2);
 }
 
@@ -2970,6 +3025,8 @@ parse_sockaddrnameport(cfg_parser_t *pctx, const cfg_type_t *type,
                                            &obj->value.tuple[0]));
                        CHECK(cfg_parse_obj(pctx, fields[1].type,
                                            &obj->value.tuple[1]));
+                       CHECK(cfg_parse_obj(pctx, fields[2].type,
+                                           &obj->value.tuple[2]));
                        *ret = obj;
                        obj = NULL;
                }
index de0fa31ee2288adb929b82bdd1479a6cc66765e8..52a65b33fdc578642813a43986f56fd1ac6a26ef 100644 (file)
@@ -1860,6 +1860,28 @@ cfg_print_rawaddr(cfg_printer_t *pctx, const isc_netaddr_t *na) {
        cfg_print_chars(pctx, isc_buffer_base(&buf), isc_buffer_usedlength(&buf));
 }
 
+isc_result_t
+cfg_parse_dscp(cfg_parser_t *pctx, isc_dscp_t *dscp) {
+       isc_result_t result;
+
+       CHECK(cfg_gettoken(pctx, ISC_LEXOPT_NUMBER));
+
+       if (pctx->token.type != isc_tokentype_number) {
+               cfg_parser_error(pctx, CFG_LOG_NEAR,
+                            "expected number");
+               return (ISC_R_UNEXPECTEDTOKEN);
+       }
+       if (pctx->token.value.as_ulong > 63) {
+               cfg_parser_error(pctx, CFG_LOG_NEAR,
+                            "dscp out of range");
+               return (ISC_R_RANGE);
+       }
+       *dscp = (isc_dscp_t)(pctx->token.value.as_ulong);
+       return (ISC_R_SUCCESS);
+ cleanup:
+       return (result);
+}
+
 /* netaddr */
 
 static unsigned int netaddr_flags = CFG_ADDR_V4OK | CFG_ADDR_V6OK;
@@ -2030,17 +2052,43 @@ parse_sockaddrsub(cfg_parser_t *pctx, const cfg_type_t *type,
        isc_result_t result;
        isc_netaddr_t netaddr;
        in_port_t port = 0;
+       isc_dscp_t dscp = -1;
        cfg_obj_t *obj = NULL;
+       int have_port = 0, have_dscp = 0;
 
        CHECK(cfg_create_obj(pctx, type, &obj));
        CHECK(cfg_parse_rawaddr(pctx, flags, &netaddr));
-       CHECK(cfg_peektoken(pctx, 0));
-       if (pctx->token.type == isc_tokentype_string &&
-           strcasecmp(TOKEN_STRING(pctx), "port") == 0) {
-               CHECK(cfg_gettoken(pctx, 0)); /* read "port" */
-               CHECK(cfg_parse_rawport(pctx, flags, &port));
+       for (;;) {
+               CHECK(cfg_peektoken(pctx, 0));
+               if (pctx->token.type == isc_tokentype_string) {
+                       if (strcasecmp(TOKEN_STRING(pctx), "port") == 0) {
+                               CHECK(cfg_gettoken(pctx, 0)); /* read "port" */
+                               CHECK(cfg_parse_rawport(pctx, flags, &port));
+                               ++have_port;
+                       } else if ((flags & CFG_ADDR_DSCPOK) != 0 &&
+                                  strcasecmp(TOKEN_STRING(pctx), "dscp") == 0)
+                       {
+                               CHECK(cfg_gettoken(pctx, 0)); /* read "dscp" */
+                               CHECK(cfg_parse_dscp(pctx, &dscp));
+                               ++have_dscp;
+                       } else
+                               break;
+               } else
+                       break;
+       }
+       if (have_port > 1) {
+               cfg_parser_error(pctx, 0, "expected at most one port");
+               result = ISC_R_UNEXPECTEDTOKEN;
+               goto cleanup;
+       }
+
+       if (have_dscp > 1) {
+               cfg_parser_error(pctx, 0, "expected at most one dscp");
+               result = ISC_R_UNEXPECTEDTOKEN;
+               goto cleanup;
        }
        isc_sockaddr_fromnetaddr(&obj->value.sockaddr, &netaddr, port);
+       obj->value.sockaddrdscp.dscp = dscp;
        *ret = obj;
        return (ISC_R_SUCCESS);
 
@@ -2055,6 +2103,13 @@ cfg_type_t cfg_type_sockaddr = {
        &cfg_rep_sockaddr, &sockaddr_flags
 };
 
+static unsigned int sockaddrdscp_flags = CFG_ADDR_V4OK | CFG_ADDR_V6OK |
+                                        CFG_ADDR_DSCPOK;
+cfg_type_t cfg_type_sockaddrdscp = {
+       "sockaddr", cfg_parse_sockaddr, cfg_print_sockaddr, cfg_doc_sockaddr,
+       &cfg_rep_sockaddr, &sockaddrdscp_flags
+};
+
 isc_result_t
 cfg_parse_sockaddr(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
        const unsigned int *flagp = type->of;
@@ -2075,6 +2130,10 @@ cfg_print_sockaddr(cfg_printer_t *pctx, const cfg_obj_t *obj) {
                cfg_print_chars(pctx, " port ", 6);
                cfg_print_rawuint(pctx, port);
        }
+       if (obj->value.sockaddrdscp.dscp != -1) {
+               cfg_print_chars(pctx, " dscp ", 6);
+               cfg_print_rawuint(pctx, obj->value.sockaddrdscp.dscp);
+       }
 }
 
 void
@@ -2105,6 +2164,9 @@ cfg_doc_sockaddr(cfg_printer_t *pctx, const cfg_type_t *type) {
        } else {
                cfg_print_cstr(pctx, "[ port <integer> ]");
        }
+       if ((*flagp & CFG_ADDR_DSCPOK) != 0) {
+               cfg_print_cstr(pctx, " [ dscp <integer> ]");
+       }
 }
 
 isc_boolean_t
@@ -2119,6 +2181,12 @@ cfg_obj_assockaddr(const cfg_obj_t *obj) {
        return (&obj->value.sockaddr);
 }
 
+isc_dscp_t
+cfg_obj_getdscp(const cfg_obj_t *obj) {
+       REQUIRE(obj != NULL && obj->type->rep == &cfg_rep_sockaddr);
+       return (obj->value.sockaddrdscp.dscp);
+}
+
 isc_result_t
 cfg_gettoken(cfg_parser_t *pctx, int options) {
        isc_result_t result;
index 98abbcf8e25f3966fd559ec36442243cff09f53d..e5d5bd873a8f1e2b346ffc4556dcd0c5f6cb618c 100644 (file)
@@ -22,6 +22,7 @@ cfg_obj_asuint64
 cfg_obj_attach
 cfg_obj_destroy
 cfg_obj_file
+cfg_obj_getdscp
 cfg_obj_isboolean
 cfg_obj_islist
 cfg_obj_ismap