Skip to content

Commit

Permalink
pinctrl: dns: Ignore additional records.
Browse files Browse the repository at this point in the history
EDNS is backwards compatible so it's safe to just ignore additional ARs.

Reported-at: ovn-org#228
Reported-at: https://issues.redhat.com/browse/FDP-222
Signed-off-by: Dumitru Ceara <[email protected]>
Acked-by: Mark Michelson <[email protected]>
(cherry picked from commit b7fe2c8)
  • Loading branch information
dceara committed Feb 12, 2024
1 parent 6c15e96 commit cb0c918
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 10 deletions.
21 changes: 11 additions & 10 deletions controller/pinctrl.c
Original file line number Diff line number Diff line change
Expand Up @@ -2949,6 +2949,8 @@ dns_build_ptr_answer(
free(encoded_answer);
}

#define DNS_QUERY_TYPE_CLASS_LEN (2 * sizeof(ovs_be16))

/* Called with in the pinctrl_handler thread context. */
static void
pinctrl_handle_dns_lookup(
Expand Down Expand Up @@ -3010,18 +3012,13 @@ pinctrl_handle_dns_lookup(
goto exit;
}

/* Check if there is an additional record present, which is unsupported */
if (in_dns_header->arcount) {
VLOG_DBG_RL(&rl, "Received DNS query with additional records, which"
" is unsupported");
goto exit;
}

struct udp_header *in_udp = dp_packet_l4(pkt_in);
size_t udp_len = ntohs(in_udp->udp_len);
size_t l4_len = dp_packet_l4_size(pkt_in);
uint8_t *l4_start = (uint8_t *) in_udp;
uint8_t *end = (uint8_t *)in_udp + MIN(udp_len, l4_len);
uint8_t *in_dns_data = (uint8_t *)(in_dns_header + 1);
uint8_t *in_dns_data_start = in_dns_data;
uint8_t *in_queryname = in_dns_data;
uint16_t idx = 0;
struct ds query_name;
Expand All @@ -3045,7 +3042,7 @@ pinctrl_handle_dns_lookup(
in_dns_data += idx;

/* Query should have TYPE and CLASS fields */
if (in_dns_data + (2 * sizeof(ovs_be16)) > end) {
if (in_dns_data + DNS_QUERY_TYPE_CLASS_LEN > end) {
ds_destroy(&query_name);
goto exit;
}
Expand All @@ -3059,6 +3056,10 @@ pinctrl_handle_dns_lookup(
goto exit;
}

uint8_t *rest = in_dns_data + DNS_QUERY_TYPE_CLASS_LEN;
uint32_t query_size = rest - in_dns_data_start;
uint32_t query_l4_size = rest - l4_start;

uint64_t dp_key = ntohll(pin->flow_metadata.flow.metadata);
const char *answer_data = NULL;
struct shash_node *iter;
Expand Down Expand Up @@ -3127,7 +3128,7 @@ pinctrl_handle_dns_lookup(
goto exit;
}

uint16_t new_l4_size = ntohs(in_udp->udp_len) + dns_answer.size;
uint16_t new_l4_size = query_l4_size + dns_answer.size;
size_t new_packet_size = pkt_in->l4_ofs + new_l4_size;
struct dp_packet pkt_out;
dp_packet_init(&pkt_out, new_packet_size);
Expand Down Expand Up @@ -3160,7 +3161,7 @@ pinctrl_handle_dns_lookup(
out_dns_header->arcount = 0;

/* Copy the Query section. */
dp_packet_put(&pkt_out, dp_packet_data(pkt_in), dp_packet_size(pkt_in));
dp_packet_put(&pkt_out, dp_packet_data(pkt_in), query_size);

/* Copy the answer sections. */
dp_packet_put(&pkt_out, dns_answer.data, dns_answer.size);
Expand Down
51 changes: 51 additions & 0 deletions tests/ovn.at
Original file line number Diff line number Diff line change
Expand Up @@ -11115,6 +11115,57 @@ OVN_CLEANUP([hv1])
AT_CLEANUP
])

OVN_FOR_EACH_NORTHD([
AT_SETUP([dns lookup : EDNS])
AT_SKIP_IF([test $HAVE_SCAPY = no])
ovn_start

check ovn-nbctl ls-add ls \
-- lsp-add ls lsp \
-- lsp-set-addresses lsp "00:00:00:00:00:01 10.0.0.1"

d=$(ovn-nbctl create dns records={})

check ovn-nbctl set dns $d records:foo.ovn.org="10.0.0.42"
check ovn-nbctl set Logical_switch ls dns_records="$d"

net_add n1
sim_add hv1

as hv1
ovs-vsctl add-br br-phys
ovn_attach n1 br-phys 192.168.0.1
check ovs-vsctl add-port br-int hv1-vif1 -- \
set interface hv1-vif1 external-ids:iface-id=lsp \
options:tx_pcap=hv1/vif1-tx.pcap \
options:rxq_pcap=hv1/vif1-rx.pcap

OVN_POPULATE_ARP
wait_for_ports_up
check ovn-nbctl --wait=hv sync

dns_req=$(fmt_pkt "Ether(dst='00:00:00:00:00:02', src='00:00:00:00:00:01') / \
IP(dst='10.0.0.254', src='10.0.0.1') / \
UDP(sport=42424, dport=53) / \
DNS(rd=1, qd=DNSQR(qname='foo.ovn.org'), arcount=1, ar=[ \
DNSRR(type='OPT', rclass=4096, \
rdata=EDNS0ClientSubnet(source_plen=24, \
address='10.0.0.1'))])")
dns_reply=$(fmt_pkt "Ether(dst='00:00:00:00:00:01', src='00:00:00:00:00:02') / \
IP(dst='10.0.0.1', src='10.0.0.254') / \
UDP(sport=53, dport=42424,chksum=0) / \
DNS(qr=1, qd=DNSQR(qname='foo.ovn.org'), \
an=DNSRR(rrname='foo.ovn.org', type='A', ttl=3600, \
rdata='10.0.0.42'))")
echo ${dns_reply} > expected

as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 ${dns_req}
OVN_CHECK_PACKETS_REMOVE_BROADCAST([hv1/vif1-tx.pcap], [expected])

OVN_CLEANUP([hv1])
AT_CLEANUP
])

OVN_FOR_EACH_NORTHD([
AT_SETUP([4 HV, 1 LS, 1 LR, packet test with HA distributed router gateway port])
ovn_start
Expand Down

0 comments on commit cb0c918

Please sign in to comment.