From patchwork Tue Sep 13 12:33:39 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans Dedecker X-Patchwork-Id: 669318 X-Patchwork-Delegate: blogic@openwrt.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from arrakis.dune.hu (arrakis.dune.hu [78.24.191.176]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3sYPHl1MSVz9s9x for ; Tue, 13 Sep 2016 22:34:11 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b=F/YWlQDB; dkim-atps=neutral Received: from arrakis.dune.hu (localhost [127.0.0.1]) by arrakis.dune.hu (Postfix) with ESMTP id A68DAB92109; Tue, 13 Sep 2016 14:33:52 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.1 (2015-04-28) on arrakis.dune.hu X-Spam-Level: X-Spam-Status: No, score=-1.5 required=5.0 tests=BAYES_00,FREEMAIL_FROM, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.1 Received: from arrakis.dune.hu (localhost [127.0.0.1]) by arrakis.dune.hu (Postfix) with ESMTP; Tue, 13 Sep 2016 14:33:52 +0200 (CEST) Received: from arrakis.dune.hu (localhost [127.0.0.1]) by arrakis.dune.hu (Postfix) with ESMTP id B5280B920FA for ; Tue, 13 Sep 2016 14:33:48 +0200 (CEST) X-policyd-weight: using cached result; rate: -7 Received: from mail-wm0-f67.google.com (mail-wm0-f67.google.com [74.125.82.67]) by arrakis.dune.hu (Postfix) with ESMTPS for ; Tue, 13 Sep 2016 14:33:48 +0200 (CEST) Received: by mail-wm0-f67.google.com with SMTP id c131so2781450wmh.2 for ; Tue, 13 Sep 2016 05:33:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=bAEi97kr4TA4M6ioeevJ0vq26q10WKl1Tx2AE0i0DaI=; b=F/YWlQDBmmRKbeRpCi9dSFJZNQ0QV3N4J0JD/p5qdXAke/5/DiG0FcyASh2ysqyi5k lJYXiSZRw+DmgK3pq8P+thetqgcSGxyXWU0ysLPlYNyrAmWKSlPN16QFMQ7+UFD539om 2GpwgCUf/Jh1Gpji3oY5aBHt3D8Vetllh1EuscJ2g3JoOGm4GNU/qUAOOnCHzDBNF/0K I/YuVObIRseNW6E1E8FFCtz14Vx154j+B2AKGS4pRdri0tPvnaJUpJ5qxUO/6uvyJP1p iRAmWJ0sZzdbdvj4al49GE2ps9bmIyAahDkEv3PAZNbVOYIorllKa0wg6c89VZt3qkPK VSIA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=bAEi97kr4TA4M6ioeevJ0vq26q10WKl1Tx2AE0i0DaI=; b=W9DlHgItsGji2SWs/uKxQCkYS6KnAQuLWCnXSlWlR5GYZvggmlMgaDqXQSE+zCRWp7 VOQ5A+V8dHBwRf9d5lRtga754tbM6obfQjdM+MUhDpK5SryvoGeu4ZSajX9YAdOs+fck WFwI2I+j/bhqgs5nuKQgad3tR+v1cVkTXKi3VtXlb1159BMJPPWHn/4DJhsy76d2GP5x OUOaZ8/L5KttqinY0j31wU8D4SPRvQOApngdlYgvrI/RD/Et9/CKwm8yvS5JPC6Ko/eN u27gLSb8uluPU1eUhqWaClZfU4+58U6y+ltR+ymWMUjXeevc+Ogi2DnMKrrOmQjrAPrX zITg== X-Gm-Message-State: AE9vXwPTQ+XlX5tyJU8pCT+ry8JurmZGRSnxiUAclFVEhKynUpFYiNS/v+7SNGKoJ/IcWg== X-Received: by 10.194.147.19 with SMTP id tg19mr20301893wjb.162.1473770027984; Tue, 13 Sep 2016 05:33:47 -0700 (PDT) Received: from cplx43.eu.thmulti.com ([141.11.62.7]) by smtp.gmail.com with ESMTPSA id yt4sm22715991wjc.48.2016.09.13.05.33.46 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 13 Sep 2016 05:33:47 -0700 (PDT) From: Hans Dedecker To: lede-dev@lists.infradead.org, openwrt-devel@lists.openwrt.org Date: Tue, 13 Sep 2016 14:33:39 +0200 Message-Id: <1473770020-19533-2-git-send-email-dedeckeh@gmail.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1473770020-19533-1-git-send-email-dedeckeh@gmail.com> References: <1473770020-19533-1-git-send-email-dedeckeh@gmail.com> Subject: [OpenWrt-Devel] [PATCH netifd 2/3] interface-ip: DNS name server sorting support in resolv.conf.auto X-BeenThere: openwrt-devel@lists.openwrt.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: OpenWrt Development List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Hans Dedecker MIME-Version: 1.0 Errors-To: openwrt-devel-bounces@lists.openwrt.org Sender: "openwrt-devel" Interface name servers when being written to resolv.conf.auto are sorted based on the following parameters: -Primary sorting key is interface dns_metric; name servers having lowest interface dns_metric are listed first -Secondary sorting key is interface metric; in case of equal interface dns_metric name servers having lowest interface metric are listed first -Finally alphabetical order of the interface names in case of equal interface dns_metric and metric In case the resolver queries the multiple servers in the order listed; sorting is usefull in the following scenarios : -Name resolving over a main and backup interface -Assign priority to IPv6 name servers over IPv4 or vice versa Signed-off-by: Hans Dedecker --- interface-ip.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++----------- interface.c | 6 +++++ interface.h | 1 + ubus.c | 1 + 4 files changed, 68 insertions(+), 13 deletions(-) diff --git a/interface-ip.c b/interface-ip.c index 26a2865..24ea054 100644 --- a/interface-ip.c +++ b/interface-ip.c @@ -1197,21 +1197,33 @@ write_resolv_conf_entries(FILE *f, struct interface_ip_settings *ip, const char } } -void -interface_write_resolv_conf(void) +/* Sorting of interface resolver entries : */ +/* Primary on interface dns_metric : lowest metric first */ +/* Secondary on interface metric : lowest metric first */ +/* Finally alphabetical order of interface names */ +static int resolv_conf_iface_cmp(const void *k1, const void *k2, void *ptr) +{ + const struct interface *iface1 = k1, *iface2 = k2; + + if (iface1->dns_metric != iface2->dns_metric) + return iface1->dns_metric - iface2->dns_metric; + + if (iface1->metric != iface2->metric) + return iface1->metric - iface2->metric; + + return strcmp(iface1->name, iface2->name); +} + +static void +__interface_write_dns_entries(FILE *f) { struct interface *iface; - char *path = alloca(strlen(resolv_conf) + 5); - FILE *f; - uint32_t crcold, crcnew; + struct { + struct avl_node node; + } *entry, *n_entry; + struct avl_tree resolv_conf_iface_entries; - sprintf(path, "%s.tmp", resolv_conf); - unlink(path); - f = fopen(path, "w+"); - if (!f) { - D(INTERFACE, "Failed to open %s for writing\n", path); - return; - } + avl_init(&resolv_conf_iface_entries, resolv_conf_iface_cmp, false, NULL); vlist_for_each_element(&interfaces, iface, node) { if (iface->state != IFS_UP) @@ -1219,15 +1231,50 @@ interface_write_resolv_conf(void) if (vlist_simple_empty(&iface->proto_ip.dns_search) && vlist_simple_empty(&iface->proto_ip.dns_servers) && - vlist_simple_empty(&iface->config_ip.dns_search) && + vlist_simple_empty(&iface->config_ip.dns_search) && vlist_simple_empty(&iface->config_ip.dns_servers)) continue; + entry = calloc(1, sizeof(*entry)); + if (!entry) + continue; + + entry->node.key = iface; + avl_insert(&resolv_conf_iface_entries, &entry->node); + } + + avl_for_each_element(&resolv_conf_iface_entries, entry, node) { + iface = (struct interface *)entry->node.key; + fprintf(f, "# Interface %s\n", iface->name); + write_resolv_conf_entries(f, &iface->config_ip, iface->ifname); + if (!iface->proto_ip.no_dns) write_resolv_conf_entries(f, &iface->proto_ip, iface->ifname); } + + avl_remove_all_elements(&resolv_conf_iface_entries, entry, node, n_entry) + free(entry); +} + +void +interface_write_resolv_conf(void) +{ + char *path = alloca(strlen(resolv_conf) + 5); + FILE *f; + uint32_t crcold, crcnew; + + sprintf(path, "%s.tmp", resolv_conf); + unlink(path); + f = fopen(path, "w+"); + if (!f) { + D(INTERFACE, "Failed to open %s for writing\n", path); + return; + } + + __interface_write_dns_entries(f); + fflush(f); rewind(f); crcnew = crc32_file(f); diff --git a/interface.c b/interface.c index 71e2ecc..5870422 100644 --- a/interface.c +++ b/interface.c @@ -35,6 +35,7 @@ enum { IFACE_ATTR_PEERDNS, IFACE_ATTR_DNS, IFACE_ATTR_DNS_SEARCH, + IFACE_ATTR_DNS_METRIC, IFACE_ATTR_METRIC, IFACE_ATTR_INTERFACE, IFACE_ATTR_IP6ASSIGN, @@ -57,6 +58,7 @@ static const struct blobmsg_policy iface_attrs[IFACE_ATTR_MAX] = { [IFACE_ATTR_METRIC] = { .name = "metric", .type = BLOBMSG_TYPE_INT32 }, [IFACE_ATTR_DNS] = { .name = "dns", .type = BLOBMSG_TYPE_ARRAY }, [IFACE_ATTR_DNS_SEARCH] = { .name = "dns_search", .type = BLOBMSG_TYPE_ARRAY }, + [IFACE_ATTR_DNS_METRIC] = { .name = "dns_metric", .type = BLOBMSG_TYPE_INT32 }, [IFACE_ATTR_INTERFACE] = { .name = "interface", .type = BLOBMSG_TYPE_STRING }, [IFACE_ATTR_IP6ASSIGN] = { .name = "ip6assign", .type = BLOBMSG_TYPE_INT32 }, [IFACE_ATTR_IP6HINT] = { .name = "ip6hint", .type = BLOBMSG_TYPE_STRING }, @@ -795,6 +797,9 @@ interface_alloc(const char *name, struct blob_attr *config) if ((cur = tb[IFACE_ATTR_DNS_SEARCH])) interface_add_dns_search_list(&iface->config_ip, cur); + if ((cur = tb[IFACE_ATTR_DNS_METRIC])) + iface->dns_metric = blobmsg_get_u32(cur); + if ((cur = tb[IFACE_ATTR_METRIC])) iface->metric = blobmsg_get_u32(cur); @@ -1185,6 +1190,7 @@ interface_change_config(struct interface *if_old, struct interface *if_new) if_old->parent_ifname = if_new->parent_ifname; if_old->proto_handler = if_new->proto_handler; if_old->force_link = if_new->force_link; + if_old->dns_metric = if_new->dns_metric; if_old->proto_ip.no_dns = if_new->proto_ip.no_dns; interface_replace_dns(&if_old->config_ip, &if_new->config_ip); diff --git a/interface.h b/interface.h index 5b89b17..aa2085d 100644 --- a/interface.h +++ b/interface.h @@ -145,6 +145,7 @@ struct interface { struct vlist_tree host_routes; int metric; + int dns_metric; unsigned int ip4table; unsigned int ip6table; diff --git a/ubus.c b/ubus.c index 74cdf28..1cbc479 100644 --- a/ubus.c +++ b/ubus.c @@ -687,6 +687,7 @@ netifd_dump_status(struct interface *iface) if (iface->ip6table) blobmsg_add_u32(&b, "ip6table", iface->ip6table); blobmsg_add_u32(&b, "metric", iface->metric); + blobmsg_add_u32(&b, "dns_metric", iface->dns_metric); blobmsg_add_u8(&b, "delegation", !iface->proto_ip.no_delegation); a = blobmsg_open_array(&b, "ipv4-address"); interface_ip_dump_address_list(&iface->config_ip, false, true);