Bug 675

Summary: nslookup does not properly use second argument [SERVER]
Product: Busybox Reporter: dimedrol <dimedrol>
Component: NetworkingAssignee: unassigned
Status: REOPENED ---    
Severity: minor CC: andrei, bkuhn, busybox-cvs, vcunat, xiaosong8584
Priority: P5    
Version: 1.15.x   
Target Milestone: ---   
Hardware: Other   
OS: Linux   
Host: Target:
Build: mips, 2009-10-04
Attachments: Fix nslooup second argument use

Description dimedrol 2009-10-21 16:52:41 UTC
BusyBox v1.15.1 (2009-10-04 18:20:08 MSD) multi-call binary

hardware is Asus wifi router wl-500g premium.

$ cat /proc/cpuinfo 
system type		: Broadcom BCM4704 chip rev 9 pkg 0
cpu model		: BCM3302 V0.6
BogoMIPS		: 263.78
...

firmware is from http://code.google.com/p/wl500g/

$ uname -a
Linux my-test-router 2.4.37.6 #1 2009-10-04 18:23:22 MSD mips GNU/Linux

nslookup syntax is
$ nslookup
BusyBox v1.15.1 (2009-10-04 18:20:08 MSD) multi-call binary

Usage: nslookup [HOST] [SERVER]

Query the nameserver for the IP address of the given HOST
optionally using a specified DNS server
-------

For my tasks i need use the second argument [SERVER], for example:

nslookup www.ru 87.240.1.1

then nslookup show
Server:    87.240.1.1
Address 1: 87.240.1.1 ns1.qwerty.ru

Name:      www.ru
Address 1: 194.87.0.50 www.ru

Looks as if it uses the second argument.
But really the SERVER argument (87.240.1.1) is not used for dns lookups. It is seen from any sniffer, for example in tcpdump.
I run tcpdump on my internet router:
# tcpdump -nnpi eth0 port 53
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
20:34:08.430492 IP 10.101.251.9.1073 > 10.101.251.1.53: 2+ PTR? 1.1.240.87.in-addr.arpa. (41)
20:34:08.433413 IP 10.101.251.1.53 > 10.101.251.9.1073: 2 1/0/0 PTR ns1.qwerty.ru. (68)
20:34:08.436927 IP 10.101.251.9.1073 > 10.101.251.1.53: 3+ AAAA? www.ru. (24)
20:34:08.438834 IP 10.101.251.1.53 > 10.101.251.9.1073: 3 0/0/0 (24)
20:34:08.439783 IP 10.101.251.9.1073 > 10.101.251.1.53: 4+ A? www.ru. (24)
20:34:08.455562 IP 10.101.251.1.53 > 10.101.251.9.1073: 4 1/0/0 A 194.87.0.50 (40)
20:34:08.458001 IP 10.101.251.9.1073 > 10.101.251.1.53: 5+ PTR? 50.0.87.194.in-addr.arpa. (42)
20:34:08.473415 IP 10.101.251.1.53 > 10.101.251.9.1073: 5 1/0/0 PTR www.ru. (62)
-----------------

10.101.251.9 - is host with busybox
10.101.251.1 - is main router
It show that dns server 10.101.251.1 (from system /etc/resolv.conf) is used instead one in command line (87.240.1.1).
Comment 1 Denys Vlasenko 2009-10-21 21:57:52 UTC
nslookup stores the address of the server into global _res structure, into _res.nsaddr_list[0].

