summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Michelson <mmichels@redhat.com>2018-02-09 09:11:00 -0600
committerBen Pfaff <blp@ovn.org>2018-02-09 09:59:50 -0800
commit995933f224d3f682541ef060a949986620df5f05 (patch)
tree321b8cb9c53beedd8c90b97e4ba29f5de33b7bc9
parent0d87cb5b6757b81be4951c6aae20eb0c38999216 (diff)
downloadopenvswitch-995933f224d3f682541ef060a949986620df5f05.tar.gz
ovn: Allow DNS lookups over IPv6
There was a bug in DNS request handling where the incoming packet was assumed to be IPv4. The result was that for the outgoing packet, we would attempt to write the IPv4 checksum and total length into what was actually an IPv6 header. This resulted in the source IPv6 address getting corrupted. Later, the source and destination IPv6 addresses would get swapped, resulting in the DNS response being sent to a nonsense destination. With this change, we check the ethertype of the packet to determine what l3 information to write, and where to write it. A test is also included that verifies that this works as expected. Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=1539608 Signed-off-by: Mark Michelson <mmichels@redhat.com> Signed-off-by: Ben Pfaff <blp@ovn.org>
-rw-r--r--ovn/controller/pinctrl.c17
-rw-r--r--tests/ovn.at51
2 files changed, 63 insertions, 5 deletions
diff --git a/ovn/controller/pinctrl.c b/ovn/controller/pinctrl.c
index af2ea15ea..2bc17c847 100644
--- a/ovn/controller/pinctrl.c
+++ b/ovn/controller/pinctrl.c
@@ -897,11 +897,18 @@ pinctrl_handle_dns_lookup(
out_udp->udp_len = htons(new_l4_size);
out_udp->udp_csum = 0;
- struct ip_header *out_ip = dp_packet_l3(&pkt_out);
- out_ip->ip_tot_len = htons(pkt_out.l4_ofs - pkt_out.l3_ofs + new_l4_size);
- /* Checksum needs to be initialized to zero. */
- out_ip->ip_csum = 0;
- out_ip->ip_csum = csum(out_ip, sizeof *out_ip);
+ struct eth_header *eth = dp_packet_data(&pkt_out);
+ if (eth->eth_type == htons(ETH_TYPE_IP)) {
+ struct ip_header *out_ip = dp_packet_l3(&pkt_out);
+ out_ip->ip_tot_len = htons(pkt_out.l4_ofs - pkt_out.l3_ofs
+ + new_l4_size);
+ /* Checksum needs to be initialized to zero. */
+ out_ip->ip_csum = 0;
+ out_ip->ip_csum = csum(out_ip, sizeof *out_ip);
+ } else {
+ struct ovs_16aligned_ip6_hdr *nh = dp_packet_l3(&pkt_out);
+ nh->ip6_plen = htons(new_l4_size);
+ }
pin->packet = dp_packet_data(&pkt_out);
pin->packet_len = dp_packet_size(&pkt_out);
diff --git a/tests/ovn.at b/tests/ovn.at
index d825115b6..2355b9d40 100644
--- a/tests/ovn.at
+++ b/tests/ovn.at
@@ -6763,6 +6763,38 @@ test_dns() {
as hv1 ovs-appctl netdev-dummy/receive hv1-vif$inport $request
}
+test_dns6() {
+ local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5 dns_reply=$6
+ local dns_query_data=$7
+ shift; shift; shift; shift; shift; shift; shift;
+ # Packet size => UDP header (8) +
+ # DNS data (header + query)
+ ip_len=`expr 8 + ${#dns_query_data} / 2`
+ udp_len=$ip_len
+ ip_len=$(printf "%x" $ip_len)
+ udp_len=$(printf "%x" $udp_len)
+ local request=${dst_mac}${src_mac}86dd6000000000${ip_len}11ff${src_ip}${dst_ip}
+ request=${request}9234003500${udp_len}0000
+ #dns data
+ request=${request}${dns_query_data}
+
+ if test $dns_reply != 0; then
+ local dns_reply=$1
+ ip_len=`expr 8 + ${#dns_reply} / 2`
+ udp_len=$ip_len
+ ip_len=$(printf "%x" $ip_len)
+ udp_len=$(printf "%x" $udp_len)
+ local reply=${src_mac}${dst_mac}86dd6000000000${ip_len}11ff${dst_ip}${src_ip}
+ reply=${reply}0035923400${udp_len}0000${dns_reply}
+ echo $reply >> $inport.expected
+ else
+ for outport; do
+ echo $request >> $outport.expected
+ done
+ fi
+ as hv1 ovs-appctl netdev-dummy/receive hv1-vif$inport $request
+}
+
AT_CAPTURE_FILE([ofctl_monitor0.log])
as hv1 ovs-ofctl monitor br-int resume --detach --no-chdir \
--pidfile=ovs-ofctl0.pid 2> ofctl_monitor0.log
@@ -6958,6 +6990,25 @@ reset_pcap_file hv1-vif2 hv1/vif2
rm -f 1.expected
rm -f 2.expected
+# Try DNS query over IPv6
+set_dns_params vm1
+src_ip=aef00000000000000000000000000004
+dst_ip=aef00000000000000000000000000001
+dns_reply=1
+test_dns6 1 f00000000001 f000000000f0 $src_ip $dst_ip $dns_reply $dns_req_data $dns_resp_data
+
+# NXT_RESUMEs should be 9.
+OVS_WAIT_UNTIL([test 9 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`])
+
+$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/vif1-tx.pcap > 1.packets
+cat 1.expected > expout
+AT_CHECK([cat 1.packets], [0], [expout])
+
+reset_pcap_file hv1-vif1 hv1/vif1
+reset_pcap_file hv1-vif2 hv1/vif2
+rm -f 1.expected
+rm -f 2.expected
+
as hv1
OVS_APP_EXIT_AND_WAIT([ovn-controller])
OVS_APP_EXIT_AND_WAIT([ovs-vswitchd])