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: nslookup is a tool to query Internet name servers.
|
||||
//config:
|
||||
//config:config NSLOOKUP_BIG
|
||||
//config:config FEATURE_NSLOOKUP_BIG
|
||||
//config: bool "Use internal resolver code instead of libc"
|
||||
//config: depends on NSLOOKUP
|
||||
//config: default y
|
||||
@ -14,17 +14,16 @@
|
||||
//config:config FEATURE_NSLOOKUP_LONG_OPTIONS
|
||||
//config: bool "Enable long options"
|
||||
//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))
|
||||
|
||||
//kbuild:lib-$(CONFIG_NSLOOKUP) += nslookup.o
|
||||
|
||||
//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: "Query the nameserver for the IP address of the given HOST\n"
|
||||
//usage: "optionally using a specified DNS server"
|
||||
//usage: "Query DNS about HOST"
|
||||
//usage:
|
||||
//usage:#define nslookup_example_usage
|
||||
//usage: "$ nslookup localhost\n"
|
||||
@ -42,7 +41,7 @@
|
||||
#include "common_bufsiz.h"
|
||||
|
||||
|
||||
#if !ENABLE_NSLOOKUP_BIG
|
||||
#if !ENABLE_FEATURE_NSLOOKUP_BIG
|
||||
|
||||
/*
|
||||
* Mini nslookup implementation for busybox
|
||||
@ -326,7 +325,7 @@ struct globals {
|
||||
} while (0)
|
||||
|
||||
enum {
|
||||
OPT_stats = (1 << 4),
|
||||
OPT_stats = (1 << 0),
|
||||
};
|
||||
|
||||
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);
|
||||
ns = &G.server[count];
|
||||
ns->name = addr;
|
||||
ns->lsa = xhost2sockaddr(addr, 53);
|
||||
ns->lsa = xhost2sockaddr(addr, G.default_port);
|
||||
/*ns->replies = 0; - already is */
|
||||
/*ns->failures = 0; - already is */
|
||||
}
|
||||
@ -747,107 +746,130 @@ int nslookup_main(int argc UNUSED_PARAM, char **argv)
|
||||
{
|
||||
struct ns *ns;
|
||||
struct query *queries;
|
||||
llist_t *type_strings;
|
||||
int n_queries;
|
||||
unsigned types;
|
||||
int opts;
|
||||
int rc;
|
||||
int err;
|
||||
|
||||
INIT_G();
|
||||
|
||||
type_strings = NULL;
|
||||
#if ENABLE_FEATURE_NSLOOKUP_LONG_OPTIONS
|
||||
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");
|
||||
|
||||
/* manpage: "Options can also be specified on the command line
|
||||
* if they precede the arguments and are prefixed with a hyphen."
|
||||
*/
|
||||
types = 0;
|
||||
while (type_strings) {
|
||||
int c;
|
||||
char *ptr, *chr;
|
||||
argv++;
|
||||
for (;;) {
|
||||
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 */
|
||||
chr = strchr(ptr, '=');
|
||||
if (chr)
|
||||
ptr = chr + 1;
|
||||
/* Separate out "=val" part */
|
||||
arg = (*argv++) + 1;
|
||||
val = strchrnul(arg, '=');
|
||||
if (*val)
|
||||
*val++ = '\0';
|
||||
|
||||
for (c = 0;; c++) {
|
||||
if (c == ARRAY_SIZE(qtypes))
|
||||
bb_error_msg_and_die("invalid query type \"%s\"", ptr);
|
||||
if (strcmp(qtypes[c].name, ptr) == 0)
|
||||
break;
|
||||
i = index_in_substrings(options, arg);
|
||||
//bb_error_msg("i:%d arg:'%s' val:'%s'", i, arg, val);
|
||||
if (i < 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;
|
||||
}
|
||||
types |= (1 << i);
|
||||
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);
|
||||
}
|
||||
|
||||
types |= (1 << c);
|
||||
}
|
||||
|
||||
argv += optind;
|
||||
|
||||
n_queries = 0;
|
||||
queries = NULL;
|
||||
do {
|
||||
if (types == 0) {
|
||||
/* No explicit type given, guess query type.
|
||||
* If we can convert the domain argument into a ptr (means that
|
||||
* inet_pton() could read it) we assume a PTR request, else
|
||||
* we issue A+AAAA queries and switch to an output format
|
||||
* mimicking the one of the traditional nslookup applet.
|
||||
*/
|
||||
char *ptr;
|
||||
char buf80[80];
|
||||
if (types == 0) {
|
||||
/* No explicit type given, guess query type.
|
||||
* If we can convert the domain argument into a ptr (means that
|
||||
* inet_pton() could read it) we assume a PTR request, else
|
||||
* we issue A+AAAA queries and switch to an output format
|
||||
* mimicking the one of the traditional nslookup applet.
|
||||
*/
|
||||
char *ptr;
|
||||
char buf80[80];
|
||||
|
||||
ptr = make_ptr(buf80, *argv);
|
||||
if (ptr) {
|
||||
add_query(&queries, &n_queries, T_PTR, xstrdup(ptr));
|
||||
} else {
|
||||
add_query(&queries, &n_queries, T_A, *argv);
|
||||
#if ENABLE_FEATURE_IPV6
|
||||
add_query(&queries, &n_queries, T_AAAA, *argv);
|
||||
#endif
|
||||
}
|
||||
ptr = make_ptr(buf80, argv[0]);
|
||||
if (ptr) {
|
||||
add_query(&queries, &n_queries, T_PTR, xstrdup(ptr));
|
||||
} else {
|
||||
int c;
|
||||
for (c = 0; c < ARRAY_SIZE(qtypes); c++) {
|
||||
if (types & (1 << c))
|
||||
add_query(&queries, &n_queries, qtypes[c].type, *argv);
|
||||
}
|
||||
add_query(&queries, &n_queries, T_A, argv[0]);
|
||||
#if ENABLE_FEATURE_IPV6
|
||||
add_query(&queries, &n_queries, T_AAAA, argv[0]);
|
||||
#endif
|
||||
}
|
||||
argv++;
|
||||
} while (argv[0] && argv[1]);
|
||||
} else {
|
||||
int c;
|
||||
for (c = 0; c < ARRAY_SIZE(qtypes); c++) {
|
||||
if (types & (1 << c))
|
||||
add_query(&queries, &n_queries, qtypes[c].type, argv[0]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Use given DNS server if present */
|
||||
if (argv[0]) {
|
||||
add_ns(argv[0]);
|
||||
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 */
|
||||
@ -861,7 +883,7 @@ int nslookup_main(int argc UNUSED_PARAM, char **argv)
|
||||
c = send_queries(&G.server[rc], queries, n_queries);
|
||||
if (c > 0) {
|
||||
/* more than zero replies received */
|
||||
if (opts & OPT_stats) {
|
||||
if (option_mask32 & OPT_stats) {
|
||||
printf("Replies:\t%d\n", G.server[rc].replies);
|
||||
printf("Failures:\t%d\n\n", G.server[rc].failures);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user