diff options
-rw-r--r-- | networking/nslookup.c | 204 |
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 | ||
328 | enum { | 327 | enum { |
329 | OPT_stats = (1 << 4), | 328 | OPT_stats = (1 << 0), |
330 | }; | 329 | }; |
331 | 330 | ||
332 | static int parse_reply(const unsigned char *msg, size_t len) | 331 | static 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 | } |