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 <mmich...@redhat.com> --- ovn/controller/pinctrl.c | 17 +++++++++++----- tests/ovn.at | 51 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 5 deletions(-) diff --git a/ovn/controller/pinctrl.c b/ovn/controller/pinctrl.c index faeb3f932..6654d7f49 100644 --- a/ovn/controller/pinctrl.c +++ b/ovn/controller/pinctrl.c @@ -916,11 +916,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 == ntohs(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 1632a981b..00d26e757 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -6865,6 +6865,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 @@ -7060,6 +7092,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]) -- 2.13.6 _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev