diff options
Diffstat (limited to 'busybox/networking/nslookup.c')
-rw-r--r-- | busybox/networking/nslookup.c | 206 |
1 files changed, 206 insertions, 0 deletions
diff --git a/busybox/networking/nslookup.c b/busybox/networking/nslookup.c new file mode 100644 index 000000000..936fa33cb --- /dev/null +++ b/busybox/networking/nslookup.c | |||
@@ -0,0 +1,206 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | ||
2 | /* | ||
3 | * Mini nslookup implementation for busybox | ||
4 | * | ||
5 | * Copyright (C) 1999,2000 by Lineo, inc. and John Beppu | ||
6 | * Copyright (C) 1999,2000,2001 by John Beppu <beppu@codepoet.org> | ||
7 | * | ||
8 | * Correct default name server display and explicit name server option | ||
9 | * added by Ben Zeckel <bzeckel@hmc.edu> June 2001 | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License as published by | ||
13 | * the Free Software Foundation; either version 2 of the License, or | ||
14 | * (at your option) any later version. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
19 | * General Public License for more details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU General Public License | ||
22 | * along with this program; if not, write to the Free Software | ||
23 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
24 | * | ||
25 | */ | ||
26 | |||
27 | #include <ctype.h> | ||
28 | #include <errno.h> | ||
29 | #include <stdio.h> | ||
30 | #include <string.h> | ||
31 | #include <stdlib.h> | ||
32 | |||
33 | #include <stdint.h> | ||
34 | #include <netdb.h> | ||
35 | #include <sys/socket.h> | ||
36 | #include <sys/types.h> | ||
37 | #include <netinet/in.h> | ||
38 | #include <resolv.h> | ||
39 | #include <arpa/inet.h> | ||
40 | #include "busybox.h" | ||
41 | |||
42 | /* | ||
43 | | I'm only implementing non-interactive mode; | ||
44 | | I totally forgot nslookup even had an interactive mode. | ||
45 | */ | ||
46 | |||
47 | /* only works for IPv4 */ | ||
48 | static int addr_fprint(char *addr) | ||
49 | { | ||
50 | uint8_t split[4]; | ||
51 | uint32_t ip; | ||
52 | uint32_t *x = (uint32_t *) addr; | ||
53 | |||
54 | ip = ntohl(*x); | ||
55 | split[0] = (ip & 0xff000000) >> 24; | ||
56 | split[1] = (ip & 0x00ff0000) >> 16; | ||
57 | split[2] = (ip & 0x0000ff00) >> 8; | ||
58 | split[3] = (ip & 0x000000ff); | ||
59 | printf("%d.%d.%d.%d", split[0], split[1], split[2], split[3]); | ||
60 | return 0; | ||
61 | } | ||
62 | |||
63 | /* takes the NULL-terminated array h_addr_list, and | ||
64 | * prints its contents appropriately | ||
65 | */ | ||
66 | static int addr_list_fprint(char **h_addr_list) | ||
67 | { | ||
68 | int i, j; | ||
69 | char *addr_string = (h_addr_list[1]) | ||
70 | ? "Addresses: " : "Address: "; | ||
71 | |||
72 | printf("%s ", addr_string); | ||
73 | for (i = 0, j = 0; h_addr_list[i]; i++, j++) { | ||
74 | addr_fprint(h_addr_list[i]); | ||
75 | |||
76 | /* real nslookup does this */ | ||
77 | if (j == 4) { | ||
78 | if (h_addr_list[i + 1]) { | ||
79 | printf("\n "); | ||
80 | } | ||
81 | j = 0; | ||
82 | } else { | ||
83 | if (h_addr_list[i + 1]) { | ||
84 | printf(", "); | ||
85 | } | ||
86 | } | ||
87 | |||
88 | } | ||
89 | printf("\n"); | ||
90 | return 0; | ||
91 | } | ||
92 | |||
93 | /* print the results as nslookup would */ | ||
94 | static struct hostent *hostent_fprint(struct hostent *host, const char *server_host) | ||
95 | { | ||
96 | if (host) { | ||
97 | printf("%s %s\n", server_host, host->h_name); | ||
98 | addr_list_fprint(host->h_addr_list); | ||
99 | } else { | ||
100 | printf("*** Unknown host\n"); | ||
101 | } | ||
102 | return host; | ||
103 | } | ||
104 | |||
105 | /* changes a c-string matching the perl regex \d+\.\d+\.\d+\.\d+ | ||
106 | * into a uint32_t | ||
107 | */ | ||
108 | static uint32_t str_to_addr(const char *addr) | ||
109 | { | ||
110 | uint32_t split[4]; | ||
111 | uint32_t ip; | ||
112 | |||
113 | sscanf(addr, "%d.%d.%d.%d", | ||
114 | &split[0], &split[1], &split[2], &split[3]); | ||
115 | |||
116 | /* assuming sscanf worked */ | ||
117 | ip = (split[0] << 24) | | ||
118 | (split[1] << 16) | (split[2] << 8) | (split[3]); | ||
119 | |||
120 | return htonl(ip); | ||
121 | } | ||
122 | |||
123 | /* gethostbyaddr wrapper */ | ||
124 | static struct hostent *gethostbyaddr_wrapper(const char *address) | ||
125 | { | ||
126 | struct in_addr addr; | ||
127 | |||
128 | addr.s_addr = str_to_addr(address); | ||
129 | return gethostbyaddr((char *) &addr, 4, AF_INET); /* IPv4 only for now */ | ||
130 | } | ||
131 | |||
132 | /* lookup the default nameserver and display it */ | ||
133 | static inline void server_print(void) | ||
134 | { | ||
135 | struct sockaddr_in def = _res.nsaddr_list[0]; | ||
136 | char *ip = inet_ntoa(def.sin_addr); | ||
137 | |||
138 | hostent_fprint(gethostbyaddr_wrapper(ip), "Server:"); | ||
139 | printf("\n"); | ||
140 | } | ||
141 | |||
142 | /* alter the global _res nameserver structure to use | ||
143 | an explicit dns server instead of what is in /etc/resolv.h */ | ||
144 | static inline void set_default_dns(char *server) | ||
145 | { | ||
146 | struct in_addr server_in_addr; | ||
147 | |||
148 | if(inet_aton(server,&server_in_addr)) | ||
149 | { | ||
150 | _res.nscount = 1; | ||
151 | _res.nsaddr_list[0].sin_addr = server_in_addr; | ||
152 | } | ||
153 | } | ||
154 | |||
155 | /* naive function to check whether char *s is an ip address */ | ||
156 | static int is_ip_address(const char *s) | ||
157 | { | ||
158 | while (*s) { | ||
159 | if ((isdigit(*s)) || (*s == '.')) { | ||
160 | s++; | ||
161 | continue; | ||
162 | } | ||
163 | return 0; | ||
164 | } | ||
165 | return 1; | ||
166 | } | ||
167 | |||
168 | /* ________________________________________________________________________ */ | ||
169 | int nslookup_main(int argc, char **argv) | ||
170 | { | ||
171 | struct hostent *host; | ||
172 | |||
173 | /* | ||
174 | * initialize DNS structure _res used in printing the default | ||
175 | * name server and in the explicit name server option feature. | ||
176 | */ | ||
177 | |||
178 | res_init(); | ||
179 | |||
180 | /* | ||
181 | * We allow 1 or 2 arguments. | ||
182 | * The first is the name to be looked up and the second is an | ||
183 | * optional DNS server with which to do the lookup. | ||
184 | * More than 3 arguments is an error to follow the pattern of the | ||
185 | * standard nslookup | ||
186 | */ | ||
187 | |||
188 | if (argc < 2 || *argv[1]=='-' || argc > 3) | ||
189 | bb_show_usage(); | ||
190 | else if(argc == 3) | ||
191 | set_default_dns(argv[2]); | ||
192 | |||
193 | server_print(); | ||
194 | if (is_ip_address(argv[1])) { | ||
195 | host = gethostbyaddr_wrapper(argv[1]); | ||
196 | } else { | ||
197 | host = xgethostbyname(argv[1]); | ||
198 | } | ||
199 | hostent_fprint(host, "Name: "); | ||
200 | if (host) { | ||
201 | return EXIT_SUCCESS; | ||
202 | } | ||
203 | return EXIT_FAILURE; | ||
204 | } | ||
205 | |||
206 | /* $Id: nslookup.c,v 1.33 2004/10/13 07:25:01 andersen Exp $ */ | ||