nslookup: rework option parsing
function old new delta nslookup_main 2715 2754 +39 packed_usage 32179 32211 +32 add_ns 65 66 +1 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 3/0 up/down: 72/0) Total: 72 bytes text data bss dec hex filename 926262 555 5740 932557 e3acd busybox_old 926239 555 5740 932534 e3ab6 busybox_unstripped Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
a980109c6a
commit
d4461ef9fb
@ -6,7 +6,7 @@
|
|||||||
//config: help
|
//config: help
|
||||||
//config: nslookup is a tool to query Internet name servers.
|
//config: nslookup is a tool to query Internet name servers.
|
||||||
//config:
|
//config:
|
||||||
//config:config NSLOOKUP_BIG
|
//config:config FEATURE_NSLOOKUP_BIG
|
||||||
//config: bool "Use internal resolver code instead of libc"
|
//config: bool "Use internal resolver code instead of libc"
|
||||||
//config: depends on NSLOOKUP
|
//config: depends on NSLOOKUP
|
||||||
//config: default y
|
//config: default y
|
||||||
@ -14,17 +14,16 @@
|
|||||||
//config:config FEATURE_NSLOOKUP_LONG_OPTIONS
|
//config:config FEATURE_NSLOOKUP_LONG_OPTIONS
|
||||||
//config: bool "Enable long options"
|
//config: bool "Enable long options"
|
||||||
//config: default y
|
//config: default y
|
||||||
//config: depends on NSLOOKUP_BIG && LONG_OPTS
|
//config: depends on FEATURE_NSLOOKUP_BIG && LONG_OPTS
|
||||||
|
|
||||||
//applet:IF_NSLOOKUP(APPLET(nslookup, BB_DIR_USR_BIN, BB_SUID_DROP))
|
//applet:IF_NSLOOKUP(APPLET(nslookup, BB_DIR_USR_BIN, BB_SUID_DROP))
|
||||||
|
|
||||||
//kbuild:lib-$(CONFIG_NSLOOKUP) += nslookup.o
|
//kbuild:lib-$(CONFIG_NSLOOKUP) += nslookup.o
|
||||||
|
|
||||||
//usage:#define nslookup_trivial_usage
|
//usage:#define nslookup_trivial_usage
|
||||||
//usage: "[HOST] [SERVER]"
|
//usage: IF_FEATURE_NSLOOKUP_BIG("[-type=QUERY_TYPE] ") "HOST [DNS_SERVER]"
|
||||||
//usage:#define nslookup_full_usage "\n\n"
|
//usage:#define nslookup_full_usage "\n\n"
|
||||||
//usage: "Query the nameserver for the IP address of the given HOST\n"
|
//usage: "Query DNS about HOST"
|
||||||
//usage: "optionally using a specified DNS server"
|
|
||||||
//usage:
|
//usage:
|
||||||
//usage:#define nslookup_example_usage
|
//usage:#define nslookup_example_usage
|
||||||
//usage: "$ nslookup localhost\n"
|
//usage: "$ nslookup localhost\n"
|
||||||
@ -42,7 +41,7 @@
|
|||||||
#include "common_bufsiz.h"
|
#include "common_bufsiz.h"
|
||||||
|
|
||||||
|
|
||||||
#if !ENABLE_NSLOOKUP_BIG
|
#if !ENABLE_FEATURE_NSLOOKUP_BIG
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Mini nslookup implementation for busybox
|
* Mini nslookup implementation for busybox
|
||||||
@ -326,7 +325,7 @@ struct globals {
|
|||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
OPT_stats = (1 << 4),
|
OPT_stats = (1 << 0),
|
||||||
};
|
};
|
||||||
|
|
||||||
static int parse_reply(const unsigned char *msg, size_t len)
|
static int parse_reply(const unsigned char *msg, size_t len)
|
||||||
@ -687,7 +686,7 @@ static void add_ns(const char *addr)
|
|||||||
G.server = xrealloc_vector(G.server, /*8=2^3:*/ 3, count);
|
G.server = xrealloc_vector(G.server, /*8=2^3:*/ 3, count);
|
||||||
ns = &G.server[count];
|
ns = &G.server[count];
|
||||||
ns->name = addr;
|
ns->name = addr;
|
||||||
ns->lsa = xhost2sockaddr(addr, 53);
|
ns->lsa = xhost2sockaddr(addr, G.default_port);
|
||||||
/*ns->replies = 0; - already is */
|
/*ns->replies = 0; - already is */
|
||||||
/*ns->failures = 0; - already is */
|
/*ns->failures = 0; - already is */
|
||||||
}
|
}
|
||||||
@ -747,75 +746,98 @@ int nslookup_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
{
|
{
|
||||||
struct ns *ns;
|
struct ns *ns;
|
||||||
struct query *queries;
|
struct query *queries;
|
||||||
llist_t *type_strings;
|
|
||||||
int n_queries;
|
int n_queries;
|
||||||
unsigned types;
|
unsigned types;
|
||||||
int opts;
|
|
||||||
int rc;
|
int rc;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
INIT_G();
|
INIT_G();
|
||||||
|
|
||||||
type_strings = NULL;
|
/* manpage: "Options can also be specified on the command line
|
||||||
#if ENABLE_FEATURE_NSLOOKUP_LONG_OPTIONS
|
* if they precede the arguments and are prefixed with a hyphen."
|
||||||
opts = getopt32long(argv, "^"
|
*/
|
||||||
"+" /* '+': stop at first non-option (why?) */
|
|
||||||
"q:*p:+r:+t:+s"
|
|
||||||
"\0"
|
|
||||||
"-1:q::", /* minimum 1 arg, -q is a list */
|
|
||||||
"type\0" Required_argument "q"
|
|
||||||
"querytype\0" Required_argument "q"
|
|
||||||
"port\0" Required_argument "p"
|
|
||||||
"retry\0" Required_argument "r"
|
|
||||||
"timeout\0" Required_argument "t"
|
|
||||||
"stats\0" No_argument "s",
|
|
||||||
&type_strings, &G.default_port,
|
|
||||||
&G.default_retry, &G.default_timeout
|
|
||||||
);
|
|
||||||
#else
|
|
||||||
opts = getopt32(argv, "^"
|
|
||||||
"+" /* '+': stop at first non-option (why?) */
|
|
||||||
"q:*p:+r:+t:+s"
|
|
||||||
"\0"
|
|
||||||
"-1:q::", /* minimum 1 arg, -q is a list */
|
|
||||||
&type_strings, &G.default_port,
|
|
||||||
&G.default_retry, &G.default_timeout
|
|
||||||
);
|
|
||||||
#endif
|
|
||||||
if (G.default_port > 65535)
|
|
||||||
bb_error_msg_and_die("invalid server port");
|
|
||||||
if (G.default_retry == 0)
|
|
||||||
bb_error_msg_and_die("invalid retry value");
|
|
||||||
if (G.default_timeout == 0)
|
|
||||||
bb_error_msg_and_die("invalid timeout value");
|
|
||||||
|
|
||||||
types = 0;
|
types = 0;
|
||||||
while (type_strings) {
|
argv++;
|
||||||
int c;
|
for (;;) {
|
||||||
char *ptr, *chr;
|
const char *options =
|
||||||
|
// bind-utils-9.11.3 accept these:
|
||||||
|
// class= cl=
|
||||||
|
// type= ty= querytype= query= qu= q=
|
||||||
|
// domain= do=
|
||||||
|
// port= po=
|
||||||
|
// timeout= t=
|
||||||
|
// retry= ret=
|
||||||
|
// ndots=
|
||||||
|
// recurse
|
||||||
|
// norecurse
|
||||||
|
// defname
|
||||||
|
// nodefname
|
||||||
|
// vc
|
||||||
|
// novc
|
||||||
|
// debug
|
||||||
|
// nodebug
|
||||||
|
// d2
|
||||||
|
// nod2
|
||||||
|
// search
|
||||||
|
// nosearch
|
||||||
|
// sil
|
||||||
|
// fail
|
||||||
|
// nofail
|
||||||
|
// ver (prints version and exits)
|
||||||
|
"type\0" /* 0 */
|
||||||
|
"querytype\0" /* 1 */
|
||||||
|
"port\0" /* 2 */
|
||||||
|
"retry\0" /* 3 */
|
||||||
|
"stats\0" /* 4 */
|
||||||
|
"t\0" /* disambiguate with "type": else -t=2 fails */
|
||||||
|
"timeout\0" /* 6 */
|
||||||
|
"";
|
||||||
|
int i;
|
||||||
|
char *arg;
|
||||||
|
char *val;
|
||||||
|
|
||||||
ptr = llist_pop(&type_strings);
|
if (!*argv)
|
||||||
|
bb_show_usage();
|
||||||
|
if (argv[0][0] != '-')
|
||||||
|
break;
|
||||||
|
|
||||||
/* skip leading text, e.g. when invoked with -querytype=AAAA */
|
/* Separate out "=val" part */
|
||||||
chr = strchr(ptr, '=');
|
arg = (*argv++) + 1;
|
||||||
if (chr)
|
val = strchrnul(arg, '=');
|
||||||
ptr = chr + 1;
|
if (*val)
|
||||||
|
*val++ = '\0';
|
||||||
|
|
||||||
for (c = 0;; c++) {
|
i = index_in_substrings(options, arg);
|
||||||
if (c == ARRAY_SIZE(qtypes))
|
//bb_error_msg("i:%d arg:'%s' val:'%s'", i, arg, val);
|
||||||
bb_error_msg_and_die("invalid query type \"%s\"", ptr);
|
if (i < 0)
|
||||||
if (strcmp(qtypes[c].name, ptr) == 0)
|
bb_show_usage();
|
||||||
|
|
||||||
|
if (i <= 1) {
|
||||||
|
for (i = 0;; i++) {
|
||||||
|
if (i == ARRAY_SIZE(qtypes))
|
||||||
|
bb_error_msg_and_die("invalid query type \"%s\"", val);
|
||||||
|
if (strcmp(qtypes[i].name, val) == 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
types |= (1 << i);
|
||||||
types |= (1 << c);
|
continue;
|
||||||
|
}
|
||||||
|
if (i == 2) {
|
||||||
|
G.default_port = xatou_range(val, 1, 0xffff);
|
||||||
|
}
|
||||||
|
if (i == 3) {
|
||||||
|
G.default_retry = xatou_range(val, 1, INT_MAX);
|
||||||
|
}
|
||||||
|
if (i == 4) {
|
||||||
|
option_mask32 |= OPT_stats;
|
||||||
|
}
|
||||||
|
if (i > 4) {
|
||||||
|
G.default_timeout = xatou_range(val, 1, INT_MAX / 1000);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
argv += optind;
|
|
||||||
|
|
||||||
n_queries = 0;
|
n_queries = 0;
|
||||||
queries = NULL;
|
queries = NULL;
|
||||||
do {
|
|
||||||
if (types == 0) {
|
if (types == 0) {
|
||||||
/* No explicit type given, guess query type.
|
/* No explicit type given, guess query type.
|
||||||
* If we can convert the domain argument into a ptr (means that
|
* If we can convert the domain argument into a ptr (means that
|
||||||
@ -826,28 +848,28 @@ int nslookup_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
char *ptr;
|
char *ptr;
|
||||||
char buf80[80];
|
char buf80[80];
|
||||||
|
|
||||||
ptr = make_ptr(buf80, *argv);
|
ptr = make_ptr(buf80, argv[0]);
|
||||||
if (ptr) {
|
if (ptr) {
|
||||||
add_query(&queries, &n_queries, T_PTR, xstrdup(ptr));
|
add_query(&queries, &n_queries, T_PTR, xstrdup(ptr));
|
||||||
} else {
|
} else {
|
||||||
add_query(&queries, &n_queries, T_A, *argv);
|
add_query(&queries, &n_queries, T_A, argv[0]);
|
||||||
#if ENABLE_FEATURE_IPV6
|
#if ENABLE_FEATURE_IPV6
|
||||||
add_query(&queries, &n_queries, T_AAAA, *argv);
|
add_query(&queries, &n_queries, T_AAAA, argv[0]);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
int c;
|
int c;
|
||||||
for (c = 0; c < ARRAY_SIZE(qtypes); c++) {
|
for (c = 0; c < ARRAY_SIZE(qtypes); c++) {
|
||||||
if (types & (1 << c))
|
if (types & (1 << c))
|
||||||
add_query(&queries, &n_queries, qtypes[c].type, *argv);
|
add_query(&queries, &n_queries, qtypes[c].type, argv[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
argv++;
|
|
||||||
} while (argv[0] && argv[1]);
|
|
||||||
|
|
||||||
/* Use given DNS server if present */
|
/* Use given DNS server if present */
|
||||||
if (argv[0]) {
|
if (argv[1]) {
|
||||||
add_ns(argv[0]);
|
if (argv[2])
|
||||||
|
bb_show_usage();
|
||||||
|
add_ns(argv[1]);
|
||||||
} else {
|
} else {
|
||||||
parse_resolvconf();
|
parse_resolvconf();
|
||||||
/* Fall back to localhost if we could not find NS in resolv.conf */
|
/* Fall back to localhost if we could not find NS in resolv.conf */
|
||||||
@ -861,7 +883,7 @@ int nslookup_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
c = send_queries(&G.server[rc], queries, n_queries);
|
c = send_queries(&G.server[rc], queries, n_queries);
|
||||||
if (c > 0) {
|
if (c > 0) {
|
||||||
/* more than zero replies received */
|
/* more than zero replies received */
|
||||||
if (opts & OPT_stats) {
|
if (option_mask32 & OPT_stats) {
|
||||||
printf("Replies:\t%d\n", G.server[rc].replies);
|
printf("Replies:\t%d\n", G.server[rc].replies);
|
||||||
printf("Failures:\t%d\n\n", G.server[rc].failures);
|
printf("Failures:\t%d\n\n", G.server[rc].failures);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user