source: MondoRescue/branches/3.3/mindi-busybox/networking/nslookup.c@ 3734

Last change on this file since 3734 was 3621, checked in by Bruno Cornec, 10 years ago

New 3?3 banch for incorporation of latest busybox 1.25. Changing minor version to handle potential incompatibilities.

File size: 5.9 KB
RevLine 
[821]1/* vi: set sw=4 ts=4: */
2/*
3 * Mini nslookup implementation for busybox
4 *
5 * Copyright (C) 1999,2000 by Lineo, inc. and John Beppu
6 * Copyright (C) 1999,2000,2001 by John Beppu <beppu@codepoet.org>
7 *
8 * Correct default name server display and explicit name server option
9 * added by Ben Zeckel <bzeckel@hmc.edu> June 2001
10 *
[2725]11 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
[821]12 */
13
[3232]14//usage:#define nslookup_trivial_usage
15//usage: "[HOST] [SERVER]"
16//usage:#define nslookup_full_usage "\n\n"
17//usage: "Query the nameserver for the IP address of the given HOST\n"
18//usage: "optionally using a specified DNS server"
19//usage:
20//usage:#define nslookup_example_usage
21//usage: "$ nslookup localhost\n"
22//usage: "Server: default\n"
23//usage: "Address: default\n"
24//usage: "\n"
25//usage: "Name: debian\n"
26//usage: "Address: 127.0.0.1\n"
27
[821]28#include <resolv.h>
[1765]29#include "libbb.h"
[821]30
31/*
[2725]32 * I'm only implementing non-interactive mode;
33 * I totally forgot nslookup even had an interactive mode.
34 *
35 * This applet is the only user of res_init(). Without it,
36 * you may avoid pulling in _res global from libc.
[821]37 */
38
[1765]39/* Examples of 'standard' nslookup output
40 * $ nslookup yahoo.com
41 * Server: 128.193.0.10
42 * Address: 128.193.0.10#53
43 *
44 * Non-authoritative answer:
45 * Name: yahoo.com
46 * Address: 216.109.112.135
47 * Name: yahoo.com
48 * Address: 66.94.234.13
49 *
50 * $ nslookup 204.152.191.37
51 * Server: 128.193.4.20
52 * Address: 128.193.4.20#53
53 *
54 * Non-authoritative answer:
55 * 37.191.152.204.in-addr.arpa canonical name = 37.32-27.191.152.204.in-addr.arpa.
56 * 37.32-27.191.152.204.in-addr.arpa name = zeus-pub2.kernel.org.
57 *
58 * Authoritative answers can be found from:
59 * 32-27.191.152.204.in-addr.arpa nameserver = ns1.kernel.org.
60 * 32-27.191.152.204.in-addr.arpa nameserver = ns2.kernel.org.
61 * 32-27.191.152.204.in-addr.arpa nameserver = ns3.kernel.org.
62 * ns1.kernel.org internet address = 140.211.167.34
63 * ns2.kernel.org internet address = 204.152.191.4
64 * ns3.kernel.org internet address = 204.152.191.36
65 */
66
67static int print_host(const char *hostname, const char *header)
[821]68{
[1765]69 /* We can't use xhost2sockaddr() - we want to get ALL addresses,
70 * not just one */
71 struct addrinfo *result = NULL;
72 int rc;
73 struct addrinfo hint;
[821]74
[1765]75 memset(&hint, 0 , sizeof(hint));
76 /* hint.ai_family = AF_UNSPEC; - zero anyway */
77 /* Needed. Or else we will get each address thrice (or more)
78 * for each possible socket type (tcp,udp,raw...): */
79 hint.ai_socktype = SOCK_STREAM;
80 // hint.ai_flags = AI_CANONNAME;
81 rc = getaddrinfo(hostname, NULL /*service*/, &hint, &result);
[821]82
[3232]83 if (rc == 0) {
[1765]84 struct addrinfo *cur = result;
85 unsigned cnt = 0;
[821]86
[1765]87 printf("%-10s %s\n", header, hostname);
[2725]88 // puts(cur->ai_canonname); ?
[1765]89 while (cur) {
90 char *dotted, *revhost;
91 dotted = xmalloc_sockaddr2dotted_noport(cur->ai_addr);
92 revhost = xmalloc_sockaddr2hostonly_noport(cur->ai_addr);
93
94 printf("Address %u: %s%c", ++cnt, dotted, revhost ? ' ' : '\n');
95 if (revhost) {
96 puts(revhost);
97 if (ENABLE_FEATURE_CLEAN_UP)
98 free(revhost);
[821]99 }
[1765]100 if (ENABLE_FEATURE_CLEAN_UP)
101 free(dotted);
102 cur = cur->ai_next;
[821]103 }
104 } else {
[1765]105#if ENABLE_VERBOSE_RESOLUTION_ERRORS
106 bb_error_msg("can't resolve '%s': %s", hostname, gai_strerror(rc));
107#else
108 bb_error_msg("can't resolve '%s'", hostname);
109#endif
[821]110 }
[3232]111 if (ENABLE_FEATURE_CLEAN_UP && result)
[1765]112 freeaddrinfo(result);
113 return (rc != 0);
[821]114}
115
116/* lookup the default nameserver and display it */
[1765]117static void server_print(void)
[821]118{
[1765]119 char *server;
[2725]120 struct sockaddr *sa;
[821]121
[2725]122#if ENABLE_FEATURE_IPV6
123 sa = (struct sockaddr*)_res._u._ext.nsaddrs[0];
124 if (!sa)
125#endif
126 sa = (struct sockaddr*)&_res.nsaddr_list[0];
127 server = xmalloc_sockaddr2dotted_noport(sa);
128
[1765]129 print_host(server, "Server:");
130 if (ENABLE_FEATURE_CLEAN_UP)
131 free(server);
[2725]132 bb_putchar('\n');
[821]133}
134
135/* alter the global _res nameserver structure to use
[2725]136 an explicit dns server instead of what is in /etc/resolv.conf */
137static void set_default_dns(const char *server)
[821]138{
[2725]139 len_and_sockaddr *lsa;
[821]140
[3621]141 if (!server)
142 return;
143
[2725]144 /* NB: this works even with, say, "[::1]:5353"! :) */
145 lsa = xhost2sockaddr(server, 53);
146
147 if (lsa->u.sa.sa_family == AF_INET) {
[821]148 _res.nscount = 1;
[2725]149 /* struct copy */
150 _res.nsaddr_list[0] = lsa->u.sin;
[821]151 }
[2725]152#if ENABLE_FEATURE_IPV6
153 /* Hoped libc can cope with IPv4 address there too.
154 * No such luck, glibc 2.4 segfaults even with IPv6,
155 * maybe I misunderstand how to make glibc use IPv6 addr?
156 * (uclibc 0.9.31+ should work) */
157 if (lsa->u.sa.sa_family == AF_INET6) {
158 // glibc neither SEGVs nor sends any dgrams with this
159 // (strace shows no socket ops):
160 //_res.nscount = 0;
161 _res._u._ext.nscount = 1;
162 /* store a pointer to part of malloc'ed lsa */
163 _res._u._ext.nsaddrs[0] = &lsa->u.sin6;
164 /* must not free(lsa)! */
165 }
166#endif
[821]167}
168
[2725]169int nslookup_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
[821]170int nslookup_main(int argc, char **argv)
171{
[1765]172 /* We allow 1 or 2 arguments.
173 * The first is the name to be looked up and the second is an
174 * optional DNS server with which to do the lookup.
175 * More than 3 arguments is an error to follow the pattern of the
176 * standard nslookup */
[2725]177 if (!argv[1] || argv[1][0] == '-' || argc > 3)
[1765]178 bb_show_usage();
[821]179
[1765]180 /* initialize DNS structure _res used in printing the default
181 * name server and in the explicit name server option feature. */
[821]182 res_init();
[1765]183 /* rfc2133 says this enables IPv6 lookups */
[2725]184 /* (but it also says "may be enabled in /etc/resolv.conf") */
[1765]185 /*_res.options |= RES_USE_INET6;*/
[821]186
[3621]187 set_default_dns(argv[2]);
[821]188
189 server_print();
[3621]190
191 /* getaddrinfo and friends are free to request a resolver
192 * reinitialization. Just in case, set_default_dns() again
193 * after getaddrinfo (in server_print). This reportedly helps
194 * with bug 675 "nslookup does not properly use second argument"
195 * at least on Debian Wheezy and Openwrt AA (eglibc based).
196 */
197 set_default_dns(argv[2]);
198
[1765]199 return print_host(argv[1], "Name:");
[821]200}
Note: See TracBrowser for help on using the repository browser.