blob: b8e454cde1eba6aa698947da133ea89e6ab1a8d9 [file] [log] [blame]
Erik Andersene49d5ec2000-02-08 19:58:47 +00001/* vi: set sw=4 ts=4: */
John Beppub332e772000-01-29 12:59:01 +00002/*
3 * Mini nslookup implementation for busybox
4 *
Eric Andersenbdfd0d72001-10-24 05:00:29 +00005 * Copyright (C) 1999,2000 by Lineo, inc. and John Beppu
6 * Copyright (C) 1999,2000,2001 by John Beppu <beppu@codepoet.org>
John Beppub332e772000-01-29 12:59:01 +00007 *
Eric Andersen39cdf4e2004-01-30 22:40:05 +00008 * Correct default name server display and explicit name server option
Robert Griebl31a2e202002-07-24 00:56:56 +00009 * added by Ben Zeckel <bzeckel@hmc.edu> June 2001
10 *
"Robert P. J. Day"2819f752006-07-11 11:32:31 +000011 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
John Beppub332e772000-01-29 12:59:01 +000012 */
13
John Beppub332e772000-01-29 12:59:01 +000014#include <ctype.h>
15#include <errno.h>
16#include <stdio.h>
17#include <string.h>
Eric Andersened3ef502001-01-27 08:24:39 +000018#include <stdlib.h>
John Beppub332e772000-01-29 12:59:01 +000019
Eric Andersen39cdf4e2004-01-30 22:40:05 +000020#include <stdint.h>
John Beppub332e772000-01-29 12:59:01 +000021#include <netdb.h>
22#include <sys/socket.h>
23#include <sys/types.h>
24#include <netinet/in.h>
Eric Andersendab3d462001-06-12 22:21:24 +000025#include <resolv.h>
26#include <arpa/inet.h>
Eric Andersencbe31da2001-02-20 06:14:08 +000027#include "busybox.h"
John Beppub332e772000-01-29 12:59:01 +000028
John Beppu50bc1012000-01-30 09:47:16 +000029/*
30 | I'm only implementing non-interactive mode;
31 | I totally forgot nslookup even had an interactive mode.
John Beppu50bc1012000-01-30 09:47:16 +000032 */
John Beppub332e772000-01-29 12:59:01 +000033
John Beppub332e772000-01-29 12:59:01 +000034/* only works for IPv4 */
Eric Andersen5f825ee2001-01-20 16:22:58 +000035static int addr_fprint(char *addr)
John Beppub332e772000-01-29 12:59:01 +000036{
Eric Andersen39cdf4e2004-01-30 22:40:05 +000037 uint8_t split[4];
38 uint32_t ip;
39 uint32_t *x = (uint32_t *) addr;
John Beppub332e772000-01-29 12:59:01 +000040
Erik Andersene49d5ec2000-02-08 19:58:47 +000041 ip = ntohl(*x);
42 split[0] = (ip & 0xff000000) >> 24;
43 split[1] = (ip & 0x00ff0000) >> 16;
44 split[2] = (ip & 0x0000ff00) >> 8;
45 split[3] = (ip & 0x000000ff);
Eric Andersen5f825ee2001-01-20 16:22:58 +000046 printf("%d.%d.%d.%d", split[0], split[1], split[2], split[3]);
Erik Andersene49d5ec2000-02-08 19:58:47 +000047 return 0;
John Beppub332e772000-01-29 12:59:01 +000048}
49
John Beppu50bc1012000-01-30 09:47:16 +000050/* takes the NULL-terminated array h_addr_list, and
51 * prints its contents appropriately
52 */
Eric Andersen5f825ee2001-01-20 16:22:58 +000053static int addr_list_fprint(char **h_addr_list)
John Beppub332e772000-01-29 12:59:01 +000054{
Erik Andersene49d5ec2000-02-08 19:58:47 +000055 int i, j;
56 char *addr_string = (h_addr_list[1])
Erik Andersen5e1189e2000-04-15 16:34:54 +000057 ? "Addresses: " : "Address: ";
John Beppub332e772000-01-29 12:59:01 +000058
Eric Andersen5f825ee2001-01-20 16:22:58 +000059 printf("%s ", addr_string);
Erik Andersene49d5ec2000-02-08 19:58:47 +000060 for (i = 0, j = 0; h_addr_list[i]; i++, j++) {
Eric Andersen5f825ee2001-01-20 16:22:58 +000061 addr_fprint(h_addr_list[i]);
John Beppu50bc1012000-01-30 09:47:16 +000062
Erik Andersene49d5ec2000-02-08 19:58:47 +000063 /* real nslookup does this */
64 if (j == 4) {
65 if (h_addr_list[i + 1]) {
Eric Andersen5f825ee2001-01-20 16:22:58 +000066 printf("\n ");
Erik Andersene49d5ec2000-02-08 19:58:47 +000067 }
68 j = 0;
69 } else {
70 if (h_addr_list[i + 1]) {
Eric Andersen5f825ee2001-01-20 16:22:58 +000071 printf(", ");
Erik Andersene49d5ec2000-02-08 19:58:47 +000072 }
73 }
74
John Beppub332e772000-01-29 12:59:01 +000075 }
Eric Andersen5f825ee2001-01-20 16:22:58 +000076 printf("\n");
Erik Andersene49d5ec2000-02-08 19:58:47 +000077 return 0;
John Beppub332e772000-01-29 12:59:01 +000078}
79
John Beppu50bc1012000-01-30 09:47:16 +000080/* print the results as nslookup would */
Eric Andersencd8c4362001-11-10 11:22:46 +000081static struct hostent *hostent_fprint(struct hostent *host, const char *server_host)
John Beppu50bc1012000-01-30 09:47:16 +000082{
Erik Andersene49d5ec2000-02-08 19:58:47 +000083 if (host) {
Eric Andersencd8c4362001-11-10 11:22:46 +000084 printf("%s %s\n", server_host, host->h_name);
Eric Andersen5f825ee2001-01-20 16:22:58 +000085 addr_list_fprint(host->h_addr_list);
Erik Andersene49d5ec2000-02-08 19:58:47 +000086 } else {
Eric Andersen5f825ee2001-01-20 16:22:58 +000087 printf("*** Unknown host\n");
Erik Andersene49d5ec2000-02-08 19:58:47 +000088 }
89 return host;
John Beppub332e772000-01-29 12:59:01 +000090}
91
Eric Andersendab3d462001-06-12 22:21:24 +000092/* changes a c-string matching the perl regex \d+\.\d+\.\d+\.\d+
Eric Andersen39cdf4e2004-01-30 22:40:05 +000093 * into a uint32_t
Eric Andersendab3d462001-06-12 22:21:24 +000094 */
Eric Andersen39cdf4e2004-01-30 22:40:05 +000095static uint32_t str_to_addr(const char *addr)
Eric Andersendab3d462001-06-12 22:21:24 +000096{
Eric Andersen39cdf4e2004-01-30 22:40:05 +000097 uint32_t split[4];
98 uint32_t ip;
Eric Andersendab3d462001-06-12 22:21:24 +000099
100 sscanf(addr, "%d.%d.%d.%d",
101 &split[0], &split[1], &split[2], &split[3]);
102
103 /* assuming sscanf worked */
104 ip = (split[0] << 24) |
105 (split[1] << 16) | (split[2] << 8) | (split[3]);
106
107 return htonl(ip);
108}
109
110/* gethostbyaddr wrapper */
111static struct hostent *gethostbyaddr_wrapper(const char *address)
112{
113 struct in_addr addr;
114
115 addr.s_addr = str_to_addr(address);
116 return gethostbyaddr((char *) &addr, 4, AF_INET); /* IPv4 only for now */
117}
118
119/* lookup the default nameserver and display it */
120static inline void server_print(void)
121{
122 struct sockaddr_in def = _res.nsaddr_list[0];
123 char *ip = inet_ntoa(def.sin_addr);
124
Eric Andersencd8c4362001-11-10 11:22:46 +0000125 hostent_fprint(gethostbyaddr_wrapper(ip), "Server:");
Eric Andersendab3d462001-06-12 22:21:24 +0000126 printf("\n");
127}
John Beppub332e772000-01-29 12:59:01 +0000128
Robert Griebl31a2e202002-07-24 00:56:56 +0000129/* alter the global _res nameserver structure to use
130 an explicit dns server instead of what is in /etc/resolv.h */
131static inline void set_default_dns(char *server)
132{
133 struct in_addr server_in_addr;
134
Eric Andersen39cdf4e2004-01-30 22:40:05 +0000135 if(inet_aton(server,&server_in_addr))
Robert Griebl31a2e202002-07-24 00:56:56 +0000136 {
137 _res.nscount = 1;
138 _res.nsaddr_list[0].sin_addr = server_in_addr;
139 }
Eric Andersen39cdf4e2004-01-30 22:40:05 +0000140}
Robert Griebl31a2e202002-07-24 00:56:56 +0000141
John Beppu50bc1012000-01-30 09:47:16 +0000142/* naive function to check whether char *s is an ip address */
Erik Andersene49d5ec2000-02-08 19:58:47 +0000143static int is_ip_address(const char *s)
John Beppub332e772000-01-29 12:59:01 +0000144{
Erik Andersene49d5ec2000-02-08 19:58:47 +0000145 while (*s) {
146 if ((isdigit(*s)) || (*s == '.')) {
147 s++;
148 continue;
149 }
150 return 0;
151 }
152 return 1;
John Beppub332e772000-01-29 12:59:01 +0000153}
154
155/* ________________________________________________________________________ */
Erik Andersene49d5ec2000-02-08 19:58:47 +0000156int nslookup_main(int argc, char **argv)
John Beppub332e772000-01-29 12:59:01 +0000157{
Erik Andersene49d5ec2000-02-08 19:58:47 +0000158 struct hostent *host;
John Beppu50bc1012000-01-30 09:47:16 +0000159
Robert Griebl31a2e202002-07-24 00:56:56 +0000160 /*
161 * initialize DNS structure _res used in printing the default
162 * name server and in the explicit name server option feature.
163 */
Eric Andersen39cdf4e2004-01-30 22:40:05 +0000164
Eric Andersendab3d462001-06-12 22:21:24 +0000165 res_init();
Robert Griebl31a2e202002-07-24 00:56:56 +0000166
167 /*
Eric Andersen39cdf4e2004-01-30 22:40:05 +0000168 * We allow 1 or 2 arguments.
169 * The first is the name to be looked up and the second is an
170 * optional DNS server with which to do the lookup.
Robert Griebl31a2e202002-07-24 00:56:56 +0000171 * More than 3 arguments is an error to follow the pattern of the
172 * standard nslookup
173 */
174
Eric Andersen39cdf4e2004-01-30 22:40:05 +0000175 if (argc < 2 || *argv[1]=='-' || argc > 3)
Manuel Novoa III cad53642003-03-19 09:13:01 +0000176 bb_show_usage();
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000177 else if(argc == 3)
Robert Griebl31a2e202002-07-24 00:56:56 +0000178 set_default_dns(argv[2]);
179
Eric Andersenfe9888a2001-01-20 21:51:21 +0000180 server_print();
Erik Andersene49d5ec2000-02-08 19:58:47 +0000181 if (is_ip_address(argv[1])) {
182 host = gethostbyaddr_wrapper(argv[1]);
183 } else {
Matt Kraai524fcb92001-10-01 17:50:25 +0000184 host = xgethostbyname(argv[1]);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000185 }
Eric Andersencd8c4362001-11-10 11:22:46 +0000186 hostent_fprint(host, "Name: ");
Eric Andersen9789bf12004-10-13 07:25:01 +0000187 if (host) {
188 return EXIT_SUCCESS;
189 }
190 return EXIT_FAILURE;
John Beppub332e772000-01-29 12:59:01 +0000191}
192
Eric Andersen9789bf12004-10-13 07:25:01 +0000193/* $Id: nslookup.c,v 1.33 2004/10/13 07:25:01 andersen Exp $ */