From a920fb9dc2ff16f32dd73e53469d0febcdcc6c11 Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Tue, 15 Jul 2014 22:40:39 +1000 Subject: [PATCH] 3893. [bug] Peer DSCP values could be returned without being set. [RT #36538] --- CHANGES | 3 + lib/dns/peer.c | 47 +++++++----- lib/dns/tests/Makefile.in | 7 ++ lib/dns/tests/peer_test.c | 145 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 186 insertions(+), 16 deletions(-) create mode 100644 lib/dns/tests/peer_test.c diff --git a/CHANGES b/CHANGES index 1c7a9b3d56..6539e42981 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,6 @@ +3893. [bug] Peer DSCP values could be returned without being set. + [RT #36538] + 3892. [bug] Setting '-t aaaa' in .digrc had unintended side effects. [RT #36452] diff --git a/lib/dns/peer.c b/lib/dns/peer.c index c4df3abafa..40520d7614 100644 --- a/lib/dns/peer.c +++ b/lib/dns/peer.c @@ -34,16 +34,19 @@ /*% * Bit positions in the dns_peer_t structure flags field */ -#define BOGUS_BIT 0 -#define SERVER_TRANSFER_FORMAT_BIT 1 -#define TRANSFERS_BIT 2 -#define PROVIDE_IXFR_BIT 3 -#define REQUEST_IXFR_BIT 4 -#define SUPPORT_EDNS_BIT 5 -#define SERVER_UDPSIZE_BIT 6 -#define SERVER_MAXUDP_BIT 7 -#define REQUEST_NSID_BIT 8 -#define REQUEST_SIT_BIT 9 +#define BOGUS_BIT 0 +#define SERVER_TRANSFER_FORMAT_BIT 1 +#define TRANSFERS_BIT 2 +#define PROVIDE_IXFR_BIT 3 +#define REQUEST_IXFR_BIT 4 +#define SUPPORT_EDNS_BIT 5 +#define SERVER_UDPSIZE_BIT 6 +#define SERVER_MAXUDP_BIT 7 +#define REQUEST_NSID_BIT 8 +#define REQUEST_SIT_BIT 9 +#define NOTIFY_DSCP_BIT 10 +#define TRANSFER_DSCP_BIT 11 +#define QUERY_DSCP_BIT 12 static void peerlist_delete(dns_peerlist_t **list); @@ -749,6 +752,7 @@ dns_peer_setnotifydscp(dns_peer_t *peer, isc_dscp_t dscp) { REQUIRE(dscp < 64); peer->notify_dscp = dscp; + DNS_BIT_SET(NOTIFY_DSCP_BIT, &peer->bitflags); return (ISC_R_SUCCESS); } @@ -757,8 +761,11 @@ 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); + if (DNS_BIT_CHECK(NOTIFY_DSCP_BIT, &peer->bitflags)) { + *dscpp = peer->notify_dscp; + return (ISC_R_SUCCESS); + } + return (ISC_R_NOTFOUND); } isc_result_t @@ -767,6 +774,7 @@ dns_peer_settransferdscp(dns_peer_t *peer, isc_dscp_t dscp) { REQUIRE(dscp < 64); peer->transfer_dscp = dscp; + DNS_BIT_SET(TRANSFER_DSCP_BIT, &peer->bitflags); return (ISC_R_SUCCESS); } @@ -775,8 +783,11 @@ 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); + if (DNS_BIT_CHECK(TRANSFER_DSCP_BIT, &peer->bitflags)) { + *dscpp = peer->transfer_dscp; + return (ISC_R_SUCCESS); + } + return (ISC_R_NOTFOUND); } isc_result_t @@ -785,6 +796,7 @@ dns_peer_setquerydscp(dns_peer_t *peer, isc_dscp_t dscp) { REQUIRE(dscp < 64); peer->query_dscp = dscp; + DNS_BIT_SET(QUERY_DSCP_BIT, &peer->bitflags); return (ISC_R_SUCCESS); } @@ -793,6 +805,9 @@ 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); + if (DNS_BIT_CHECK(QUERY_DSCP_BIT, &peer->bitflags)) { + *dscpp = peer->query_dscp; + return (ISC_R_SUCCESS); + } + return (ISC_R_NOTFOUND); } diff --git a/lib/dns/tests/Makefile.in b/lib/dns/tests/Makefile.in index 8770106199..86e11df781 100644 --- a/lib/dns/tests/Makefile.in +++ b/lib/dns/tests/Makefile.in @@ -48,6 +48,7 @@ SRCS = db_test.c \ keytable_test.c \ master_test.c \ nsec3_test.c \ + peer_test.c \ private_test.c \ rbt_test.c \ rbt_serialize_test.c \ @@ -70,6 +71,7 @@ TARGETS = db_test@EXEEXT@ \ keytable_test@EXEEXT@ \ master_test@EXEEXT@ \ nsec3_test@EXEEXT@ \ + peer_test@EXEEXT@ \ private_test@EXEEXT@ \ rbt_test@EXEEXT@ \ rbt_serialize_test@EXEEXT@ \ @@ -106,6 +108,11 @@ time_test@EXEEXT@: time_test.@O@ dnstest.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} time_test.@O@ dnstest.@O@ ${DNSLIBS} \ ${ISCLIBS} ${LIBS} +peer_test@EXEEXT@: peer_test.@O@ dnstest.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + peer_test.@O@ dnstest.@O@ ${DNSLIBS} \ + ${ISCLIBS} ${LIBS} + private_test@EXEEXT@: private_test.@O@ dnstest.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ private_test.@O@ dnstest.@O@ ${DNSLIBS} \ diff --git a/lib/dns/tests/peer_test.c b/lib/dns/tests/peer_test.c new file mode 100644 index 0000000000..5f5bc538e9 --- /dev/null +++ b/lib/dns/tests/peer_test.c @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2014 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. + */ + +/*! \file */ + +#include + +#include + +#include + +#include + +#include "dnstest.h" + +/* + * Individual unit tests + */ +ATF_TC(dscp); +ATF_TC_HEAD(dscp, tc) { + atf_tc_set_md_var(tc, "descr", + "Test DSCP set/get functions"); +} +ATF_TC_BODY(dscp, tc) { + isc_result_t result; + isc_netaddr_t netaddr; + struct in_addr ina; + dns_peer_t *peer = NULL; + isc_dscp_t dscp; + + result = dns_test_begin(NULL, ISC_TRUE); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + /* + * Create peer structure for the loopback address. + */ + ina.s_addr = INADDR_LOOPBACK; + isc_netaddr_fromin(&netaddr, &ina); + result = dns_peer_new(mctx, &netaddr, &peer); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + /* + * All should be not set on creation. + * 'dscp' should remain unchanged. + */ + dscp = 100; + result = dns_peer_getquerydscp(peer, &dscp); + ATF_REQUIRE_EQ(result, ISC_R_NOTFOUND); + ATF_REQUIRE_EQ(dscp, 100); + + result = dns_peer_getnotifydscp(peer, &dscp); + ATF_REQUIRE_EQ(result, ISC_R_NOTFOUND); + ATF_REQUIRE_EQ(dscp, 100); + + result = dns_peer_gettransferdscp(peer, &dscp); + ATF_REQUIRE_EQ(result, ISC_R_NOTFOUND); + ATF_REQUIRE_EQ(dscp, 100); + + /* + * Test that setting query dscp does not affect the other + * dscp values. 'dscp' should remain unchanged until + * dns_peer_getquerydscp is called. + */ + dscp = 100; + result = dns_peer_setquerydscp(peer, 1); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_peer_getnotifydscp(peer, &dscp); + ATF_REQUIRE_EQ(result, ISC_R_NOTFOUND); + ATF_REQUIRE_EQ(dscp, 100); + + result = dns_peer_gettransferdscp(peer, &dscp); + ATF_REQUIRE_EQ(result, ISC_R_NOTFOUND); + ATF_REQUIRE_EQ(dscp, 100); + + result = dns_peer_getquerydscp(peer, &dscp); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + ATF_REQUIRE_EQ(dscp, 1); + + /* + * Test that setting notify dscp does not affect the other + * dscp values. 'dscp' should remain unchanged until + * dns_peer_getquerydscp is called then should change again + * on dns_peer_getnotifydscp. + */ + dscp = 100; + result = dns_peer_setnotifydscp(peer, 2); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_peer_gettransferdscp(peer, &dscp); + ATF_REQUIRE_EQ(result, ISC_R_NOTFOUND); + ATF_REQUIRE_EQ(dscp, 100); + + result = dns_peer_getquerydscp(peer, &dscp); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + ATF_REQUIRE_EQ(dscp, 1); + + result = dns_peer_getnotifydscp(peer, &dscp); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + ATF_REQUIRE_EQ(dscp, 2); + + /* + * Test that setting notify dscp does not affect the other + * dscp values. Check that appropriate values are returned. + */ + dscp = 100; + result = dns_peer_settransferdscp(peer, 3); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = dns_peer_getquerydscp(peer, &dscp); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + ATF_REQUIRE_EQ(dscp, 1); + + result = dns_peer_getnotifydscp(peer, &dscp); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + ATF_REQUIRE_EQ(dscp, 2); + + result = dns_peer_gettransferdscp(peer, &dscp); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + ATF_REQUIRE_EQ(dscp, 3); + + dns_peer_detach(&peer); + dns_test_end(); +} + +/* + * Main + */ +ATF_TP_ADD_TCS(tp) { + ATF_TP_ADD_TC(tp, dscp); + return (atf_no_error()); +}