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 $ */
|
---|