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/netstat.c

    r821 r1765  
    66 * Copyright (C) 2002 by Bart Visscher <magick@linux-fan.com>
    77 *
    8  * This program is free software; you can redistribute it and/or modify
    9  * it under the terms of the GNU General Public License as published by
    10  * the Free Software Foundation; either version 2 of the License, or
    11  * (at your option) any later version.
    12  *
    13  * This program is distributed in the hope that it will be useful,
    14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    16  * General Public License for more details.
    17  *
    18  * You should have received a copy of the GNU General Public License
    19  * along with this program; if not, write to the Free Software
    20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    21  *
    228 * 2002-04-20
    239 * IPV6 support added by Bart Visscher <magick@linux-fan.com>
     10 *
     11 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
    2412 */
    2513
    26 #include <stdio.h>
    27 #include <stdlib.h>
    28 #include <string.h>
    29 #include <stdarg.h>
    30 #include <signal.h>
    31 #include <errno.h>
    32 #include <sys/stat.h>
    33 #include <dirent.h>
    34 #include <unistd.h>
     14#include "libbb.h"
    3515#include "inet_common.h"
    36 #include "busybox.h"
    37 #include "pwd_.h"
    38 
    39 #ifdef CONFIG_ROUTE
    40 extern void displayroutes(int noresolve, int netstatfmt);
    41 #endif
    42 
    43 #define NETSTAT_CONNECTED   0x01
    44 #define NETSTAT_LISTENING   0x02
    45 #define NETSTAT_NUMERIC     0x04
    46 #define NETSTAT_TCP         0x10
    47 #define NETSTAT_UDP         0x20
    48 #define NETSTAT_RAW         0x40
    49 #define NETSTAT_UNIX        0x80
    50 
    51 static int flags = NETSTAT_CONNECTED |
    52             NETSTAT_TCP | NETSTAT_UDP | NETSTAT_RAW | NETSTAT_UNIX;
    53 
    54 #define PROGNAME_WIDTHs PROGNAME_WIDTH1(PROGNAME_WIDTH)
    55 #define PROGNAME_WIDTH1(s) PROGNAME_WIDTH2(s)
    56 #define PROGNAME_WIDTH2(s) #s
    57 
    58 #define PRG_HASH_SIZE 211
    5916
    6017enum {
    61     TCP_ESTABLISHED = 1,
    62     TCP_SYN_SENT,
    63     TCP_SYN_RECV,
    64     TCP_FIN_WAIT1,
    65     TCP_FIN_WAIT2,
    66     TCP_TIME_WAIT,
    67     TCP_CLOSE,
    68     TCP_CLOSE_WAIT,
    69     TCP_LAST_ACK,
    70     TCP_LISTEN,
    71     TCP_CLOSING         /* now a valid state */
     18    OPT_extended = 0x4,
     19    OPT_showroute = 0x100,
     20    OPT_widedisplay = 0x200 * ENABLE_FEATURE_NETSTAT_WIDE,
    7221};
    73 
    74 static const char * const tcp_state[] =
    75 {
    76     "",
    77     "ESTABLISHED",
    78     "SYN_SENT",
    79     "SYN_RECV",
    80     "FIN_WAIT1",
    81     "FIN_WAIT2",
    82     "TIME_WAIT",
    83     "CLOSE",
    84     "CLOSE_WAIT",
    85     "LAST_ACK",
    86     "LISTEN",
    87     "CLOSING"
     22# define NETSTAT_OPTS "laentuwxr"USE_FEATURE_NETSTAT_WIDE("W")
     23
     24#define NETSTAT_CONNECTED 0x01
     25#define NETSTAT_LISTENING 0x02
     26#define NETSTAT_NUMERIC   0x04
     27/* Must match getopt32 option string */
     28#define NETSTAT_TCP       0x10
     29#define NETSTAT_UDP       0x20
     30#define NETSTAT_RAW       0x40
     31#define NETSTAT_UNIX      0x80
     32#define NETSTAT_ALLPROTO  (NETSTAT_TCP|NETSTAT_UDP|NETSTAT_RAW|NETSTAT_UNIX)
     33
     34static smallint flags = NETSTAT_CONNECTED | NETSTAT_ALLPROTO;
     35
     36enum {
     37    TCP_ESTABLISHED = 1,
     38    TCP_SYN_SENT,
     39    TCP_SYN_RECV,
     40    TCP_FIN_WAIT1,
     41    TCP_FIN_WAIT2,
     42    TCP_TIME_WAIT,
     43    TCP_CLOSE,
     44    TCP_CLOSE_WAIT,
     45    TCP_LAST_ACK,
     46    TCP_LISTEN,
     47    TCP_CLOSING /* now a valid state */
    8848};
    8949
     50static const char *const tcp_state[] = {
     51    "",
     52    "ESTABLISHED",
     53    "SYN_SENT",
     54    "SYN_RECV",
     55    "FIN_WAIT1",
     56    "FIN_WAIT2",
     57    "TIME_WAIT",
     58    "CLOSE",
     59    "CLOSE_WAIT",
     60    "LAST_ACK",
     61    "LISTEN",
     62    "CLOSING"
     63};
     64
    9065typedef enum {
    91     SS_FREE = 0,        /* not allocated                */
    92     SS_UNCONNECTED,     /* unconnected to any socket    */
    93     SS_CONNECTING,      /* in process of connecting     */
    94     SS_CONNECTED,       /* connected to socket          */
    95     SS_DISCONNECTING        /* in process of disconnecting  */
     66    SS_FREE = 0,     /* not allocated                */
     67    SS_UNCONNECTED,  /* unconnected to any socket    */
     68    SS_CONNECTING,   /* in process of connecting     */
     69    SS_CONNECTED,    /* connected to socket          */
     70    SS_DISCONNECTING /* in process of disconnecting  */
    9671} socket_state;
    9772
    98 #define SO_ACCEPTCON    (1<<16) /* performed a listen           */
    99 #define SO_WAITDATA     (1<<17) /* wait data to read            */
    100 #define SO_NOSPACE      (1<<18) /* no space to write            */
    101 
    102 static char *itoa(unsigned int i)
    103 {
    104     /* 21 digits plus null terminator, good for 64-bit or smaller ints */
    105     static char local[22];
    106     char *p = &local[21];
    107     *p-- = '\0';
    108     do {
    109         *p-- = '0' + i % 10;
    110         i /= 10;
    111     } while (i > 0);
    112     return p + 1;
    113 }
    114 
    115 static char *get_sname(int port, const char *proto, int num)
    116 {
    117     char *str=itoa(ntohs(port));
    118     if (num) {
     73#define SO_ACCEPTCON (1<<16)    /* performed a listen           */
     74#define SO_WAITDATA  (1<<17)    /* wait data to read            */
     75#define SO_NOSPACE   (1<<18)    /* no space to write            */
     76
     77/* Standard printout size */
     78#define PRINT_IP_MAX_SIZE           23
     79#define PRINT_NET_CONN              "%s   %6ld %6ld %-23s %-23s %-12s\n"
     80#define PRINT_NET_CONN_HEADER       "\nProto Recv-Q Send-Q %-23s %-23s State\n"
     81
     82/* When there are IPv6 connections the IPv6 addresses will be
     83 * truncated to none-recognition. The '-W' option makes the
     84 * address columns wide enough to accomodate for longest possible
     85 * IPv6 addresses, i.e. addresses of the form
     86 * xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:ddd.ddd.ddd.ddd
     87 */
     88#define PRINT_IP_MAX_SIZE_WIDE      51  /* INET6_ADDRSTRLEN + 5 for the port number */
     89#define PRINT_NET_CONN_WIDE         "%s   %6ld %6ld %-51s %-51s %-12s\n"
     90#define PRINT_NET_CONN_HEADER_WIDE  "\nProto Recv-Q Send-Q %-51s %-51s State\n"
     91
     92static const char *net_conn_line = PRINT_NET_CONN;
     93
     94
     95#if ENABLE_FEATURE_IPV6
     96static void build_ipv6_addr(char* local_addr, struct sockaddr_in6* localaddr)
     97{
     98    char addr6[INET6_ADDRSTRLEN];
     99    struct in6_addr in6;
     100
     101    sscanf(local_addr, "%08X%08X%08X%08X",
     102           &in6.s6_addr32[0], &in6.s6_addr32[1],
     103           &in6.s6_addr32[2], &in6.s6_addr32[3]);
     104    inet_ntop(AF_INET6, &in6, addr6, sizeof(addr6));
     105    inet_pton(AF_INET6, addr6, (struct sockaddr *) &localaddr->sin6_addr);
     106
     107    localaddr->sin6_family = AF_INET6;
     108}
     109#endif
     110
     111#if ENABLE_FEATURE_IPV6
     112static void build_ipv4_addr(char* local_addr, struct sockaddr_in6* localaddr)
     113#else
     114static void build_ipv4_addr(char* local_addr, struct sockaddr_in* localaddr)
     115#endif
     116{
     117    sscanf(local_addr, "%X",
     118           &((struct sockaddr_in *) localaddr)->sin_addr.s_addr);
     119    ((struct sockaddr *) localaddr)->sa_family = AF_INET;
     120}
     121
     122static const char *get_sname(int port, const char *proto, int numeric)
     123{
     124    if (!port)
     125        return "*";
     126    if (!numeric) {
     127        struct servent *se = getservbyport(port, proto);
     128        if (se)
     129            return se->s_name;
     130    }
     131    /* hummm, we may return static buffer here!! */
     132    return itoa(ntohs(port));
     133}
     134
     135static char *ip_port_str(struct sockaddr *addr, int port, const char *proto, int numeric)
     136{
     137    enum { salen = USE_FEATURE_IPV6(sizeof(struct sockaddr_in6)) SKIP_FEATURE_IPV6(sizeof(struct sockaddr_in)) };
     138    char *host, *host_port;
     139
     140    /* Code which used "*" for INADDR_ANY is removed: it's ambiguous in IPv6,
     141     * while "0.0.0.0" is not. */
     142
     143    host = numeric ? xmalloc_sockaddr2dotted_noport(addr)
     144                   : xmalloc_sockaddr2host_noport(addr);
     145
     146    host_port = xasprintf("%s:%s", host, get_sname(htons(port), proto, numeric));
     147    free(host);
     148    return host_port;
     149}
     150
     151static void tcp_do_one(int lnr, const char *line)
     152{
     153    char local_addr[64], rem_addr[64];
     154    char more[512];
     155    int num, local_port, rem_port, d, state, timer_run, uid, timeout;
     156#if ENABLE_FEATURE_IPV6
     157    struct sockaddr_in6 localaddr, remaddr;
     158#else
     159    struct sockaddr_in localaddr, remaddr;
     160#endif
     161    unsigned long rxq, txq, time_len, retr, inode;
     162
     163    if (lnr == 0)
     164        return;
     165
     166    more[0] = '\0';
     167    num = sscanf(line,
     168            "%d: %64[0-9A-Fa-f]:%X %64[0-9A-Fa-f]:%X %X %lX:%lX %X:%lX %lX %d %d %ld %512s\n",
     169            &d, local_addr, &local_port,
     170            rem_addr, &rem_port, &state,
     171            &txq, &rxq, &timer_run, &time_len, &retr, &uid, &timeout, &inode, more);
     172
     173    if (strlen(local_addr) > 8) {
     174#if ENABLE_FEATURE_IPV6
     175        build_ipv6_addr(local_addr, &localaddr);
     176        build_ipv6_addr(rem_addr, &remaddr);
     177#endif
    119178    } else {
    120         struct servent *se=getservbyport(port,proto);
    121         if (se)
    122             str=se->s_name;
    123     }
    124     if (!port) {
    125         str="*";
    126     }
    127     return str;
    128 }
    129 
    130 static void snprint_ip_port(char *ip_port, int size, struct sockaddr *addr, int port, char *proto, int numeric)
    131 {
    132     char *port_name;
    133 
    134 #ifdef CONFIG_FEATURE_IPV6
    135     if (addr->sa_family == AF_INET6) {
    136         INET6_rresolve(ip_port, size, (struct sockaddr_in6 *)addr,
    137                        (numeric&NETSTAT_NUMERIC) ? 0x0fff : 0);
    138     } else
    139 #endif
    140     {
    141     INET_rresolve(ip_port, size, (struct sockaddr_in *)addr,
    142         0x4000 | ((numeric&NETSTAT_NUMERIC) ? 0x0fff : 0),
    143         0xffffffff);
    144     }
    145     port_name=get_sname(htons(port), proto, numeric);
    146     if ((strlen(ip_port) + strlen(port_name)) > 22)
    147         ip_port[22 - strlen(port_name)] = '\0';
    148     ip_port+=strlen(ip_port);
    149     strcat(ip_port, ":");
    150     strcat(ip_port, port_name);
    151 }
    152 
    153 static void tcp_do_one(int lnr, const char *line)
     179        build_ipv4_addr(local_addr, &localaddr);
     180        build_ipv4_addr(rem_addr, &remaddr);
     181    }
     182
     183    if (num < 10) {
     184        bb_error_msg("warning, got bogus tcp line");
     185        return;
     186    }
     187
     188    if ((rem_port && (flags & NETSTAT_CONNECTED))
     189     || (!rem_port && (flags & NETSTAT_LISTENING))
     190    ) {
     191        char *l = ip_port_str(
     192                (struct sockaddr *) &localaddr, local_port,
     193                "tcp", flags & NETSTAT_NUMERIC);
     194        char *r = ip_port_str(
     195                (struct sockaddr *) &remaddr, rem_port,
     196                "tcp", flags & NETSTAT_NUMERIC);
     197        printf(net_conn_line,
     198            "tcp", rxq, txq, l, r, tcp_state[state]);
     199        free(l);
     200        free(r);
     201    }
     202}
     203
     204static void udp_do_one(int lnr, const char *line)
    154205{
    155206    char local_addr[64], rem_addr[64];
     
    157208    char more[512];
    158209    int num, local_port, rem_port, d, state, timer_run, uid, timeout;
    159 #ifdef CONFIG_FEATURE_IPV6
     210#if ENABLE_FEATURE_IPV6
    160211    struct sockaddr_in6 localaddr, remaddr;
    161     char addr6[INET6_ADDRSTRLEN];
    162     struct in6_addr in6;
    163212#else
    164213    struct sockaddr_in localaddr, remaddr;
     
    171220    more[0] = '\0';
    172221    num = sscanf(line,
    173                  "%d: %64[0-9A-Fa-f]:%X %64[0-9A-Fa-f]:%X %X %lX:%lX %X:%lX %lX %d %d %ld %512s\n",
    174                  &d, local_addr, &local_port,
    175                  rem_addr, &rem_port, &state,
    176                  &txq, &rxq, &timer_run, &time_len, &retr, &uid, &timeout, &inode, more);
     222            "%d: %64[0-9A-Fa-f]:%X %64[0-9A-Fa-f]:%X %X %lX:%lX %X:%lX %lX %d %d %ld %512s\n",
     223            &d, local_addr, &local_port,
     224            rem_addr, &rem_port, &state,
     225            &txq, &rxq, &timer_run, &time_len, &retr, &uid, &timeout, &inode, more);
    177226
    178227    if (strlen(local_addr) > 8) {
    179 #ifdef CONFIG_FEATURE_IPV6
    180         sscanf(local_addr, "%08X%08X%08X%08X",
    181                &in6.s6_addr32[0], &in6.s6_addr32[1],
    182                &in6.s6_addr32[2], &in6.s6_addr32[3]);
    183         inet_ntop(AF_INET6, &in6, addr6, sizeof(addr6));
    184         inet_pton(AF_INET6, addr6, (struct sockaddr *) &localaddr.sin6_addr);
    185         sscanf(rem_addr, "%08X%08X%08X%08X",
    186                &in6.s6_addr32[0], &in6.s6_addr32[1],
    187                &in6.s6_addr32[2], &in6.s6_addr32[3]);
    188         inet_ntop(AF_INET6, &in6, addr6, sizeof(addr6));
    189         inet_pton(AF_INET6, addr6, (struct sockaddr *) &remaddr.sin6_addr);
    190         localaddr.sin6_family = AF_INET6;
    191         remaddr.sin6_family = AF_INET6;
     228#if ENABLE_FEATURE_IPV6
     229        /* Demangle what the kernel gives us */
     230        build_ipv6_addr(local_addr, &localaddr);
     231        build_ipv6_addr(rem_addr, &remaddr);
    192232#endif
    193233    } else {
    194         sscanf(local_addr, "%X",
    195                &((struct sockaddr_in *) &localaddr)->sin_addr.s_addr);
    196         sscanf(rem_addr, "%X",
    197                &((struct sockaddr_in *) &remaddr)->sin_addr.s_addr);
    198         ((struct sockaddr *) &localaddr)->sa_family = AF_INET;
    199         ((struct sockaddr *) &remaddr)->sa_family = AF_INET;
     234        build_ipv4_addr(local_addr, &localaddr);
     235        build_ipv4_addr(rem_addr, &remaddr);
    200236    }
    201237
    202238    if (num < 10) {
    203         bb_error_msg("warning, got bogus tcp line.");
    204         return;
    205     }
    206     state_str = tcp_state[state];
    207     if ((rem_port && (flags&NETSTAT_CONNECTED)) ||
    208         (!rem_port && (flags&NETSTAT_LISTENING)))
    209     {
    210         snprint_ip_port(local_addr, sizeof(local_addr),
    211                         (struct sockaddr *) &localaddr, local_port,
    212                         "tcp", flags&NETSTAT_NUMERIC);
    213 
    214         snprint_ip_port(rem_addr, sizeof(rem_addr),
    215                         (struct sockaddr *) &remaddr, rem_port,
    216                         "tcp", flags&NETSTAT_NUMERIC);
    217 
    218         printf("tcp   %6ld %6ld %-23s %-23s %-12s\n",
    219                rxq, txq, local_addr, rem_addr, state_str);
    220 
    221     }
    222 }
    223 
    224 static void udp_do_one(int lnr, const char *line)
    225 {
    226     char local_addr[64], rem_addr[64];
    227     char *state_str, more[512];
    228     int num, local_port, rem_port, d, state, timer_run, uid, timeout;
    229 #ifdef CONFIG_FEATURE_IPV6
    230     struct sockaddr_in6 localaddr, remaddr;
    231     char addr6[INET6_ADDRSTRLEN];
    232     struct in6_addr in6;
    233 #else
    234     struct sockaddr_in localaddr, remaddr;
    235 #endif
    236     unsigned long rxq, txq, time_len, retr, inode;
    237 
    238     if (lnr == 0)
    239         return;
    240 
    241     more[0] = '\0';
    242     num = sscanf(line,
    243                  "%d: %64[0-9A-Fa-f]:%X %64[0-9A-Fa-f]:%X %X %lX:%lX %X:%lX %lX %d %d %ld %512s\n",
    244                  &d, local_addr, &local_port,
    245                  rem_addr, &rem_port, &state,
    246                  &txq, &rxq, &timer_run, &time_len, &retr, &uid, &timeout, &inode, more);
    247 
    248     if (strlen(local_addr) > 8) {
    249 #ifdef CONFIG_FEATURE_IPV6
    250     /* Demangle what the kernel gives us */
    251         sscanf(local_addr, "%08X%08X%08X%08X",
    252                &in6.s6_addr32[0], &in6.s6_addr32[1],
    253                &in6.s6_addr32[2], &in6.s6_addr32[3]);
    254         inet_ntop(AF_INET6, &in6, addr6, sizeof(addr6));
    255         inet_pton(AF_INET6, addr6, (struct sockaddr *) &localaddr.sin6_addr);
    256         sscanf(rem_addr, "%08X%08X%08X%08X",
    257                &in6.s6_addr32[0], &in6.s6_addr32[1],
    258                &in6.s6_addr32[2], &in6.s6_addr32[3]);
    259         inet_ntop(AF_INET6, &in6, addr6, sizeof(addr6));
    260         inet_pton(AF_INET6, addr6, (struct sockaddr *) &remaddr.sin6_addr);
    261         localaddr.sin6_family = AF_INET6;
    262         remaddr.sin6_family = AF_INET6;
    263 #endif
    264     } else {
    265         sscanf(local_addr, "%X",
    266                &((struct sockaddr_in *) &localaddr)->sin_addr.s_addr);
    267         sscanf(rem_addr, "%X",
    268                &((struct sockaddr_in *) &remaddr)->sin_addr.s_addr);
    269         ((struct sockaddr *) &localaddr)->sa_family = AF_INET;
    270         ((struct sockaddr *) &remaddr)->sa_family = AF_INET;
    271     }
    272 
    273     if (num < 10) {
    274         bb_error_msg("warning, got bogus udp line.");
     239        bb_error_msg("warning, got bogus udp line");
    275240        return;
    276241    }
     
    279244            state_str = "ESTABLISHED";
    280245            break;
    281 
    282246        case TCP_CLOSE:
    283247            state_str = "";
    284248            break;
    285 
    286249        default:
    287250            state_str = "UNKNOWN";
     
    289252    }
    290253
    291 #ifdef CONFIG_FEATURE_IPV6
    292 # define notnull(A) (((A.sin6_family == AF_INET6) &&            \
    293                      ((A.sin6_addr.s6_addr32[0]) ||            \
    294                       (A.sin6_addr.s6_addr32[1]) ||            \
    295                       (A.sin6_addr.s6_addr32[2]) ||            \
    296                       (A.sin6_addr.s6_addr32[3]))) ||          \
    297                     ((A.sin6_family == AF_INET) &&             \
    298                      ((struct sockaddr_in *) &A)->sin_addr.s_addr))
     254#if ENABLE_FEATURE_IPV6
     255# define notnull(A) ( \
     256    ( (A.sin6_family == AF_INET6)                               \
     257      && (A.sin6_addr.s6_addr32[0] | A.sin6_addr.s6_addr32[1] | \
     258          A.sin6_addr.s6_addr32[2] | A.sin6_addr.s6_addr32[3])  \
     259    ) || (                                                      \
     260      (A.sin6_family == AF_INET)                                \
     261      && ((struct sockaddr_in*)&A)->sin_addr.s_addr             \
     262    )                                                           \
     263)
    299264#else
    300265# define notnull(A) (A.sin_addr.s_addr)
    301266#endif
    302     if ((notnull(remaddr) && (flags&NETSTAT_CONNECTED)) ||
    303         (!notnull(remaddr) && (flags&NETSTAT_LISTENING)))
    304267    {
    305         snprint_ip_port(local_addr, sizeof(local_addr),
    306                         (struct sockaddr *) &localaddr, local_port,
    307                         "udp", flags&NETSTAT_NUMERIC);
    308 
    309         snprint_ip_port(rem_addr, sizeof(rem_addr),
    310                         (struct sockaddr *) &remaddr, rem_port,
    311                         "udp", flags&NETSTAT_NUMERIC);
    312 
    313         printf("udp   %6ld %6ld %-23s %-23s %-12s\n",
    314                rxq, txq, local_addr, rem_addr, state_str);
    315 
     268        int have_remaddr = notnull(remaddr);
     269        if ((have_remaddr && (flags & NETSTAT_CONNECTED))
     270         || (!have_remaddr && (flags & NETSTAT_LISTENING))
     271        ) {
     272            char *l = ip_port_str(
     273                (struct sockaddr *) &localaddr, local_port,
     274                "udp", flags & NETSTAT_NUMERIC);
     275            char *r = ip_port_str(
     276                (struct sockaddr *) &remaddr, rem_port,
     277                "udp", flags & NETSTAT_NUMERIC);
     278            printf(net_conn_line,
     279                "udp", rxq, txq, l, r, state_str);
     280            free(l);
     281            free(r);
     282        }
    316283    }
    317284}
     
    320287{
    321288    char local_addr[64], rem_addr[64];
    322     char *state_str, more[512];
     289    char more[512];
    323290    int num, local_port, rem_port, d, state, timer_run, uid, timeout;
    324 #ifdef CONFIG_FEATURE_IPV6
     291#if ENABLE_FEATURE_IPV6
    325292    struct sockaddr_in6 localaddr, remaddr;
    326     char addr6[INET6_ADDRSTRLEN];
    327     struct in6_addr in6;
    328293#else
    329294    struct sockaddr_in localaddr, remaddr;
     
    336301    more[0] = '\0';
    337302    num = sscanf(line,
    338                  "%d: %64[0-9A-Fa-f]:%X %64[0-9A-Fa-f]:%X %X %lX:%lX %X:%lX %lX %d %d %ld %512s\n",
    339                  &d, local_addr, &local_port,
    340                  rem_addr, &rem_port, &state,
    341                  &txq, &rxq, &timer_run, &time_len, &retr, &uid, &timeout, &inode, more);
     303            "%d: %64[0-9A-Fa-f]:%X %64[0-9A-Fa-f]:%X %X %lX:%lX %X:%lX %lX %d %d %ld %512s\n",
     304            &d, local_addr, &local_port,
     305            rem_addr, &rem_port, &state,
     306            &txq, &rxq, &timer_run, &time_len, &retr, &uid, &timeout, &inode, more);
    342307
    343308    if (strlen(local_addr) > 8) {
    344 #ifdef CONFIG_FEATURE_IPV6
    345         sscanf(local_addr, "%08X%08X%08X%08X",
    346                &in6.s6_addr32[0], &in6.s6_addr32[1],
    347                &in6.s6_addr32[2], &in6.s6_addr32[3]);
    348         inet_ntop(AF_INET6, &in6, addr6, sizeof(addr6));
    349         inet_pton(AF_INET6, addr6, (struct sockaddr *) &localaddr.sin6_addr);
    350         sscanf(rem_addr, "%08X%08X%08X%08X",
    351                &in6.s6_addr32[0], &in6.s6_addr32[1],
    352                &in6.s6_addr32[2], &in6.s6_addr32[3]);
    353         inet_ntop(AF_INET6, &in6, addr6, sizeof(addr6));
    354         inet_pton(AF_INET6, addr6, (struct sockaddr *) &remaddr.sin6_addr);
    355         localaddr.sin6_family = AF_INET6;
    356         remaddr.sin6_family = AF_INET6;
     309#if ENABLE_FEATURE_IPV6
     310        build_ipv6_addr(local_addr, &localaddr);
     311        build_ipv6_addr(rem_addr, &remaddr);
    357312#endif
    358313    } else {
    359         sscanf(local_addr, "%X",
    360                &((struct sockaddr_in *) &localaddr)->sin_addr.s_addr);
    361         sscanf(rem_addr, "%X",
    362                &((struct sockaddr_in *) &remaddr)->sin_addr.s_addr);
    363         ((struct sockaddr *) &localaddr)->sa_family = AF_INET;
    364         ((struct sockaddr *) &remaddr)->sa_family = AF_INET;
     314        build_ipv4_addr(local_addr, &localaddr);
     315        build_ipv4_addr(rem_addr, &remaddr);
    365316    }
    366317
    367318    if (num < 10) {
    368         bb_error_msg("warning, got bogus raw line.");
    369         return;
    370     }
    371     state_str=itoa(state);
    372 
    373 #ifdef CONFIG_FEATURE_IPV6
    374 # define notnull(A) (((A.sin6_family == AF_INET6) &&            \
    375                      ((A.sin6_addr.s6_addr32[0]) ||            \
    376                       (A.sin6_addr.s6_addr32[1]) ||            \
    377                       (A.sin6_addr.s6_addr32[2]) ||            \
    378                       (A.sin6_addr.s6_addr32[3]))) ||          \
    379                     ((A.sin6_family == AF_INET) &&             \
    380                      ((struct sockaddr_in *) &A)->sin_addr.s_addr))
    381 #else
    382 # define notnull(A) (A.sin_addr.s_addr)
    383 #endif
    384     if ((notnull(remaddr) && (flags&NETSTAT_CONNECTED)) ||
    385         (!notnull(remaddr) && (flags&NETSTAT_LISTENING)))
     319        bb_error_msg("warning, got bogus raw line");
     320        return;
     321    }
     322
    386323    {
    387         snprint_ip_port(local_addr, sizeof(local_addr),
    388                         (struct sockaddr *) &localaddr, local_port,
    389                         "raw", flags&NETSTAT_NUMERIC);
    390 
    391         snprint_ip_port(rem_addr, sizeof(rem_addr),
    392                         (struct sockaddr *) &remaddr, rem_port,
    393                         "raw", flags&NETSTAT_NUMERIC);
    394 
    395         printf("raw   %6ld %6ld %-23s %-23s %-12s\n",
    396                rxq, txq, local_addr, rem_addr, state_str);
    397 
    398     }
    399 }
    400 
    401 #define HAS_INODE 1
     324        int have_remaddr = notnull(remaddr);
     325        if ((have_remaddr && (flags & NETSTAT_CONNECTED))
     326         || (!have_remaddr && (flags & NETSTAT_LISTENING))
     327        ) {
     328            char *l = ip_port_str(
     329                (struct sockaddr *) &localaddr, local_port,
     330                "raw", flags & NETSTAT_NUMERIC);
     331            char *r = ip_port_str(
     332                (struct sockaddr *) &remaddr, rem_port,
     333                "raw", flags & NETSTAT_NUMERIC);
     334            printf(net_conn_line,
     335                "raw", rxq, txq, l, r, itoa(state));
     336            free(l);
     337            free(r);
     338        }
     339    }
     340}
    402341
    403342static void unix_do_one(int nr, const char *line)
    404343{
    405     static int has = 0;
     344    static smallint has_inode = 0;
     345
    406346    char path[PATH_MAX], ss_flags[32];
    407     char *ss_proto, *ss_state, *ss_type;
     347    const char *ss_proto, *ss_state, *ss_type;
    408348    int num, state, type, inode;
    409349    void *d;
     
    412352    if (nr == 0) {
    413353        if (strstr(line, "Inode"))
    414             has |= HAS_INODE;
     354            has_inode = 1;
    415355        return;
    416356    }
    417357    path[0] = '\0';
    418358    num = sscanf(line, "%p: %lX %lX %lX %X %X %d %s",
    419                  &d, &refcnt, &proto, &unix_flags, &type, &state, &inode, path);
     359            &d, &refcnt, &proto, &unix_flags, &type, &state, &inode, path);
    420360    if (num < 6) {
    421         bb_error_msg("warning, got bogus unix line.");
    422         return;
    423     }
    424     if (!(has & HAS_INODE))
    425         snprintf(path,sizeof(path),"%d",inode);
    426 
    427     if ((flags&(NETSTAT_LISTENING|NETSTAT_CONNECTED))!=(NETSTAT_LISTENING|NETSTAT_CONNECTED)) {
     361        bb_error_msg("warning, got bogus unix line");
     362        return;
     363    }
     364    if (!has_inode)
     365        sprintf(path, "%d", inode);
     366
     367    if ((flags & (NETSTAT_LISTENING|NETSTAT_CONNECTED)) != (NETSTAT_LISTENING|NETSTAT_CONNECTED)) {
    428368        if ((state == SS_UNCONNECTED) && (unix_flags & SO_ACCEPTCON)) {
    429             if (!(flags&NETSTAT_LISTENING))
     369            if (!(flags & NETSTAT_LISTENING))
    430370                return;
    431371        } else {
    432             if (!(flags&NETSTAT_CONNECTED))
     372            if (!(flags & NETSTAT_CONNECTED))
    433373                return;
    434374        }
     
    439379            ss_proto = "unix";
    440380            break;
    441 
    442381        default:
    443382            ss_proto = "??";
     
    448387            ss_type = "STREAM";
    449388            break;
    450 
    451389        case SOCK_DGRAM:
    452390            ss_type = "DGRAM";
    453391            break;
    454 
    455392        case SOCK_RAW:
    456393            ss_type = "RAW";
    457394            break;
    458 
    459395        case SOCK_RDM:
    460396            ss_type = "RDM";
    461397            break;
    462 
    463398        case SOCK_SEQPACKET:
    464399            ss_type = "SEQPACKET";
    465400            break;
    466 
    467401        default:
    468402            ss_type = "UNKNOWN";
     
    473407            ss_state = "FREE";
    474408            break;
    475 
    476409        case SS_UNCONNECTED:
    477410            /*
     
    485418            }
    486419            break;
    487 
    488420        case SS_CONNECTING:
    489421            ss_state = "CONNECTING";
    490422            break;
    491 
    492423        case SS_CONNECTED:
    493424            ss_state = "CONNECTED";
    494425            break;
    495 
    496426        case SS_DISCONNECTING:
    497427            ss_state = "DISCONNECTING";
    498428            break;
    499 
    500429        default:
    501430            ss_state = "UNKNOWN";
     
    509438    if (unix_flags & SO_NOSPACE)
    510439        strcat(ss_flags, "N ");
    511 
    512440    strcat(ss_flags, "]");
    513441
    514442    printf("%-5s %-6ld %-11s %-10s %-13s ",
    515443           ss_proto, refcnt, ss_flags, ss_type, ss_state);
    516     if (has & HAS_INODE)
    517         printf("%-6d ",inode);
     444    if (has_inode)
     445        printf("%-6d ", inode);
    518446    else
    519447        printf("-      ");
     
    531459static void do_info(const char *file, const char *name, void (*proc)(int, const char *))
    532460{
    533     char buffer[8192];
    534461    int lnr = 0;
    535462    FILE *procinfo;
     
    538465    if (procinfo == NULL) {
    539466        if (errno != ENOENT) {
    540             perror(file);
     467            bb_perror_msg("%s", file);
    541468        } else {
    542         bb_error_msg("no support for `%s' on this system.", name);
     469            bb_error_msg("no support for '%s' on this system", name);
    543470        }
    544     } else {
    545         do {
    546             if (fgets(buffer, sizeof(buffer), procinfo))
    547                 (proc)(lnr++, buffer);
    548         } while (!feof(procinfo));
    549         fclose(procinfo);
    550     }
     471        return;
     472    }
     473    do {
     474        char *buffer = xmalloc_fgets(procinfo);
     475        if (buffer) {
     476            (proc)(lnr++, buffer);
     477            free(buffer);
     478        }
     479    } while (!feof(procinfo));
     480    fclose(procinfo);
    551481}
    552482
     
    555485 */
    556486
     487int netstat_main(int argc, char **argv);
    557488int netstat_main(int argc, char **argv)
    558489{
    559     int opt;
    560     int new_flags=0;
    561     int showroute = 0, extended = 0;
    562 #ifdef CONFIG_FEATURE_IPV6
    563     int inet=1;
    564     int inet6=1;
    565 #else
    566 # define inet 1
    567 # define inet6 0
    568 #endif
    569     while ((opt = getopt(argc, argv, "laenrtuwx")) != -1)
    570         switch (opt) {
    571         case 'l':
    572             flags &= ~NETSTAT_CONNECTED;
    573             flags |= NETSTAT_LISTENING;
    574             break;
    575         case 'a':
    576             flags |= NETSTAT_LISTENING | NETSTAT_CONNECTED;
    577             break;
    578         case 'n':
    579             flags |= NETSTAT_NUMERIC;
    580             break;
    581         case 'r':
    582             showroute = 1;
    583             break;
    584         case 'e':
    585             extended = 1;
    586             break;
    587         case 't':
    588             new_flags |= NETSTAT_TCP;
    589             break;
    590         case 'u':
    591             new_flags |= NETSTAT_UDP;
    592             break;
    593         case 'w':
    594             new_flags |= NETSTAT_RAW;
    595             break;
    596         case 'x':
    597             new_flags |= NETSTAT_UNIX;
    598             break;
    599         default:
    600             bb_show_usage();
    601         }
    602     if ( showroute ) {
    603 #ifdef CONFIG_ROUTE
    604         displayroutes ( flags & NETSTAT_NUMERIC, !extended );
     490    const char *net_conn_line_header = PRINT_NET_CONN_HEADER;
     491    unsigned opt;
     492#if ENABLE_FEATURE_IPV6
     493    smallint inet = 1;
     494    smallint inet6 = 1;
     495#else
     496    enum { inet = 1, inet6 = 0 };
     497#endif
     498
     499    /* Option string must match NETSTAT_xxx constants */
     500    opt = getopt32(argv, NETSTAT_OPTS);
     501    if (opt & 0x1) { // -l
     502        flags &= ~NETSTAT_CONNECTED;
     503        flags |= NETSTAT_LISTENING;
     504    }
     505    if (opt & 0x2) flags |= NETSTAT_LISTENING | NETSTAT_CONNECTED; // -a
     506    //if (opt & 0x4) // -e
     507    if (opt & 0x8) flags |= NETSTAT_NUMERIC; // -n
     508    //if (opt & 0x10) // -t: NETSTAT_TCP
     509    //if (opt & 0x20) // -u: NETSTAT_UDP
     510    //if (opt & 0x40) // -w: NETSTAT_RAW
     511    //if (opt & 0x80) // -x: NETSTAT_UNIX
     512    if (opt & OPT_showroute) { // -r
     513#if ENABLE_ROUTE
     514        bb_displayroutes(flags & NETSTAT_NUMERIC, !(opt & OPT_extended));
    605515        return 0;
    606516#else
    607         bb_error_msg_and_die( "-r (display routing table) is not compiled in." );
    608 #endif
    609     }
    610 
    611     if (new_flags) {
    612         flags &= ~(NETSTAT_TCP|NETSTAT_UDP|NETSTAT_RAW|NETSTAT_UNIX);
    613         flags |= new_flags;
    614     }
    615     if (flags&(NETSTAT_TCP|NETSTAT_UDP|NETSTAT_RAW)) {
     517        bb_show_usage();
     518#endif
     519    }
     520
     521    if (opt & OPT_widedisplay) { // -W
     522        net_conn_line = PRINT_NET_CONN_WIDE;
     523        net_conn_line_header = PRINT_NET_CONN_HEADER_WIDE;
     524    }
     525
     526    opt &= NETSTAT_ALLPROTO;
     527    if (opt) {
     528        flags &= ~NETSTAT_ALLPROTO;
     529        flags |= opt;
     530    }
     531    if (flags & (NETSTAT_TCP|NETSTAT_UDP|NETSTAT_RAW)) {
    616532        printf("Active Internet connections "); /* xxx */
    617533
    618         if ((flags&(NETSTAT_LISTENING|NETSTAT_CONNECTED))==(NETSTAT_LISTENING|NETSTAT_CONNECTED))
     534        if ((flags & (NETSTAT_LISTENING|NETSTAT_CONNECTED)) == (NETSTAT_LISTENING|NETSTAT_CONNECTED))
    619535            printf("(servers and established)");
    620         else {
    621             if (flags&NETSTAT_LISTENING)
    622                 printf("(only servers)");
    623             else
    624                 printf("(w/o servers)");
    625         }
    626         printf("\nProto Recv-Q Send-Q Local Address           Foreign Address         State      \n");
    627     }
    628     if (inet && flags&NETSTAT_TCP)
    629         do_info(_PATH_PROCNET_TCP,"AF INET (tcp)",tcp_do_one);
    630 #ifdef CONFIG_FEATURE_IPV6
    631     if (inet6 && flags&NETSTAT_TCP)
    632         do_info(_PATH_PROCNET_TCP6,"AF INET6 (tcp)",tcp_do_one);
    633 #endif
    634     if (inet && flags&NETSTAT_UDP)
    635         do_info(_PATH_PROCNET_UDP,"AF INET (udp)",udp_do_one);
    636 #ifdef CONFIG_FEATURE_IPV6
    637     if (inet6 && flags&NETSTAT_UDP)
    638         do_info(_PATH_PROCNET_UDP6,"AF INET6 (udp)",udp_do_one);
    639 #endif
    640     if (inet && flags&NETSTAT_RAW)
    641         do_info(_PATH_PROCNET_RAW,"AF INET (raw)",raw_do_one);
    642 #ifdef CONFIG_FEATURE_IPV6
    643     if (inet6 && flags&NETSTAT_RAW)
    644         do_info(_PATH_PROCNET_RAW6,"AF INET6 (raw)",raw_do_one);
    645 #endif
    646     if (flags&NETSTAT_UNIX) {
     536        else if (flags & NETSTAT_LISTENING)
     537            printf("(only servers)");
     538        else
     539            printf("(w/o servers)");
     540        printf(net_conn_line_header, "Local Address", "Foreign Address");
     541    }
     542    if (inet && flags & NETSTAT_TCP)
     543        do_info(_PATH_PROCNET_TCP, "AF INET (tcp)", tcp_do_one);
     544#if ENABLE_FEATURE_IPV6
     545    if (inet6 && flags & NETSTAT_TCP)
     546        do_info(_PATH_PROCNET_TCP6, "AF INET6 (tcp)", tcp_do_one);
     547#endif
     548    if (inet && flags & NETSTAT_UDP)
     549        do_info(_PATH_PROCNET_UDP, "AF INET (udp)", udp_do_one);
     550#if ENABLE_FEATURE_IPV6
     551    if (inet6 && flags & NETSTAT_UDP)
     552        do_info(_PATH_PROCNET_UDP6, "AF INET6 (udp)", udp_do_one);
     553#endif
     554    if (inet && flags & NETSTAT_RAW)
     555        do_info(_PATH_PROCNET_RAW, "AF INET (raw)", raw_do_one);
     556#if ENABLE_FEATURE_IPV6
     557    if (inet6 && flags & NETSTAT_RAW)
     558        do_info(_PATH_PROCNET_RAW6, "AF INET6 (raw)", raw_do_one);
     559#endif
     560    if (flags & NETSTAT_UNIX) {
    647561        printf("Active UNIX domain sockets ");
    648         if ((flags&(NETSTAT_LISTENING|NETSTAT_CONNECTED))==(NETSTAT_LISTENING|NETSTAT_CONNECTED))
     562        if ((flags & (NETSTAT_LISTENING|NETSTAT_CONNECTED)) == (NETSTAT_LISTENING|NETSTAT_CONNECTED))
    649563            printf("(servers and established)");
    650         else {
    651             if (flags&NETSTAT_LISTENING)
    652                 printf("(only servers)");
    653             else
    654                 printf("(w/o servers)");
    655         }
    656 
     564        else if (flags & NETSTAT_LISTENING)
     565            printf("(only servers)");
     566        else
     567            printf("(w/o servers)");
    657568        printf("\nProto RefCnt Flags       Type       State         I-Node Path\n");
    658         do_info(_PATH_PROCNET_UNIX,"AF UNIX",unix_do_one);
     569        do_info(_PATH_PROCNET_UNIX, "AF UNIX", unix_do_one);
    659570    }
    660571    return 0;
Note: See TracChangeset for help on using the changeset viewer.