nslookup: add support for search domains, closes 11161
function old new delta
parse_resolvconf - 311 +311
add_query_with_search - 105 +105
nslookup_main 873 757 -116
------------------------------------------------------------------------------
(add/remove: 2/0 grow/shrink: 0/1 up/down: 416/-116) Total: 300 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
diff --git a/networking/nslookup.c b/networking/nslookup.c
index 3a614b0..e153eb5 100644
--- a/networking/nslookup.c
+++ b/networking/nslookup.c
@@ -318,6 +318,8 @@
unsigned serv_count;
struct ns *server;
struct query *query;
+ char *search;
+ smalluint have_search_directive;
} FIX_ALIASING;
#define G (*(struct globals*)bb_common_bufsiz1)
#define INIT_G() do { \
@@ -667,24 +669,60 @@
resolv = fopen("/etc/resolv.conf", "r");
if (resolv) {
- char line[128], *p;
+ char line[512]; /* "search" is defined to be up to 256 chars */
while (fgets(line, sizeof(line), resolv)) {
+ char *p, *arg;
+
p = strtok(line, " \t\n");
-
- if (!p || strcmp(p, "nameserver") != 0)
- continue;
-
- p = strtok(NULL, " \t\n");
-
if (!p)
continue;
+ dbg("resolv_key:'%s'\n", p);
+ arg = strtok(NULL, "\n");
+ dbg("resolv_arg:'%s'\n", arg);
+ if (!arg)
+ continue;
- add_ns(xstrdup(p));
+ if (strcmp(p, "domain") == 0) {
+ /* domain DOM */
+ if (!G.have_search_directive)
+ goto set_search;
+ continue;
+ }
+ if (strcmp(p, "search") == 0) {
+ /* search DOM1 DOM2... */
+ G.have_search_directive = 1;
+ set_search:
+ free(G.search);
+ G.search = xstrdup(arg);
+ dbg("search='%s'\n", G.search);
+ continue;
+ }
+
+ if (strcmp(p, "nameserver") != 0)
+ continue;
+
+ /* nameserver DNS */
+ add_ns(xstrdup(arg));
}
fclose(resolv);
}
+
+ if (!G.search) {
+ /* default search domain is domain part of hostname */
+ char *h = safe_gethostname();
+ char *d = strchr(h, '.');
+ if (d) {
+ G.search = d + 1;
+ dbg("search='%s' (from hostname)\n", G.search);
+ }
+ /* else free(h); */
+ }
+
+ /* Cater for case of "domain ." in resolv.conf */
+ if (G.search && LONE_CHAR(G.search, '.'))
+ G.search = NULL;
}
static void add_query(int type, const char *dname)
@@ -695,7 +733,7 @@
count = G.query_count++;
- G.query = xrealloc_vector(G.query, /*2=2^1:*/ 1, count);
+ G.query = xrealloc_vector(G.query, /*4=2^2:*/ 2, count);
new_q = &G.query[count];
dbg("new query#%u type %u for '%s'\n", count, type, dname);
@@ -709,6 +747,28 @@
new_q->qlen = qlen;
}
+static void add_query_with_search(int type, const char *dname)
+{
+ char *s;
+
+ if (type == T_PTR || !G.search || strchr(dname, '.')) {
+ add_query(type, dname);
+ return;
+ }
+
+ s = G.search;
+ for (;;) {
+ char *fullname, *e;
+
+ e = skip_non_whitespace(s);
+ fullname = xasprintf("%s.%.*s", dname, (int)(e - s), s);
+ add_query(type, fullname);
+ s = skip_whitespace(e);
+ if (!*s)
+ break;
+ }
+}
+
static char *make_ptr(const char *addrstr)
{
unsigned char addr[16];
@@ -833,6 +893,18 @@
}
}
+ /* Use given DNS server if present */
+ if (argv[1]) {
+ if (argv[2])
+ bb_show_usage();
+ add_ns(argv[1]);
+ } else {
+ parse_resolvconf();
+ /* Fall back to localhost if we could not find NS in resolv.conf */
+ if (G.serv_count == 0)
+ add_ns("127.0.0.1");
+ }
+
if (types == 0) {
/* No explicit type given, guess query type.
* If we can convert the domain argument into a ptr (means that
@@ -846,31 +918,19 @@
if (ptr) {
add_query(T_PTR, ptr);
} else {
- add_query(T_A, argv[0]);
+ add_query_with_search(T_A, argv[0]);
#if ENABLE_FEATURE_IPV6
- add_query(T_AAAA, argv[0]);
+ add_query_with_search(T_AAAA, argv[0]);
#endif
}
} else {
int c;
for (c = 0; c < ARRAY_SIZE(qtypes); c++) {
if (types & (1 << c))
- add_query(qtypes[c].type, argv[0]);
+ add_query_with_search(qtypes[c].type, argv[0]);
}
}
- /* Use given DNS server if present */
- if (argv[1]) {
- if (argv[2])
- bb_show_usage();
- add_ns(argv[1]);
- } else {
- parse_resolvconf();
- /* Fall back to localhost if we could not find NS in resolv.conf */
- if (G.serv_count == 0)
- add_ns("127.0.0.1");
- }
-
for (rc = 0; rc < G.serv_count;) {
int c;