Ignore:
Timestamp:
Nov 4, 2007, 3:16:40 AM (17 years ago)
Author:
Bruno Cornec
Message:

Update to busybox 1.7.2

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/2.2.5/mindi-busybox/networking/nslookup.c

    r821 r1765  
    99 * added by Ben Zeckel <bzeckel@hmc.edu> June 2001
    1010 *
    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.
    2512 */
    2613
    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>
    3814#include <resolv.h>
    39 #include <arpa/inet.h>
    40 #include "busybox.h"
     15#include "libbb.h"
    4116
    4217/*
    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.
    4520 */
    4621
    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
     50static int print_host(const char *hostname, const char *header)
    4951{
    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 */
    5354
    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;
    6258
    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);
    7166
    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;
    7570
    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);
    8083            }
    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;
    8687        }
    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
    8894    }
    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);
    13098}
    13199
    132100/* lookup the default nameserver and display it */
    133 static inline void server_print(void)
     101static void server_print(void)
    134102{
    135     struct sockaddr_in def = _res.nsaddr_list[0];
    136     char *ip = inet_ntoa(def.sin_addr);
     103    char *server;
    137104
    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("");
    140116}
    141117
    142118/* alter the global _res nameserver structure to use
    143119   an explicit dns server instead of what is in /etc/resolv.h */
    144 static inline void set_default_dns(char *server)
     120static void set_default_dns(char *server)
    145121{
    146122    struct in_addr server_in_addr;
    147123
    148     if(inet_aton(server,&server_in_addr))
    149     {
     124    if (inet_pton(AF_INET, server, &server_in_addr) > 0) {
    150125        _res.nscount = 1;
    151126        _res.nsaddr_list[0].sin_addr = server_in_addr;
     
    153128}
    154129
    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 /* ________________________________________________________________________ */
     130int nslookup_main(int argc, char **argv);
    169131int nslookup_main(int argc, char **argv)
    170132{
    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 */
    172138
    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();
    177141
     142    /* initialize DNS structure _res used in printing the default
     143     * name server and in the explicit name server option feature. */
    178144    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;*/
    179148
    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)
    191150        set_default_dns(argv[2]);
    192151
    193152    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:");
    204154}
    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.