blob: ffa720174d2889bd99aa397ce0f7ccd00822b79a [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 *
5 *
6 * Copyright (C) 2000 by Lineo, inc.
7 * Written by John Beppu <beppu@lineo.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 *
23 */
24
25#include "internal.h"
26#include <ctype.h>
27#include <errno.h>
28#include <stdio.h>
29#include <string.h>
30
31#include <netdb.h>
32#include <sys/socket.h>
33#include <sys/types.h>
34#include <netinet/in.h>
35
John Beppu50bc1012000-01-30 09:47:16 +000036/*
37 | I'm only implementing non-interactive mode;
38 | I totally forgot nslookup even had an interactive mode.
39 |
40 | [ TODO ]
41 | + find out how to use non-default name servers
42 | + find out how the real nslookup gets the default name server
43 */
John Beppub332e772000-01-29 12:59:01 +000044
Erik Andersene49d5ec2000-02-08 19:58:47 +000045static const char nslookup_usage[] = "nslookup [HOST]\n\n";
John Beppub332e772000-01-29 12:59:01 +000046
47
John Beppu50bc1012000-01-30 09:47:16 +000048/* I have to see how the real nslookup does this.
49 * I could dig through /etc/resolv.conf, but is there a
50 * better (programatic) way?
51 */
Erik Andersene49d5ec2000-02-08 19:58:47 +000052static void server_fprint(FILE * dst)
John Beppub332e772000-01-29 12:59:01 +000053{
Erik Andersene49d5ec2000-02-08 19:58:47 +000054 fprintf(dst, "Server: %s\n", "something");
55 fprintf(dst, "Address: %s\n\n", "something");
John Beppub332e772000-01-29 12:59:01 +000056}
57
58/* only works for IPv4 */
Erik Andersene49d5ec2000-02-08 19:58:47 +000059static int addr_fprint(char *addr, FILE * dst)
John Beppub332e772000-01-29 12:59:01 +000060{
Erik Andersene49d5ec2000-02-08 19:58:47 +000061 uint8_t split[4];
62 uint32_t ip;
63 uint32_t *x = (uint32_t *) addr;
John Beppub332e772000-01-29 12:59:01 +000064
Erik Andersene49d5ec2000-02-08 19:58:47 +000065 ip = ntohl(*x);
66 split[0] = (ip & 0xff000000) >> 24;
67 split[1] = (ip & 0x00ff0000) >> 16;
68 split[2] = (ip & 0x0000ff00) >> 8;
69 split[3] = (ip & 0x000000ff);
70 fprintf(dst, "%d.%d.%d.%d", split[0], split[1], split[2], split[3]
71 );
72 return 0;
John Beppub332e772000-01-29 12:59:01 +000073}
74
John Beppu50bc1012000-01-30 09:47:16 +000075/* changes a c-string matching the perl regex \d+\.\d+\.\d+\.\d+
76 * into a uint32_t
77 */
Erik Andersene49d5ec2000-02-08 19:58:47 +000078static uint32_t str_to_addr(const char *addr)
John Beppub332e772000-01-29 12:59:01 +000079{
Erik Andersene49d5ec2000-02-08 19:58:47 +000080 uint32_t split[4];
81 uint32_t ip;
John Beppub332e772000-01-29 12:59:01 +000082
Erik Andersene49d5ec2000-02-08 19:58:47 +000083 sscanf(addr, "%d.%d.%d.%d",
84 &split[0], &split[1], &split[2], &split[3]);
John Beppub332e772000-01-29 12:59:01 +000085
Erik Andersene49d5ec2000-02-08 19:58:47 +000086 /* assuming sscanf worked */
87 ip = (split[0] << 24) |
88 (split[1] << 16) | (split[2] << 8) | (split[3]);
John Beppub332e772000-01-29 12:59:01 +000089
Erik Andersene49d5ec2000-02-08 19:58:47 +000090 return htonl(ip);
John Beppub332e772000-01-29 12:59:01 +000091}
92
John Beppu50bc1012000-01-30 09:47:16 +000093/* takes the NULL-terminated array h_addr_list, and
94 * prints its contents appropriately
95 */
Erik Andersene49d5ec2000-02-08 19:58:47 +000096static int addr_list_fprint(char **h_addr_list, FILE * dst)
John Beppub332e772000-01-29 12:59:01 +000097{
Erik Andersene49d5ec2000-02-08 19:58:47 +000098 int i, j;
99 char *addr_string = (h_addr_list[1])
100 ? "Addresses" : "Address";
John Beppub332e772000-01-29 12:59:01 +0000101
Erik Andersene49d5ec2000-02-08 19:58:47 +0000102 fprintf(dst, "%s: ", addr_string);
103 for (i = 0, j = 0; h_addr_list[i]; i++, j++) {
104 addr_fprint(h_addr_list[i], dst);
John Beppu50bc1012000-01-30 09:47:16 +0000105
Erik Andersene49d5ec2000-02-08 19:58:47 +0000106 /* real nslookup does this */
107 if (j == 4) {
108 if (h_addr_list[i + 1]) {
109 fprintf(dst, "\n ");
110 }
111 j = 0;
112 } else {
113 if (h_addr_list[i + 1]) {
114 fprintf(dst, ", ");
115 }
116 }
117
John Beppub332e772000-01-29 12:59:01 +0000118 }
Erik Andersene49d5ec2000-02-08 19:58:47 +0000119 fprintf(dst, "\n");
120 return 0;
John Beppub332e772000-01-29 12:59:01 +0000121}
122
John Beppu50bc1012000-01-30 09:47:16 +0000123/* gethostbyaddr wrapper */
Erik Andersene49d5ec2000-02-08 19:58:47 +0000124static struct hostent *gethostbyaddr_wrapper(const char *address)
John Beppub332e772000-01-29 12:59:01 +0000125{
Erik Andersene49d5ec2000-02-08 19:58:47 +0000126 struct in_addr addr;
John Beppub332e772000-01-29 12:59:01 +0000127
Erik Andersene49d5ec2000-02-08 19:58:47 +0000128 addr.s_addr = str_to_addr(address);
129 return gethostbyaddr((char *) &addr, 4, AF_INET); /* IPv4 only for now */
John Beppu50bc1012000-01-30 09:47:16 +0000130}
131
132/* print the results as nslookup would */
Erik Andersene49d5ec2000-02-08 19:58:47 +0000133static struct hostent *hostent_fprint(struct hostent *host, FILE * dst)
John Beppu50bc1012000-01-30 09:47:16 +0000134{
Erik Andersene49d5ec2000-02-08 19:58:47 +0000135 if (host) {
136 fprintf(dst, "Name: %s\n", host->h_name);
137 addr_list_fprint(host->h_addr_list, dst);
138 } else {
139 fprintf(dst, "*** %s\n", hstrerror(h_errno));
140 }
141 return host;
John Beppub332e772000-01-29 12:59:01 +0000142}
143
John Beppub332e772000-01-29 12:59:01 +0000144
John Beppu50bc1012000-01-30 09:47:16 +0000145/* naive function to check whether char *s is an ip address */
Erik Andersene49d5ec2000-02-08 19:58:47 +0000146static int is_ip_address(const char *s)
John Beppub332e772000-01-29 12:59:01 +0000147{
Erik Andersene49d5ec2000-02-08 19:58:47 +0000148 while (*s) {
149 if ((isdigit(*s)) || (*s == '.')) {
150 s++;
151 continue;
152 }
153 return 0;
154 }
155 return 1;
John Beppub332e772000-01-29 12:59:01 +0000156}
157
158/* ________________________________________________________________________ */
Erik Andersene49d5ec2000-02-08 19:58:47 +0000159int nslookup_main(int argc, char **argv)
John Beppub332e772000-01-29 12:59:01 +0000160{
Erik Andersene49d5ec2000-02-08 19:58:47 +0000161 struct hostent *host;
John Beppu50bc1012000-01-30 09:47:16 +0000162
Erik Andersene49d5ec2000-02-08 19:58:47 +0000163 if (argc < 2) {
164 usage(nslookup_usage);
165 }
John Beppub332e772000-01-29 12:59:01 +0000166
Erik Andersene49d5ec2000-02-08 19:58:47 +0000167 server_fprint(stdout);
168 if (is_ip_address(argv[1])) {
169 host = gethostbyaddr_wrapper(argv[1]);
170 } else {
171 host = gethostbyname(argv[1]);
172 }
173 hostent_fprint(host, stdout);
174 return 0;
John Beppub332e772000-01-29 12:59:01 +0000175}
176
Erik Andersene49d5ec2000-02-08 19:58:47 +0000177/* $Id: nslookup.c,v 1.4 2000/02/08 19:58:47 erik Exp $ */