From patchwork Mon Apr 20 14:02:27 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mark Michelson X-Patchwork-Id: 1273444 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.138; helo=whitealder.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=RgnJ2SbH; dkim-atps=neutral Received: from whitealder.osuosl.org (smtp1.osuosl.org [140.211.166.138]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 495T162zWCz9s71 for ; Tue, 21 Apr 2020 00:02:49 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by whitealder.osuosl.org (Postfix) with ESMTP id 48B1786D16; Mon, 20 Apr 2020 14:02:47 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from whitealder.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id L4EqPw-Oe4oY; Mon, 20 Apr 2020 14:02:45 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by whitealder.osuosl.org (Postfix) with ESMTP id E582186CC0; Mon, 20 Apr 2020 14:02:45 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id BCBBBC07FF; Mon, 20 Apr 2020 14:02:45 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from hemlock.osuosl.org (smtp2.osuosl.org [140.211.166.133]) by lists.linuxfoundation.org (Postfix) with ESMTP id B4AD3C0177 for ; Mon, 20 Apr 2020 14:02:44 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by hemlock.osuosl.org (Postfix) with ESMTP id A65AA87D0E for ; Mon, 20 Apr 2020 14:02:44 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from hemlock.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id zf5eacwhUicf for ; Mon, 20 Apr 2020 14:02:41 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from us-smtp-delivery-1.mimecast.com (us-smtp-1.mimecast.com [205.139.110.61]) by hemlock.osuosl.org (Postfix) with ESMTPS id B99F187CDB for ; Mon, 20 Apr 2020 14:02:41 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1587391360; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=KnAlSL89NQ6FEm0TMDkUyjtuRFP3+MxNV90hMLxZ0qA=; b=RgnJ2SbHtTX2eLM6QobR4K+cjzP8E/yJO69FE6mbA0AP7s3CduqjQ6+zQnqTJLPpcpl6H0 942pqpSmBRV/MGLl2+ytq17uQW4LOqEB00DWH3ispvsoG/bSZaC6SvUODJYJJoYiE5EFFt y63uCoA9Sskkpsu6rG+5jT1PsDcKXeY= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-206-WbHQYY2uP6q9c1kF0wJnSQ-1; Mon, 20 Apr 2020 10:02:30 -0400 X-MC-Unique: WbHQYY2uP6q9c1kF0wJnSQ-1 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id CBAF01B18BC7 for ; Mon, 20 Apr 2020 14:02:29 +0000 (UTC) Received: from monae.redhat.com (ovpn-113-80.rdu2.redhat.com [10.10.113.80]) by smtp.corp.redhat.com (Postfix) with ESMTP id 010AA3A8 for ; Mon, 20 Apr 2020 14:02:28 +0000 (UTC) From: Mark Michelson To: dev@openvswitch.org Date: Mon, 20 Apr 2020 10:02:27 -0400 Message-Id: <20200420140227.4171953-1-mmichels@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [ovs-dev] [PATCH ovn] DNS: Make DNS lookups case insensitive. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" From RFC 1035 Section 2.3.3: "For all parts of the DNS that are part of the official protocol, all comparisons between character strings (e.g., labels, domain names, etc.) are done in a case-insensitive manner." OVN was using case-sensitive lookups and therefore was not complying. This change makes lookups case insensitive by storing lowercase record names in the southbound database and converting incoming query names to lowercase. Signed-off-by: Mark Michelson Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=1819069 Reported-by: Jianlin Shi --- controller/pinctrl.c | 7 ++++- lib/ovn-util.c | 15 +++++++++++ lib/ovn-util.h | 5 ++++ northd/ovn-northd.c | 15 ++++++++++- ovn-sb.xml | 3 ++- tests/ovn.at | 61 ++++++++++++++++++++++++++++++++------------ 6 files changed, 87 insertions(+), 19 deletions(-) diff --git a/controller/pinctrl.c b/controller/pinctrl.c index 8703641c2..79ae86968 100644 --- a/controller/pinctrl.c +++ b/controller/pinctrl.c @@ -2368,7 +2368,12 @@ pinctrl_handle_dns_lookup( struct dns_data *d = iter->data; for (size_t i = 0; i < d->n_dps; i++) { if (d->dps[i] == dp_key) { - answer_ips = smap_get(&d->records, ds_cstr(&query_name)); + /* DNS records in SBDB are stored in lowercase. Convert to lowercase + * to perform case insensitive lookup + */ + char *query_name_lower = str_tolower(ds_cstr(&query_name)); + answer_ips = smap_get(&d->records, query_name_lower); + free(query_name_lower); if (answer_ips) { break; } diff --git a/lib/ovn-util.c b/lib/ovn-util.c index 514e2489f..1b30c2e9a 100644 --- a/lib/ovn-util.c +++ b/lib/ovn-util.c @@ -21,6 +21,7 @@ #include "openvswitch/ofp-parse.h" #include "ovn-nb-idl.h" #include "ovn-sb-idl.h" +#include VLOG_DEFINE_THIS_MODULE(ovn_util); @@ -550,3 +551,17 @@ ip46_equals(const struct v46_ip *addr1, const struct v46_ip *addr2) (addr1->family == AF_INET ? addr1->ipv4 == addr2->ipv4 : IN6_ARE_ADDR_EQUAL(&addr1->ipv6, &addr2->ipv6))); } + +char * +str_tolower(const char *orig) +{ + char *copy = xmalloc(strlen(orig) + 1); + char *p = copy; + + while (*orig) { + *p++ = tolower(*orig++); + } + *p = '\0'; + + return copy; +} diff --git a/lib/ovn-util.h b/lib/ovn-util.h index 11238f61c..4076e8b9a 100644 --- a/lib/ovn-util.h +++ b/lib/ovn-util.h @@ -124,4 +124,9 @@ struct v46_ip { bool ip46_parse_cidr(const char *str, struct v46_ip *prefix, unsigned int *plen); bool ip46_equals(const struct v46_ip *addr1, const struct v46_ip *addr2); + +/* Returns a lowercase copy of orig. + * Caller must free the returned string. + */ +char *str_tolower(const char *orig); #endif diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c index 616e52bb2..0219a4bb0 100644 --- a/northd/ovn-northd.c +++ b/northd/ovn-northd.c @@ -10706,7 +10706,20 @@ sync_dns_entries(struct northd_context *ctx, struct hmap *datapaths) dns_info->sb_dns, (struct sbrec_datapath_binding **)dns_info->sbs, dns_info->n_sbs); - sbrec_dns_set_records(dns_info->sb_dns, &dns_info->nb_dns->records); + + /* DNS lookups are case-insensitive. Convert records to lowercase so + * we can do consistent lookups when DNS requests arrive + */ + struct smap lower_records = SMAP_INITIALIZER(&lower_records); + struct smap_node *node; + SMAP_FOR_EACH (node, &dns_info->nb_dns->records) { + smap_add_nocopy(&lower_records, xstrdup(node->key), + str_tolower(node->value)); + } + + sbrec_dns_set_records(dns_info->sb_dns, &lower_records); + + smap_destroy(&lower_records); free(dns_info->sbs); free(dns_info); } diff --git a/ovn-sb.xml b/ovn-sb.xml index 72466b97e..5f8da534c 100644 --- a/ovn-sb.xml +++ b/ovn-sb.xml @@ -3597,7 +3597,8 @@ tcp.flags = RST; Key-value pair of DNS records with DNS query name as the key and a string of IP address(es) separated by comma or space as the - value. + value. ovn-northd stores the DNS query name in all lowercase in order to + facilitate case-insensitive lookups.

Example: "vm1.ovn.org" = "10.0.0.4 aef0::4"

diff --git a/tests/ovn.at b/tests/ovn.at index 7858c496e..a52e644f0 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -8357,6 +8357,12 @@ set_dns_params() { # IPv4 address - 10.0.0.4 expected_dns_answer=${query_name}00010001${ttl}00040a000004 ;; + VM1) + # VM1.OVN.ORG + query_name=03564d31034f564e034f524700 + # IPv4 address - 10.0.0.4 + expected_dns_answer=${query_name}00010001${ttl}00040a000004 + ;; vm2) # vm2.ovn.org query_name=03766d32036f766e036f726700 @@ -8519,6 +8525,29 @@ reset_pcap_file hv1-vif2 hv1/vif2 rm -f 1.expected rm -f 2.expected +# Try vm1 again but an all-caps query name + +set_dns_params VM1 +src_ip=`ip_to_hex 10 0 0 6` +dst_ip=`ip_to_hex 10 0 0 1` +dns_reply=1 +test_dns 2 f00000000002 f000000000f0 $src_ip $dst_ip $dns_reply $dns_req_data $dns_resp_data + +# NXT_RESUMEs should be 3. +OVS_WAIT_UNTIL([test 3 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`]) + +$PYTHON "$ovs_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets +cat 2.expected | cut -c -48 > expout +AT_CHECK([cat 2.packets | cut -c -48], [0], [expout]) +# Skipping the IPv4 checksum. +cat 2.expected | cut -c 53- > expout +AT_CHECK([cat 2.packets | cut -c 53-], [0], [expout]) + +reset_pcap_file hv1-vif1 hv1/vif1 +reset_pcap_file hv1-vif2 hv1/vif2 +rm -f 1.expected +rm -f 2.expected + # Clear the query name options for ls1-lp2 ovn-nbctl --wait=hv remove DNS $DNS1 records vm2.ovn.org @@ -8528,8 +8557,8 @@ dst_ip=`ip_to_hex 10 0 0 1` dns_reply=0 test_dns 1 f00000000001 f00000000002 $src_ip $dst_ip $dns_reply $dns_req_data -# NXT_RESUMEs should be 3. -OVS_WAIT_UNTIL([test 3 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`]) +# NXT_RESUMEs should be 4. +OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`]) $PYTHON "$ovs_srcdir/utilities/ovs-pcap.in" hv1/vif1-tx.pcap > 1.packets AT_CHECK([cat 1.packets], [0], []) @@ -8550,8 +8579,8 @@ dst_ip=`ip_to_hex 10 0 0 1` dns_reply=0 test_dns 2 f00000000002 f000000000f0 $src_ip $dst_ip $dns_reply $dns_req_data -# NXT_RESUMEs should be 3 only. -OVS_WAIT_UNTIL([test 3 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`]) +# NXT_RESUMEs should be 4 only. +OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`]) $PYTHON "$ovs_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets AT_CHECK([cat 2.packets], [0], []) @@ -8571,8 +8600,8 @@ dst_ip=`ip_to_hex 10 0 0 1` dns_reply=1 test_dns 2 f00000000002 f000000000f0 $src_ip $dst_ip $dns_reply $dns_req_data $dns_resp_data -# NXT_RESUMEs should be 4. -OVS_WAIT_UNTIL([test 4 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`]) +# NXT_RESUMEs should be 5. +OVS_WAIT_UNTIL([test 5 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`]) $PYTHON "$ovs_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets cat 2.expected | cut -c -48 > expout @@ -8593,8 +8622,8 @@ dst_ip=`ip_to_hex 10 0 0 1` dns_reply=1 test_dns 2 f00000000002 f000000000f0 $src_ip $dst_ip $dns_reply $dns_req_data $dns_resp_data -# NXT_RESUMEs should be 5. -OVS_WAIT_UNTIL([test 5 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`]) +# NXT_RESUMEs should be 6. +OVS_WAIT_UNTIL([test 6 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`]) $PYTHON "$ovs_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets cat 2.expected | cut -c -48 > expout @@ -8615,8 +8644,8 @@ dst_ip=`ip_to_hex 10 0 0 1` dns_reply=0 test_dns 2 f00000000002 f000000000f0 $src_ip $dst_ip $dns_reply $dns_req_data -# NXT_RESUMEs should be 6. -OVS_WAIT_UNTIL([test 6 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`]) +# NXT_RESUMEs should be 7. +OVS_WAIT_UNTIL([test 7 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`]) $PYTHON "$ovs_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets AT_CHECK([cat 2.packets], [0], []) @@ -8633,8 +8662,8 @@ dst_ip=`ip_to_hex 10 0 0 1` dns_reply=0 test_dns 2 f00000000002 f000000000f0 $src_ip $dst_ip $dns_reply $dns_req_data -# NXT_RESUMEs should be 7. -OVS_WAIT_UNTIL([test 7 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`]) +# NXT_RESUMEs should be 8. +OVS_WAIT_UNTIL([test 8 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`]) $PYTHON "$ovs_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets AT_CHECK([cat 2.packets], [0], []) @@ -8653,8 +8682,8 @@ dst_ip=`ip_to_hex 10 0 0 1` dns_reply=1 test_dns 1 f00000000001 f000000000f0 $src_ip $dst_ip $dns_reply $dns_req_data $dns_resp_data -# NXT_RESUMEs should be 8. -OVS_WAIT_UNTIL([test 8 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`]) +# NXT_RESUMEs should be 9. +OVS_WAIT_UNTIL([test 9 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`]) $PYTHON "$ovs_srcdir/utilities/ovs-pcap.in" hv1/vif1-tx.pcap > 1.packets cat 1.expected | cut -c -48 > expout @@ -8675,8 +8704,8 @@ 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`]) +# NXT_RESUMEs should be 10 +OVS_WAIT_UNTIL([test 10 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`]) $PYTHON "$ovs_srcdir/utilities/ovs-pcap.in" hv1/vif1-tx.pcap > 1.packets # Skipping the UDP checksum.