source: trunk/mindi-busybox/networking/netstat.c @ 904

Last change on this file since 904 was 821, checked in by bruno, 13 years ago

Addition of busybox 1.2.1 as a mindi-busybox new package
This should avoid delivering binary files in mindi not built there (Fedora and Debian are quite serious about that)

File size: 17.0 KB
Line 
1/* vi: set sw=4 ts=4: */
2/*
3 * Mini netstat implementation(s) for busybox
4 * based in part on the netstat implementation from net-tools.
5 *
6 * Copyright (C) 2002 by Bart Visscher <magick@linux-fan.com>
7 *
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 *
22 * 2002-04-20
23 * IPV6 support added by Bart Visscher <magick@linux-fan.com>
24 */
25
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>
35#include "inet_common.h"
36#include "busybox.h"
37#include "pwd_.h"
38
39#ifdef CONFIG_ROUTE
40extern 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
51static 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
59
60enum {
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 */
72};
73
74static 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"
88};
89
90typedef 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  */
96} socket_state;
97
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
102static 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
115static char *get_sname(int port, const char *proto, int num)
116{
117    char *str=itoa(ntohs(port));
118    if (num) {
119    } 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
130static 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
153static void tcp_do_one(int lnr, const char *line)
154{
155    char local_addr[64], rem_addr[64];
156    const char *state_str;
157    char more[512];
158    int num, local_port, rem_port, d, state, timer_run, uid, timeout;
159#ifdef CONFIG_FEATURE_IPV6
160    struct sockaddr_in6 localaddr, remaddr;
161    char addr6[INET6_ADDRSTRLEN];
162    struct in6_addr in6;
163#else
164    struct sockaddr_in localaddr, remaddr;
165#endif
166    unsigned long rxq, txq, time_len, retr, inode;
167
168    if (lnr == 0)
169        return;
170
171    more[0] = '\0';
172    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);
177
178    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;
192#endif
193    } 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;
200    }
201
202    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
224static 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.");
275        return;
276    }
277    switch (state) {
278        case TCP_ESTABLISHED:
279            state_str = "ESTABLISHED";
280            break;
281
282        case TCP_CLOSE:
283            state_str = "";
284            break;
285
286        default:
287            state_str = "UNKNOWN";
288            break;
289    }
290
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))
299#else
300# define notnull(A) (A.sin_addr.s_addr)
301#endif
302    if ((notnull(remaddr) && (flags&NETSTAT_CONNECTED)) ||
303        (!notnull(remaddr) && (flags&NETSTAT_LISTENING)))
304    {
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
316    }
317}
318
319static void raw_do_one(int lnr, const char *line)
320{
321    char local_addr[64], rem_addr[64];
322    char *state_str, more[512];
323    int num, local_port, rem_port, d, state, timer_run, uid, timeout;
324#ifdef CONFIG_FEATURE_IPV6
325    struct sockaddr_in6 localaddr, remaddr;
326    char addr6[INET6_ADDRSTRLEN];
327    struct in6_addr in6;
328#else
329    struct sockaddr_in localaddr, remaddr;
330#endif
331    unsigned long rxq, txq, time_len, retr, inode;
332
333    if (lnr == 0)
334        return;
335
336    more[0] = '\0';
337    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);
342
343    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;
357#endif
358    } 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;
365    }
366
367    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)))
386    {
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
402
403static void unix_do_one(int nr, const char *line)
404{
405    static int has = 0;
406    char path[PATH_MAX], ss_flags[32];
407    char *ss_proto, *ss_state, *ss_type;
408    int num, state, type, inode;
409    void *d;
410    unsigned long refcnt, proto, unix_flags;
411
412    if (nr == 0) {
413        if (strstr(line, "Inode"))
414            has |= HAS_INODE;
415        return;
416    }
417    path[0] = '\0';
418    num = sscanf(line, "%p: %lX %lX %lX %X %X %d %s",
419                 &d, &refcnt, &proto, &unix_flags, &type, &state, &inode, path);
420    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)) {
428        if ((state == SS_UNCONNECTED) && (unix_flags & SO_ACCEPTCON)) {
429            if (!(flags&NETSTAT_LISTENING))
430                return;
431        } else {
432            if (!(flags&NETSTAT_CONNECTED))
433                return;
434        }
435    }
436
437    switch (proto) {
438        case 0:
439            ss_proto = "unix";
440            break;
441
442        default:
443            ss_proto = "??";
444    }
445
446    switch (type) {
447        case SOCK_STREAM:
448            ss_type = "STREAM";
449            break;
450
451        case SOCK_DGRAM:
452            ss_type = "DGRAM";
453            break;
454
455        case SOCK_RAW:
456            ss_type = "RAW";
457            break;
458
459        case SOCK_RDM:
460            ss_type = "RDM";
461            break;
462
463        case SOCK_SEQPACKET:
464            ss_type = "SEQPACKET";
465            break;
466
467        default:
468            ss_type = "UNKNOWN";
469    }
470
471    switch (state) {
472        case SS_FREE:
473            ss_state = "FREE";
474            break;
475
476        case SS_UNCONNECTED:
477            /*
478             * Unconnected sockets may be listening
479             * for something.
480             */
481            if (unix_flags & SO_ACCEPTCON) {
482                ss_state = "LISTENING";
483            } else {
484                ss_state = "";
485            }
486            break;
487
488        case SS_CONNECTING:
489            ss_state = "CONNECTING";
490            break;
491
492        case SS_CONNECTED:
493            ss_state = "CONNECTED";
494            break;
495
496        case SS_DISCONNECTING:
497            ss_state = "DISCONNECTING";
498            break;
499
500        default:
501            ss_state = "UNKNOWN";
502    }
503
504    strcpy(ss_flags, "[ ");
505    if (unix_flags & SO_ACCEPTCON)
506        strcat(ss_flags, "ACC ");
507    if (unix_flags & SO_WAITDATA)
508        strcat(ss_flags, "W ");
509    if (unix_flags & SO_NOSPACE)
510        strcat(ss_flags, "N ");
511
512    strcat(ss_flags, "]");
513
514    printf("%-5s %-6ld %-11s %-10s %-13s ",
515           ss_proto, refcnt, ss_flags, ss_type, ss_state);
516    if (has & HAS_INODE)
517        printf("%-6d ",inode);
518    else
519        printf("-      ");
520    puts(path);
521}
522
523#define _PATH_PROCNET_UDP "/proc/net/udp"
524#define _PATH_PROCNET_UDP6 "/proc/net/udp6"
525#define _PATH_PROCNET_TCP "/proc/net/tcp"
526#define _PATH_PROCNET_TCP6 "/proc/net/tcp6"
527#define _PATH_PROCNET_RAW "/proc/net/raw"
528#define _PATH_PROCNET_RAW6 "/proc/net/raw6"
529#define _PATH_PROCNET_UNIX "/proc/net/unix"
530
531static void do_info(const char *file, const char *name, void (*proc)(int, const char *))
532{
533    char buffer[8192];
534    int lnr = 0;
535    FILE *procinfo;
536
537    procinfo = fopen(file, "r");
538    if (procinfo == NULL) {
539        if (errno != ENOENT) {
540            perror(file);
541        } else {
542        bb_error_msg("no support for `%s' on this system.", name);
543        }
544    } else {
545        do {
546            if (fgets(buffer, sizeof(buffer), procinfo))
547                (proc)(lnr++, buffer);
548        } while (!feof(procinfo));
549        fclose(procinfo);
550    }
551}
552
553/*
554 * Our main function.
555 */
556
557int netstat_main(int argc, char **argv)
558{
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 );
605        return 0;
606#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)) {
616        printf("Active Internet connections "); /* xxx */
617
618        if ((flags&(NETSTAT_LISTENING|NETSTAT_CONNECTED))==(NETSTAT_LISTENING|NETSTAT_CONNECTED))
619            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) {
647        printf("Active UNIX domain sockets ");
648        if ((flags&(NETSTAT_LISTENING|NETSTAT_CONNECTED))==(NETSTAT_LISTENING|NETSTAT_CONNECTED))
649            printf("(servers and established)");
650        else {
651            if (flags&NETSTAT_LISTENING)
652                printf("(only servers)");
653            else
654                printf("(w/o servers)");
655        }
656
657        printf("\nProto RefCnt Flags       Type       State         I-Node Path\n");
658        do_info(_PATH_PROCNET_UNIX,"AF UNIX",unix_do_one);
659    }
660    return 0;
661}
Note: See TracBrowser for help on using the repository browser.