On 2019-05-16 18:36:09 +0200, Michael Biebl wrote:
> Am 16.05.19 um 18:17 schrieb Vincent Lefevre:
> > On 2019-05-16 17:52:03 +0200, Michael Biebl wrote:
> >> I would suggest the following: If there is a local nameserver but no
> >> network connectivity, query the local nameserver only.
> > 
> > OK, I can do that. Indeed, the default behavior of "host" is to try
> > every server in /etc/resolv.conf until it succeeds. I suppose that
> > the solution would be to use this option:
> > 
> >   -s
> >       Do not send the query to the next nameserver if any server responds
> >       with a SERVFAIL response, which is the reverse of normal stub
> >       resolver behavior.
> 
> If the remote server would be ordered first in resolv.conf, I assume
> this would still block? I assume you are making the assumption here that
> the local server will always be listed first? Is that a safe assumption?

I'm not sure why anyone would not put the local nameserver first.
Anyway, an alternative solution is to provide the server to the
host command. Thus dns_reachable() would start with

dns_reachable() {
  # If there are no nameserver entries in resolv.conf there is no dns reachable
  grep -q "^[[:space:]]*nameserver" /etc/resolv.conf || return 1

  LOCALNS=$(sed -n 
's/^[[:space:]]*nameserver[[:space:]]\+\(127\..*\|::1\)[[:space:]]*$/\1/p' 
/etc/resolv.conf | head -n 1)

  # If there is no local nameserver and no we have no global ip addresses
  # then we can't reach any nameservers
  if [ -z "$LOCALNS" ]; then

Note: the first line currently is

  $(grep -q nameserver /etc/resolv.conf) || return 1;

First, $(...) is not necessary. And this command does not check
whether "nameserver" is in a comment (which can occur in practice).
I've fixed it above.

But... I think that the assumption that "there is no dns reachable" is
wrong. The resolv.conf(5) man page says: "If no nameserver entries are
present, the default is to use the name server on the local machine."
Thus I would assume that there *is* a reachable dns in this case.

The resolv.conf(5) man page also says: "If this file does not exist,
only the name server on the local machine will be queried".

In short, shouldn't this line be the following?

  grep -q "^[[:space:]]*nameserver" /etc/resolv.conf 2> /dev/null || return 0

With the above changes, the OUT line would change from

  OUT=`LC_ALL=C host -t soa local. 2>&1`

to

  OUT=`LC_ALL=C host -t soa local. $LOCALNS 2>&1`

But this has the effect to output some more lines about the server
if $LOCALNS is set. Thus

    if echo "$OUT" | egrep -vq 'has no|not found'; then
      return 0
    fi

should also change to

    echo "$OUT" | egrep -q 'has no|not found' || return 0

> > I have another question: in
> > 
> >   if ! $(egrep -q "nameserver 127.0.0.1|::1" /etc/resolv.conf); then 
> > 
> > why testing 127.0.0.1 only, and not all local nameservers?
> > For instance, 127.0.1.1 is used by NetworkManager:
> > 
> > https://askubuntu.com/questions/627899/nameserver-127-0-1-1-in-resolv-conf-wont-go-away
> > 
> > Also, the regexp should be something like "^ *nameserver +(127.0.0.1|::1)"
> > or "^ *nameserver +(127\.|::1)", i.e.
> >   * one should make sure that it is a nameserver line (in particular,
> >     not a comment);
> >   * several space characters should match;
> >   * one should make sure that ::1 is preceded by "nameserver"
> >     (the parentheses are missing).
> 
> Good question. I don't know why the script only checks for 127.0.0.1 and
> not 127.0.1.1
> 
> Sjoerd, looking through the history of the package, it seems you are
> most likely to be able to answer that.

Above I've used "127\..*" in the regexp.

-- 
Vincent Lefèvre <vinc...@vinc17.net> - Web: <https://www.vinc17.net/>
100% accessible validated (X)HTML - Blog: <https://www.vinc17.net/blog/>
Work: CR INRIA - computer arithmetic / AriC project (LIP, ENS-Lyon)

Reply via email to