From patchwork Sat Oct 18 15:16:05 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mathias Kresin X-Patchwork-Id: 400687 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from whitealder.osuosl.org (whitealder.osuosl.org [140.211.166.138]) by ozlabs.org (Postfix) with ESMTP id D72C0140092 for ; Sun, 19 Oct 2014 02:16:18 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by whitealder.osuosl.org (Postfix) with ESMTP id C94E791C20; Sat, 18 Oct 2014 15:16:17 +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 IOemxowUesTn; Sat, 18 Oct 2014 15:16:16 +0000 (UTC) Received: from ash.osuosl.org (ash.osuosl.org [140.211.166.34]) by whitealder.osuosl.org (Postfix) with ESMTP id 3715891BB3; Sat, 18 Oct 2014 15:16:16 +0000 (UTC) X-Original-To: uclibc@lists.busybox.net Delivered-To: uclibc@osuosl.org Received: from fraxinus.osuosl.org (fraxinus.osuosl.org [140.211.166.137]) by ash.osuosl.org (Postfix) with ESMTP id 2ADD41C2826 for ; Sat, 18 Oct 2014 15:16:15 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by fraxinus.osuosl.org (Postfix) with ESMTP id 26100A1C74 for ; Sat, 18 Oct 2014 15:16:15 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from fraxinus.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id ko6ZYcdjki8c for ; Sat, 18 Oct 2014 15:16:14 +0000 (UTC) X-Greylist: from auto-whitelisted by SQLgrey-1.7.6 Received: from mail-wg0-f45.google.com (mail-wg0-f45.google.com [74.125.82.45]) by fraxinus.osuosl.org (Postfix) with ESMTPS id 0D55CA1C71 for ; Sat, 18 Oct 2014 15:16:13 +0000 (UTC) Received: by mail-wg0-f45.google.com with SMTP id m15so2739719wgh.16 for ; Sat, 18 Oct 2014 08:16:12 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:subject:date:message-id; bh=sIX3AurOV7qtnpR9O6OATsdhYm3/WDg9v7DduZUnPLA=; b=Ra98lwxuG+ea/aEXxKmvUwla7MBAoHOFv6StfKxNChPOOs3xT1h4CCcYiRZzZ61cax yn/lSJw50hvxGuAahDfwYGFc/CFNHNpdkilu+Ir5S4ByEGnXPkwyrupMpo8LxjgFEcWN dEwEAw3gM7tEps4CcaJCmjtOX2wmq4D3rGaUtHwCCurBs7h9RwPMTgDUbHLYPIO5Mz5T 3qAakkd/9UqnZDi+Zt+wlnXaYq0UmkaprMWrCXU/KuvI9x/jBDzxTTASEIYMkpSKh0Ww zE8bPsKoqgxmpEJ7Gh2jr2b3VX8ami7advGCBQr8eF8wic5m4H2nVGEQMQTiqG97yO9S RFnQ== X-Gm-Message-State: ALoCoQmDwH3Vt93zSIriRVWDvPJg5d64aaL878Vqp8S/+EEBP6VXMBj05uQg/KTVroFtXO3T9sdZ X-Received: by 10.180.19.35 with SMTP id b3mr6732851wie.10.1413645372029; Sat, 18 Oct 2014 08:16:12 -0700 (PDT) Received: from desktop.wvd.kresin.me (p5DDC5DC1.dip0.t-ipconnect.de. [93.220.93.193]) by mx.google.com with ESMTPSA id ge1sm3272921wib.4.2014.10.18.08.16.11 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sat, 18 Oct 2014 08:16:11 -0700 (PDT) From: Mathias Kresin To: uclibc@uclibc.org Subject: [PATCH 1/2] resolv: change search domain addition logic Date: Sat, 18 Oct 2014 17:16:05 +0200 Message-Id: <1413645366-28119-1-git-send-email-openwrt@kresin.me> X-Mailer: git-send-email 1.9.1 X-BeenThere: uclibc@uclibc.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: "Discussion and development of uClibc \(the embedded C library\)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: uclibc-bounces@uclibc.org Sender: "uClibc" RFC1034 3.1 suggests that a character string that represents the starting labels of a domain name which is incomplete, and should be completed by local software using knowledge of the local domain (often called "relative"). Following this advice, the patch eliminates an incompatibility with dnsmasq > 2.57. dnsmasq always returns NOERROR when it receives a hostname for resolving, because it is handled like a TLD by dnsmasq. The dnsmasq authors explains it as the following: Consider doing a query for "com". If dnsmasq returns NXDOMAIN then whatever gets that answer can assume the nothing that ends on ".com" exists, which is clearly wrong, and breaks a lot of stuff. Simple resolvers won't break, but anything more complex will, so reverting the behaviour is no possible. To be compliant with RFC1034 on one side and still fast on the other side, its implemented using the following logic: a) The supplied name is a fqdn (ends with a dot): 1. send the name b) The supplied name contains (but doesn't end with) a dot: 1. send the name, as it could be a fqdn with a missing trailing dot 2. if the name couldn't be found, append the search domains and send c) The supplied name doesn't contain any dots: 1. append the search domains and send 2. if the name couldn't be found, send the original name Signed-off-by: Mathias Kresin --- libc/inet/resolv.c | 38 +++++++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/libc/inet/resolv.c b/libc/inet/resolv.c index cfc1eee..3d3a540 100644 --- a/libc/inet/resolv.c +++ b/libc/inet/resolv.c @@ -1258,7 +1258,8 @@ int __dns_lookup(const char *name, int local_ns_num = -1; /* Nth server to use */ int local_id = local_id; /* for compiler */ int sdomains; - bool ends_with_dot; + bool is_fqdn; + bool looks_like_fqdn; sockaddr46_t sa; fd = -1; @@ -1269,11 +1270,13 @@ int __dns_lookup(const char *name, lookup = malloc(name_len + 1/*for '.'*/ + MAXLEN_searchdomain + 1); if (!packet || !lookup || !name[0]) goto fail; - ends_with_dot = (name[name_len - 1] == '.'); + is_fqdn = (name[name_len - 1] == '.'); + looks_like_fqdn = (!is_fqdn && strchr(name, '.') != NULL) ? 1 : 0; /* no strcpy! paranoia, user might change name[] under us */ memcpy(lookup, name, name_len); DPRINTF("Looking up type %d answer for '%s'\n", type, name); + DPRINTF("is_fqdn:%d looks_like_fqdn:%d\n", is_fqdn, looks_like_fqdn); retries_left = 0; /* for compiler */ do { int pos; @@ -1297,11 +1300,24 @@ int __dns_lookup(const char *name, __open_nameservers(); sdomains = __searchdomains; lookup[name_len] = '\0'; - if ((unsigned)variant < sdomains) { - /* lookup is name_len + 1 + MAXLEN_searchdomain + 1 long */ - /* __searchdomain[] is not bigger than MAXLEN_searchdomain */ - lookup[name_len] = '.'; - strcpy(&lookup[name_len + 1], __searchdomain[variant]); + + /* add the first search domain if the name isn't a FQDN and doesn't look + * like a one (contains a dot). If we're here again and the name looked + * like a FQDN add the first search domain. If all search domains where + * added, and we are here again, send the name without any searchdomains + * as last effort */ + if (!is_fqdn) { + if (!looks_like_fqdn || variant != -1) { + if (variant == -1) + variant = 0; + + if (variant < sdomains) { + /* lookup is name_len + 1 + MAXLEN_searchdomain + 1 long */ + /* __searchdomain[] is not bigger than MAXLEN_searchdomain */ + lookup[name_len] = '.'; + strcpy(&lookup[name_len + 1], __searchdomain[variant]); + } + } } /* first time? pick starting server etc */ if (local_ns_num < 0) { @@ -1461,11 +1477,11 @@ int __dns_lookup(const char *name, * and retry, which is, eh, an error. :) * We were incurring long delays because of this. */ if (h.rcode == NXDOMAIN || h.rcode == SERVFAIL) { - /* if possible, try next search domain */ - if (!ends_with_dot) { + /* if possible, try first/next search domain */ + if (!is_fqdn) { DPRINTF("variant:%d sdomains:%d\n", variant, sdomains); - if (variant < sdomains - 1) { - /* next search domain */ + if (variant < sdomains - 1 || (variant == sdomains -1 && !looks_like_fqdn)) { + /* first/next search domain */ variant++; continue; }