aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--networking/nslookup.c204
1 files changed, 113 insertions, 91 deletions
diff --git a/networking/nslookup.c b/networking/nslookup.c
index c6f431347..112e8763c 100644
--- a/networking/nslookup.c
+++ b/networking/nslookup.c
@@ -6,7 +6,7 @@
6//config: help 6//config: help
7//config: nslookup is a tool to query Internet name servers. 7//config: nslookup is a tool to query Internet name servers.
8//config: 8//config:
9//config:config NSLOOKUP_BIG 9//config:config FEATURE_NSLOOKUP_BIG
10//config: bool "Use internal resolver code instead of libc" 10//config: bool "Use internal resolver code instead of libc"
11//config: depends on NSLOOKUP 11//config: depends on NSLOOKUP
12//config: default y 12//config: default y
@@ -14,17 +14,16 @@
14//config:config FEATURE_NSLOOKUP_LONG_OPTIONS 14//config:config FEATURE_NSLOOKUP_LONG_OPTIONS
15//config: bool "Enable long options" 15//config: bool "Enable long options"
16//config: default y 16//config: default y
17//config: depends on NSLOOKUP_BIG && LONG_OPTS 17//config: depends on FEATURE_NSLOOKUP_BIG && LONG_OPTS
18 18
19//applet:IF_NSLOOKUP(APPLET(nslookup, BB_DIR_USR_BIN, BB_SUID_DROP)) 19//applet:IF_NSLOOKUP(APPLET(nslookup, BB_DIR_USR_BIN, BB_SUID_DROP))
20 20
21//kbuild:lib-$(CONFIG_NSLOOKUP) += nslookup.o 21//kbuild:lib-$(CONFIG_NSLOOKUP) += nslookup.o
22 22
23//usage:#define nslookup_trivial_usage 23//usage:#define nslookup_trivial_usage
24//usage: "[HOST] [SERVER]" 24//usage: IF_FEATURE_NSLOOKUP_BIG("[-type=QUERY_TYPE] ") "HOST [DNS_SERVER]"
25//usage:#define nslookup_full_usage "\n\n" 25//usage:#define nslookup_full_usage "\n\n"
26//usage: "Query the nameserver for the IP address of the given HOST\n" 26//usage: "Query DNS about HOST"
27//usage: "optionally using a specified DNS server"
28//usage: 27//usage:
29//usage:#define nslookup_example_usage 28//usage:#define nslookup_example_usage
30//usage: "$ nslookup localhost\n" 29//usage: "$ nslookup localhost\n"
@@ -42,7 +41,7 @@
42#include "common_bufsiz.h" 41#include "common_bufsiz.h"
43 42
44 43
45#if !ENABLE_NSLOOKUP_BIG 44#if !ENABLE_FEATURE_NSLOOKUP_BIG
46 45
47/* 46/*
48 * Mini nslookup implementation for busybox 47 * Mini nslookup implementation for busybox
@@ -326,7 +325,7 @@ struct globals {
326} while (0) 325} while (0)
327 326
328enum { 327enum {
329 OPT_stats = (1 << 4), 328 OPT_stats = (1 << 0),
330}; 329};
331 330
332static int parse_reply(const unsigned char *msg, size_t len) 331static int parse_reply(const unsigned char *msg, size_t len)
@@ -687,7 +686,7 @@ static void add_ns(const char *addr)
687 G.server = xrealloc_vector(G.server, /*8=2^3:*/ 3, count); 686 G.server = xrealloc_vector(G.server, /*8=2^3:*/ 3, count);
688 ns = &G.server[count]; 687 ns = &G.server[count];
689 ns->name = addr; 688 ns->name = addr;
690 ns->lsa = xhost2sockaddr(addr, 53); 689 ns->lsa = xhost2sockaddr(addr, G.default_port);
691 /*ns->replies = 0; - already is */ 690 /*ns->replies = 0; - already is */
692 /*ns->failures = 0; - already is */ 691 /*ns->failures = 0; - already is */
693} 692}
@@ -747,107 +746,130 @@ int nslookup_main(int argc UNUSED_PARAM, char **argv)
747{ 746{
748 struct ns *ns; 747 struct ns *ns;
749 struct query *queries; 748 struct query *queries;
750 llist_t *type_strings;
751 int n_queries; 749 int n_queries;
752 unsigned types; 750 unsigned types;
753 int opts;
754 int rc; 751 int rc;
755 int err; 752 int err;
756 753
757 INIT_G(); 754 INIT_G();
758 755
759 type_strings = NULL; 756 /* manpage: "Options can also be specified on the command line
760#if ENABLE_FEATURE_NSLOOKUP_LONG_OPTIONS 757 * if they precede the arguments and are prefixed with a hyphen."
761 opts = getopt32long(argv, "^" 758 */
762 "+" /* '+': stop at first non-option (why?) */
763 "q:*p:+r:+t:+s"
764 "\0"
765 "-1:q::", /* minimum 1 arg, -q is a list */
766 "type\0" Required_argument "q"
767 "querytype\0" Required_argument "q"
768 "port\0" Required_argument "p"
769 "retry\0" Required_argument "r"
770 "timeout\0" Required_argument "t"
771 "stats\0" No_argument "s",
772 &type_strings, &G.default_port,
773 &G.default_retry, &G.default_timeout
774 );
775#else
776 opts = getopt32(argv, "^"
777 "+" /* '+': stop at first non-option (why?) */
778 "q:*p:+r:+t:+s"
779 "\0"
780 "-1:q::", /* minimum 1 arg, -q is a list */
781 &type_strings, &G.default_port,
782 &G.default_retry, &G.default_timeout
783 );
784#endif
785 if (G.default_port > 65535)
786 bb_error_msg_and_die("invalid server port");
787 if (G.default_retry == 0)
788 bb_error_msg_and_die("invalid retry value");
789 if (G.default_timeout == 0)
790 bb_error_msg_and_die("invalid timeout value");
791
792 types = 0; 759 types = 0;
793 while (type_strings) { 760 argv++;
794 int c; 761 for (;;) {
795 char *ptr, *chr; 762 const char *options =
796 763// bind-utils-9.11.3 accept these:
797 ptr = llist_pop(&type_strings); 764// class= cl=
798 765// type= ty= querytype= query= qu= q=
799 /* skip leading text, e.g. when invoked with -querytype=AAAA */ 766// domain= do=
800 chr = strchr(ptr, '='); 767// port= po=
801 if (chr) 768// timeout= t=
802 ptr = chr + 1; 769// retry= ret=
770// ndots=
771// recurse
772// norecurse
773// defname
774// nodefname
775// vc
776// novc
777// debug
778// nodebug
779// d2
780// nod2
781// search
782// nosearch
783// sil
784// fail
785// nofail
786// ver (prints version and exits)
787 "type\0" /* 0 */
788 "querytype\0" /* 1 */
789 "port\0" /* 2 */
790 "retry\0" /* 3 */
791 "stats\0" /* 4 */
792 "t\0" /* disambiguate with "type": else -t=2 fails */
793 "timeout\0" /* 6 */
794 "";
795 int i;
796 char *arg;
797 char *val;
798
799 if (!*argv)
800 bb_show_usage();
801 if (argv[0][0] != '-')
802 break;
803 803
804 for (c = 0;; c++) { 804 /* Separate out "=val" part */
805 if (c == ARRAY_SIZE(qtypes)) 805 arg = (*argv++) + 1;
806 bb_error_msg_and_die("invalid query type \"%s\"", ptr); 806 val = strchrnul(arg, '=');
807 if (strcmp(qtypes[c].name, ptr) == 0) 807 if (*val)
808 break; 808 *val++ = '\0';
809
810 i = index_in_substrings(options, arg);
811 //bb_error_msg("i:%d arg:'%s' val:'%s'", i, arg, val);
812 if (i < 0)
813 bb_show_usage();
814
815 if (i <= 1) {
816 for (i = 0;; i++) {
817 if (i == ARRAY_SIZE(qtypes))
818 bb_error_msg_and_die("invalid query type \"%s\"", val);
819 if (strcmp(qtypes[i].name, val) == 0)
820 break;
821 }
822 types |= (1 << i);
823 continue;
824 }
825 if (i == 2) {
826 G.default_port = xatou_range(val, 1, 0xffff);
827 }
828 if (i == 3) {
829 G.default_retry = xatou_range(val, 1, INT_MAX);
830 }
831 if (i == 4) {
832 option_mask32 |= OPT_stats;
833 }
834 if (i > 4) {
835 G.default_timeout = xatou_range(val, 1, INT_MAX / 1000);
809 } 836 }
810
811 types |= (1 << c);
812 } 837 }
813 838
814 argv += optind;
815
816 n_queries = 0; 839 n_queries = 0;
817 queries = NULL; 840 queries = NULL;
818 do { 841 if (types == 0) {
819 if (types == 0) { 842 /* No explicit type given, guess query type.
820 /* No explicit type given, guess query type. 843 * If we can convert the domain argument into a ptr (means that
821 * If we can convert the domain argument into a ptr (means that 844 * inet_pton() could read it) we assume a PTR request, else
822 * inet_pton() could read it) we assume a PTR request, else 845 * we issue A+AAAA queries and switch to an output format
823 * we issue A+AAAA queries and switch to an output format 846 * mimicking the one of the traditional nslookup applet.
824 * mimicking the one of the traditional nslookup applet. 847 */
825 */ 848 char *ptr;
826 char *ptr; 849 char buf80[80];
827 char buf80[80]; 850
828 851 ptr = make_ptr(buf80, argv[0]);
829 ptr = make_ptr(buf80, *argv); 852 if (ptr) {
830 if (ptr) { 853 add_query(&queries, &n_queries, T_PTR, xstrdup(ptr));
831 add_query(&queries, &n_queries, T_PTR, xstrdup(ptr)); 854 } else {
832 } else { 855 add_query(&queries, &n_queries, T_A, argv[0]);
833 add_query(&queries, &n_queries, T_A, *argv);
834#if ENABLE_FEATURE_IPV6 856#if ENABLE_FEATURE_IPV6
835 add_query(&queries, &n_queries, T_AAAA, *argv); 857 add_query(&queries, &n_queries, T_AAAA, argv[0]);
836#endif 858#endif
837 }
838 } else {
839 int c;
840 for (c = 0; c < ARRAY_SIZE(qtypes); c++) {
841 if (types & (1 << c))
842 add_query(&queries, &n_queries, qtypes[c].type, *argv);
843 }
844 } 859 }
845 argv++; 860 } else {
846 } while (argv[0] && argv[1]); 861 int c;
862 for (c = 0; c < ARRAY_SIZE(qtypes); c++) {
863 if (types & (1 << c))
864 add_query(&queries, &n_queries, qtypes[c].type, argv[0]);
865 }
866 }
847 867
848 /* Use given DNS server if present */ 868 /* Use given DNS server if present */
849 if (argv[0]) { 869 if (argv[1]) {
850 add_ns(argv[0]); 870 if (argv[2])
871 bb_show_usage();
872 add_ns(argv[1]);
851 } else { 873 } else {
852 parse_resolvconf(); 874 parse_resolvconf();
853 /* Fall back to localhost if we could not find NS in resolv.conf */ 875 /* 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)
861 c = send_queries(&G.server[rc], queries, n_queries); 883 c = send_queries(&G.server[rc], queries, n_queries);
862 if (c > 0) { 884 if (c > 0) {
863 /* more than zero replies received */ 885 /* more than zero replies received */
864 if (opts & OPT_stats) { 886 if (option_mask32 & OPT_stats) {
865 printf("Replies:\t%d\n", G.server[rc].replies); 887 printf("Replies:\t%d\n", G.server[rc].replies);
866 printf("Failures:\t%d\n\n", G.server[rc].failures); 888 printf("Failures:\t%d\n\n", G.server[rc].failures);
867 } 889 }