Changeset 1770 in MondoRescue for branches/stable/mindi-busybox/networking/nslookup.c
- Timestamp:
- Nov 6, 2007, 11:01:53 AM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/stable/mindi-busybox/networking/nslookup.c
r821 r1770 9 9 * added by Ben Zeckel <bzeckel@hmc.edu> June 2001 10 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 * 11 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. 25 12 */ 26 13 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 14 #include <resolv.h> 39 #include <arpa/inet.h> 40 #include "busybox.h" 15 #include "libbb.h" 41 16 42 17 /* 43 |I'm only implementing non-interactive mode;44 |I totally forgot nslookup even had an interactive mode.18 * I'm only implementing non-interactive mode; 19 * I totally forgot nslookup even had an interactive mode. 45 20 */ 46 21 47 /* only works for IPv4 */ 48 static int addr_fprint(char *addr) 22 /* Examples of 'standard' nslookup output 23 * $ nslookup yahoo.com 24 * Server: 128.193.0.10 25 * Address: 128.193.0.10#53 26 * 27 * Non-authoritative answer: 28 * Name: yahoo.com 29 * Address: 216.109.112.135 30 * Name: yahoo.com 31 * Address: 66.94.234.13 32 * 33 * $ nslookup 204.152.191.37 34 * Server: 128.193.4.20 35 * Address: 128.193.4.20#53 36 * 37 * Non-authoritative answer: 38 * 37.191.152.204.in-addr.arpa canonical name = 37.32-27.191.152.204.in-addr.arpa. 39 * 37.32-27.191.152.204.in-addr.arpa name = zeus-pub2.kernel.org. 40 * 41 * Authoritative answers can be found from: 42 * 32-27.191.152.204.in-addr.arpa nameserver = ns1.kernel.org. 43 * 32-27.191.152.204.in-addr.arpa nameserver = ns2.kernel.org. 44 * 32-27.191.152.204.in-addr.arpa nameserver = ns3.kernel.org. 45 * ns1.kernel.org internet address = 140.211.167.34 46 * ns2.kernel.org internet address = 204.152.191.4 47 * ns3.kernel.org internet address = 204.152.191.36 48 */ 49 50 static int print_host(const char *hostname, const char *header) 49 51 { 50 uint8_t split[4]; 51 uint32_t ip; 52 uint32_t *x = (uint32_t *) addr; 52 /* We can't use xhost2sockaddr() - we want to get ALL addresses, 53 * not just one */ 53 54 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 } 55 struct addrinfo *result = NULL; 56 int rc; 57 struct addrinfo hint; 62 58 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: "; 59 memset(&hint, 0 , sizeof(hint)); 60 /* hint.ai_family = AF_UNSPEC; - zero anyway */ 61 /* Needed. Or else we will get each address thrice (or more) 62 * for each possible socket type (tcp,udp,raw...): */ 63 hint.ai_socktype = SOCK_STREAM; 64 // hint.ai_flags = AI_CANONNAME; 65 rc = getaddrinfo(hostname, NULL /*service*/, &hint, &result); 71 66 72 printf("%s ", addr_string);73 for (i = 0, j = 0; h_addr_list[i]; i++, j++) {74 addr_fprint(h_addr_list[i]);67 if (!rc) { 68 struct addrinfo *cur = result; 69 unsigned cnt = 0; 75 70 76 /* real nslookup does this */ 77 if (j == 4) { 78 if (h_addr_list[i + 1]) { 79 printf("\n "); 71 printf("%-10s %s\n", header, hostname); 72 // printf("%s\n", cur->ai_canonname); ? 73 while (cur) { 74 char *dotted, *revhost; 75 dotted = xmalloc_sockaddr2dotted_noport(cur->ai_addr); 76 revhost = xmalloc_sockaddr2hostonly_noport(cur->ai_addr); 77 78 printf("Address %u: %s%c", ++cnt, dotted, revhost ? ' ' : '\n'); 79 if (revhost) { 80 puts(revhost); 81 if (ENABLE_FEATURE_CLEAN_UP) 82 free(revhost); 80 83 } 81 j = 0; 82 } else { 83 if (h_addr_list[i + 1]) { 84 printf(", "); 85 } 84 if (ENABLE_FEATURE_CLEAN_UP) 85 free(dotted); 86 cur = cur->ai_next; 86 87 } 87 88 } else { 89 #if ENABLE_VERBOSE_RESOLUTION_ERRORS 90 bb_error_msg("can't resolve '%s': %s", hostname, gai_strerror(rc)); 91 #else 92 bb_error_msg("can't resolve '%s'", hostname); 93 #endif 88 94 } 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 */ 95 if (ENABLE_FEATURE_CLEAN_UP) 96 freeaddrinfo(result); 97 return (rc != 0); 130 98 } 131 99 132 100 /* lookup the default nameserver and display it */ 133 static inlinevoid server_print(void)101 static void server_print(void) 134 102 { 135 struct sockaddr_in def = _res.nsaddr_list[0]; 136 char *ip = inet_ntoa(def.sin_addr); 103 char *server; 137 104 138 hostent_fprint(gethostbyaddr_wrapper(ip), "Server:"); 139 printf("\n"); 105 server = xmalloc_sockaddr2dotted_noport((struct sockaddr*)&_res.nsaddr_list[0]); 106 /* I honestly don't know what to do if DNS server has _IPv6 address_. 107 * Probably it is listed in 108 * _res._u._ext_.nsaddrs[MAXNS] (of type "struct sockaddr_in6*" each) 109 * but how to find out whether resolver uses 110 * _res.nsaddr_list[] or _res._u._ext_.nsaddrs[], or both? 111 * Looks like classic design from hell, BIND-grade. Hard to surpass. */ 112 print_host(server, "Server:"); 113 if (ENABLE_FEATURE_CLEAN_UP) 114 free(server); 115 puts(""); 140 116 } 141 117 142 118 /* alter the global _res nameserver structure to use 143 119 an explicit dns server instead of what is in /etc/resolv.h */ 144 static inlinevoid set_default_dns(char *server)120 static void set_default_dns(char *server) 145 121 { 146 122 struct in_addr server_in_addr; 147 123 148 if(inet_aton(server,&server_in_addr)) 149 { 124 if (inet_pton(AF_INET, server, &server_in_addr) > 0) { 150 125 _res.nscount = 1; 151 126 _res.nsaddr_list[0].sin_addr = server_in_addr; … … 153 128 } 154 129 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 /* ________________________________________________________________________ */ 130 int nslookup_main(int argc, char **argv); 169 131 int nslookup_main(int argc, char **argv) 170 132 { 171 struct hostent *host; 133 /* We allow 1 or 2 arguments. 134 * The first is the name to be looked up and the second is an 135 * optional DNS server with which to do the lookup. 136 * More than 3 arguments is an error to follow the pattern of the 137 * standard nslookup */ 172 138 173 /* 174 * initialize DNS structure _res used in printing the default 175 * name server and in the explicit name server option feature. 176 */ 139 if (argc < 2 || *argv[1] == '-' || argc > 3) 140 bb_show_usage(); 177 141 142 /* initialize DNS structure _res used in printing the default 143 * name server and in the explicit name server option feature. */ 178 144 res_init(); 145 /* rfc2133 says this enables IPv6 lookups */ 146 /* (but it also says "may be enabled in /etc/resolv.conf|) */ 147 /*_res.options |= RES_USE_INET6;*/ 179 148 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) 149 if (argc == 3) 191 150 set_default_dns(argv[2]); 192 151 193 152 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; 153 return print_host(argv[1], "Name:"); 204 154 } 205 206 /* $Id: nslookup.c,v 1.33 2004/10/13 07:25:01 andersen Exp $ */
Note:
See TracChangeset
for help on using the changeset viewer.