Since _res is one of the worst designs in C library (it has so many flaws I don't know where to start), it's no wonder this does not work reliably.

It works with uclibc.

I need to look into glibc source to figure out how it is supposed to work there.
Comment 2 Bradley M. Kuhn 2009-11-14 19:33:59 UTC
I did some looking into this bug.  I posted to the glibc help mailing list to ask as a start: http://sourceware.org/ml/libc-help/2009-11/msg00011.html
If I do not get an answer, I'll dig further into the glibc code and see if I can figure out what is going on.
Comment 3 Dmitry K 2013-05-17 13:57:26 UTC
# echo "" > /etc/resolv.conf 
# nslookup google.com
nslookup: can't resolve '(null)'

nslookup: can't resolve 'google.com'
# nslookup google.com 8.8.8.8
Server:    8.8.8.8
Address 1: 8.8.8.8

nslookup: can't resolve 'google.com'
# echo "nameserver 8.8.8.8" > /etc/resolv.conf 
# nslookup google.com
nslookup: can't resolve '(null)'

Name:      google.com
Address 1: 2a00:1450:4010:c04::66 lb-in-x66.1e100.net
Address 2: 173.194.71.139 lb-in-f139.1e100.net
Address 3: 173.194.71.102 lb-in-f102.1e100.net
Address 4: 173.194.71.100 lb-in-f100.1e100.net
Address 5: 173.194.71.101 lb-in-f101.1e100.net
Address 6: 173.194.71.138 lb-in-f138.1e100.net
Address 7: 173.194.71.113 lb-in-f113.1e100.net
# nslookup google.com 8.8.8.8
Server:    8.8.8.8
Address 1: 8.8.8.8 google-public-dns-a.google.com

Name:      google.com
Address 1: 2a00:1450:4010:c04::66 lb-in-x66.1e100.net
Address 2: 74.125.143.113 la-in-f113.1e100.net
Address 3: 74.125.143.138 la-in-f138.1e100.net
Address 4: 74.125.143.101 la-in-f101.1e100.net
Address 5: 74.125.143.102 la-in-f102.1e100.net
Address 6: 74.125.143.100 la-in-f100.1e100.net
Address 7: 74.125.143.139 la-in-f139.1e100.net


So far nslookup always prints server info for 2nd argument, not for server being used, and always performs resolv using nameserver from resolv.conf even if 2nd argument is provided.
BusyBox v1.20.2
Comment 4 Alex 2013-06-25 19:07:47 UTC
Created attachment 4964 [details]
Fix nslooup second argument use

Using _res directly is a convenient hack but getaddrinfo and friends            
are free to request a resolver reinitialization. I think that without
resorting too much to the libc internals a safe path is call set_default_dns again after the first getaddrinfo. I've attached a patch for busybox
current that fixes the issue at least on Debian Wheezy and Openwrt AA (eglibc based).
Comment 5 Denys Vlasenko 2013-06-26 23:11:11 UTC
Applied the patch, thanks!
Comment 6 Justin Cormack 2016-01-19 11:12:04 UTC
This has not fixed the issue. I have tested on both Alpine Linux (Musl libc, latest release of busybox) and a fresh compile on Ubuntu, and neither respect the second argument to nslookup.
Comment 7 Andrei Gherzan 2016-10-26 11:02:37 UTC
*** Bug 8241 has been marked as a duplicate of this bug. ***
Comment 8 Andrei Gherzan 2016-10-26 11:04:34 UTC
I reproduced this on BusyBox v1.25.1 and BusyBox v1.23.1 with GNU C Library (GNU libc) stable release version 2.21
Comment 9 rubenmuijrers 2017-08-31 10:41:01 UTC
As of 1.27.1 it is still broken:

root:~# nslookup google.com 0.0.0.0
Server:    0.0.0.0
Address 1: 0.0.0.0

Name:      google.com
Address 1: 2a00:1450:400e:807::200e ams15s30-in-x0e.1e100.net
Address 2: 216.58.211.110 ams15s32-in-f14.1e100.net
Comment 10 Vladimír Čunát 2018-02-23 07:54:51 UTC
Given how long this has been known and not resolved, what about simply printing that it won't use the server parameter?  (and preferably also returning nonzero exit code)

The current way is very confusing, doing something else than what it claims/appears to do, especially as I consider it a "debug tool".
Comment 11 Natanael Copa 2020-02-04 10:45:48 UTC
I believe this is fixed with the FEATURE_NSLOOKUP_BIG:

$ busybox nslookup google.com 0.0.0.0
nslookup: write to '0.0.0.0': Connection refused
;; connection timed out; no servers could be reached

$ busybox nslookup google.com 1.1.1.1
Server:         1.1.1.1
Address:        1.1.1.1:53

Non-authoritative answer:
Name:   google.com
Address: 172.217.17.110

Non-authoritative answer:
Name:   google.com
Address: 2a00:1450:400e:806::200e
Comment 12 Gordon Lack 2023-10-13 11:06:50 UTC
This is still an issue in 1.36.1.

Entware uses busybox and I have this installed on my Asus routers.

This is the result of trying to specify a server

[asus2]: nslookup birdman.dynalias.org 8.8.8.8
Server:    8.8.8.8
Address 1: 8.8.8.8 dns.google

Name:      birdman.dynalias.org
Address 1: 192.168.1.240 birdman.dynalias.org

but that address is from the local resolver (hence the local address) not the one from Google's resolvers.

The correct answer (at the moment) is:

[asus2]: host birdman.dynalias.org 8.8.8.8
Using domain server:
Name: 8.8.8.8
Address: 8.8.8.8#53
Aliases: 

birdman.dynalias.org has address 92.16.225.130


It does read resolv.conf, but even moving that out of the way or replacing the nameserver line in there with 8.8.8.8 doesn't stop it using the local address.

And that is because it is reading the local hosts file, even though a specific server is given.