telnetd: getopt_ulflags'isation
[oweals/busybox.git] / networking / netstat.c
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  * 2002-04-20
9  * 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.
12  */
13
14 #include "busybox.h"
15 #include "inet_common.h"
16
17 #ifdef CONFIG_ROUTE
18 extern void displayroutes(int noresolve, int netstatfmt);
19 #endif
20
21 #define NETSTAT_CONNECTED       0x01
22 #define NETSTAT_LISTENING       0x02
23 #define NETSTAT_NUMERIC         0x04
24 #define NETSTAT_TCP                     0x10
25 #define NETSTAT_UDP                     0x20
26 #define NETSTAT_RAW                     0x40
27 #define NETSTAT_UNIX            0x80
28
29 static int flags = NETSTAT_CONNECTED |
30                         NETSTAT_TCP | NETSTAT_UDP | NETSTAT_RAW | NETSTAT_UNIX;
31
32 #define PROGNAME_WIDTHs PROGNAME_WIDTH1(PROGNAME_WIDTH)
33 #define PROGNAME_WIDTH1(s) PROGNAME_WIDTH2(s)
34 #define PROGNAME_WIDTH2(s) #s
35
36 #define PRG_HASH_SIZE 211
37
38 enum {
39     TCP_ESTABLISHED = 1,
40     TCP_SYN_SENT,
41     TCP_SYN_RECV,
42     TCP_FIN_WAIT1,
43     TCP_FIN_WAIT2,
44     TCP_TIME_WAIT,
45     TCP_CLOSE,
46     TCP_CLOSE_WAIT,
47     TCP_LAST_ACK,
48     TCP_LISTEN,
49     TCP_CLOSING                 /* now a valid state */
50 };
51
52 static const char * const tcp_state[] =
53 {
54     "",
55     "ESTABLISHED",
56     "SYN_SENT",
57     "SYN_RECV",
58     "FIN_WAIT1",
59     "FIN_WAIT2",
60     "TIME_WAIT",
61     "CLOSE",
62     "CLOSE_WAIT",
63     "LAST_ACK",
64     "LISTEN",
65     "CLOSING"
66 };
67
68 typedef enum {
69     SS_FREE = 0,                /* not allocated                */
70     SS_UNCONNECTED,             /* unconnected to any socket    */
71     SS_CONNECTING,              /* in process of connecting     */
72     SS_CONNECTED,               /* connected to socket          */
73     SS_DISCONNECTING            /* in process of disconnecting  */
74 } socket_state;
75
76 #define SO_ACCEPTCON    (1<<16) /* performed a listen           */
77 #define SO_WAITDATA     (1<<17) /* wait data to read            */
78 #define SO_NOSPACE      (1<<18) /* no space to write            */
79
80 static char *get_sname(int port, const char *proto, int num)
81 {
82         char *str=itoa(ntohs(port));
83         if (num) {
84         } else {
85                 struct servent *se=getservbyport(port,proto);
86                 if (se)
87                         str=se->s_name;
88         }
89         if (!port) {
90                 str="*";
91         }
92         return str;
93 }
94
95 static void snprint_ip_port(char *ip_port, int size, struct sockaddr *addr, int port, char *proto, int numeric)
96 {
97         char *port_name;
98
99 #ifdef CONFIG_FEATURE_IPV6
100         if (addr->sa_family == AF_INET6) {
101                 INET6_rresolve(ip_port, size, (struct sockaddr_in6 *)addr,
102                                            (numeric&NETSTAT_NUMERIC) ? 0x0fff : 0);
103         } else
104 #endif
105         {
106         INET_rresolve(ip_port, size, (struct sockaddr_in *)addr,
107                 0x4000 | ((numeric&NETSTAT_NUMERIC) ? 0x0fff : 0),
108                 0xffffffff);
109         }
110         port_name=get_sname(htons(port), proto, numeric);
111         if ((strlen(ip_port) + strlen(port_name)) > 22)
112                 ip_port[22 - strlen(port_name)] = '\0';
113         ip_port+=strlen(ip_port);
114         strcat(ip_port, ":");
115         strcat(ip_port, port_name);
116 }
117
118 static void tcp_do_one(int lnr, const char *line)
119 {
120         char local_addr[64], rem_addr[64];
121         const char *state_str;
122         char more[512];
123         int num, local_port, rem_port, d, state, timer_run, uid, timeout;
124 #ifdef CONFIG_FEATURE_IPV6
125         struct sockaddr_in6 localaddr, remaddr;
126         char addr6[INET6_ADDRSTRLEN];
127         struct in6_addr in6;
128 #else
129         struct sockaddr_in localaddr, remaddr;
130 #endif
131         unsigned long rxq, txq, time_len, retr, inode;
132
133         if (lnr == 0)
134                 return;
135
136         more[0] = '\0';
137         num = sscanf(line,
138                                  "%d: %64[0-9A-Fa-f]:%X %64[0-9A-Fa-f]:%X %X %lX:%lX %X:%lX %lX %d %d %ld %512s\n",
139                                  &d, local_addr, &local_port,
140                                  rem_addr, &rem_port, &state,
141                                  &txq, &rxq, &timer_run, &time_len, &retr, &uid, &timeout, &inode, more);
142
143         if (strlen(local_addr) > 8) {
144 #ifdef CONFIG_FEATURE_IPV6
145                 sscanf(local_addr, "%08X%08X%08X%08X",
146                            &in6.s6_addr32[0], &in6.s6_addr32[1],
147                            &in6.s6_addr32[2], &in6.s6_addr32[3]);
148                 inet_ntop(AF_INET6, &in6, addr6, sizeof(addr6));
149                 inet_pton(AF_INET6, addr6, (struct sockaddr *) &localaddr.sin6_addr);
150                 sscanf(rem_addr, "%08X%08X%08X%08X",
151                            &in6.s6_addr32[0], &in6.s6_addr32[1],
152                            &in6.s6_addr32[2], &in6.s6_addr32[3]);
153                 inet_ntop(AF_INET6, &in6, addr6, sizeof(addr6));
154                 inet_pton(AF_INET6, addr6, (struct sockaddr *) &remaddr.sin6_addr);
155                 localaddr.sin6_family = AF_INET6;
156                 remaddr.sin6_family = AF_INET6;
157 #endif
158         } else {
159                 sscanf(local_addr, "%X",
160                            &((struct sockaddr_in *) &localaddr)->sin_addr.s_addr);
161                 sscanf(rem_addr, "%X",
162                            &((struct sockaddr_in *) &remaddr)->sin_addr.s_addr);
163                 ((struct sockaddr *) &localaddr)->sa_family = AF_INET;
164                 ((struct sockaddr *) &remaddr)->sa_family = AF_INET;
165         }
166
167         if (num < 10) {
168                 bb_error_msg("warning, got bogus tcp line.");
169                 return;
170         }
171         state_str = tcp_state[state];
172         if ((rem_port && (flags&NETSTAT_CONNECTED)) ||
173                 (!rem_port && (flags&NETSTAT_LISTENING)))
174         {
175                 snprint_ip_port(local_addr, sizeof(local_addr),
176                                                 (struct sockaddr *) &localaddr, local_port,
177                                                 "tcp", flags&NETSTAT_NUMERIC);
178
179                 snprint_ip_port(rem_addr, sizeof(rem_addr),
180                                                 (struct sockaddr *) &remaddr, rem_port,
181                                                 "tcp", flags&NETSTAT_NUMERIC);
182
183                 printf("tcp   %6ld %6ld %-23s %-23s %-12s\n",
184                            rxq, txq, local_addr, rem_addr, state_str);
185
186         }
187 }
188
189 static void udp_do_one(int lnr, const char *line)
190 {
191         char local_addr[64], rem_addr[64];
192         char *state_str, more[512];
193         int num, local_port, rem_port, d, state, timer_run, uid, timeout;
194 #ifdef CONFIG_FEATURE_IPV6
195         struct sockaddr_in6 localaddr, remaddr;
196         char addr6[INET6_ADDRSTRLEN];
197         struct in6_addr in6;
198 #else
199         struct sockaddr_in localaddr, remaddr;
200 #endif
201         unsigned long rxq, txq, time_len, retr, inode;
202
203         if (lnr == 0)
204                 return;
205
206         more[0] = '\0';
207         num = sscanf(line,
208                                  "%d: %64[0-9A-Fa-f]:%X %64[0-9A-Fa-f]:%X %X %lX:%lX %X:%lX %lX %d %d %ld %512s\n",
209                                  &d, local_addr, &local_port,
210                                  rem_addr, &rem_port, &state,
211                                  &txq, &rxq, &timer_run, &time_len, &retr, &uid, &timeout, &inode, more);
212
213         if (strlen(local_addr) > 8) {
214 #ifdef CONFIG_FEATURE_IPV6
215         /* Demangle what the kernel gives us */
216                 sscanf(local_addr, "%08X%08X%08X%08X",
217                            &in6.s6_addr32[0], &in6.s6_addr32[1],
218                            &in6.s6_addr32[2], &in6.s6_addr32[3]);
219                 inet_ntop(AF_INET6, &in6, addr6, sizeof(addr6));
220                 inet_pton(AF_INET6, addr6, (struct sockaddr *) &localaddr.sin6_addr);
221                 sscanf(rem_addr, "%08X%08X%08X%08X",
222                            &in6.s6_addr32[0], &in6.s6_addr32[1],
223                            &in6.s6_addr32[2], &in6.s6_addr32[3]);
224                 inet_ntop(AF_INET6, &in6, addr6, sizeof(addr6));
225                 inet_pton(AF_INET6, addr6, (struct sockaddr *) &remaddr.sin6_addr);
226                 localaddr.sin6_family = AF_INET6;
227                 remaddr.sin6_family = AF_INET6;
228 #endif
229         } else {
230                 sscanf(local_addr, "%X",
231                            &((struct sockaddr_in *) &localaddr)->sin_addr.s_addr);
232                 sscanf(rem_addr, "%X",
233                            &((struct sockaddr_in *) &remaddr)->sin_addr.s_addr);
234                 ((struct sockaddr *) &localaddr)->sa_family = AF_INET;
235                 ((struct sockaddr *) &remaddr)->sa_family = AF_INET;
236         }
237
238         if (num < 10) {
239                 bb_error_msg("warning, got bogus udp line.");
240                 return;
241         }
242         switch (state) {
243                 case TCP_ESTABLISHED:
244                         state_str = "ESTABLISHED";
245                         break;
246
247                 case TCP_CLOSE:
248                         state_str = "";
249                         break;
250
251                 default:
252                         state_str = "UNKNOWN";
253                         break;
254         }
255
256 #ifdef CONFIG_FEATURE_IPV6
257 # define notnull(A) (((A.sin6_family == AF_INET6) &&            \
258                                          ((A.sin6_addr.s6_addr32[0]) ||            \
259                                           (A.sin6_addr.s6_addr32[1]) ||            \
260                                           (A.sin6_addr.s6_addr32[2]) ||            \
261                                           (A.sin6_addr.s6_addr32[3]))) ||          \
262                                         ((A.sin6_family == AF_INET) &&             \
263                                          ((struct sockaddr_in *) &A)->sin_addr.s_addr))
264 #else
265 # define notnull(A) (A.sin_addr.s_addr)
266 #endif
267         if ((notnull(remaddr) && (flags&NETSTAT_CONNECTED)) ||
268                 (!notnull(remaddr) && (flags&NETSTAT_LISTENING)))
269         {
270                 snprint_ip_port(local_addr, sizeof(local_addr),
271                                                 (struct sockaddr *) &localaddr, local_port,
272                                                 "udp", flags&NETSTAT_NUMERIC);
273
274                 snprint_ip_port(rem_addr, sizeof(rem_addr),
275                                                 (struct sockaddr *) &remaddr, rem_port,
276                                                 "udp", flags&NETSTAT_NUMERIC);
277
278                 printf("udp   %6ld %6ld %-23s %-23s %-12s\n",
279                            rxq, txq, local_addr, rem_addr, state_str);
280
281         }
282 }
283
284 static void raw_do_one(int lnr, const char *line)
285 {
286         char local_addr[64], rem_addr[64];
287         char *state_str, more[512];
288         int num, local_port, rem_port, d, state, timer_run, uid, timeout;
289 #ifdef CONFIG_FEATURE_IPV6
290         struct sockaddr_in6 localaddr, remaddr;
291         char addr6[INET6_ADDRSTRLEN];
292         struct in6_addr in6;
293 #else
294         struct sockaddr_in localaddr, remaddr;
295 #endif
296         unsigned long rxq, txq, time_len, retr, inode;
297
298         if (lnr == 0)
299                 return;
300
301         more[0] = '\0';
302         num = sscanf(line,
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);
307
308         if (strlen(local_addr) > 8) {
309 #ifdef CONFIG_FEATURE_IPV6
310                 sscanf(local_addr, "%08X%08X%08X%08X",
311                            &in6.s6_addr32[0], &in6.s6_addr32[1],
312                            &in6.s6_addr32[2], &in6.s6_addr32[3]);
313                 inet_ntop(AF_INET6, &in6, addr6, sizeof(addr6));
314                 inet_pton(AF_INET6, addr6, (struct sockaddr *) &localaddr.sin6_addr);
315                 sscanf(rem_addr, "%08X%08X%08X%08X",
316                            &in6.s6_addr32[0], &in6.s6_addr32[1],
317                            &in6.s6_addr32[2], &in6.s6_addr32[3]);
318                 inet_ntop(AF_INET6, &in6, addr6, sizeof(addr6));
319                 inet_pton(AF_INET6, addr6, (struct sockaddr *) &remaddr.sin6_addr);
320                 localaddr.sin6_family = AF_INET6;
321                 remaddr.sin6_family = AF_INET6;
322 #endif
323         } else {
324                 sscanf(local_addr, "%X",
325                            &((struct sockaddr_in *) &localaddr)->sin_addr.s_addr);
326                 sscanf(rem_addr, "%X",
327                            &((struct sockaddr_in *) &remaddr)->sin_addr.s_addr);
328                 ((struct sockaddr *) &localaddr)->sa_family = AF_INET;
329                 ((struct sockaddr *) &remaddr)->sa_family = AF_INET;
330         }
331
332         if (num < 10) {
333                 bb_error_msg("warning, got bogus raw line.");
334                 return;
335         }
336         state_str=itoa(state);
337
338 #ifdef CONFIG_FEATURE_IPV6
339 # define notnull(A) (((A.sin6_family == AF_INET6) &&            \
340                                          ((A.sin6_addr.s6_addr32[0]) ||            \
341                                           (A.sin6_addr.s6_addr32[1]) ||            \
342                                           (A.sin6_addr.s6_addr32[2]) ||            \
343                                           (A.sin6_addr.s6_addr32[3]))) ||          \
344                                         ((A.sin6_family == AF_INET) &&             \
345                                          ((struct sockaddr_in *) &A)->sin_addr.s_addr))
346 #else
347 # define notnull(A) (A.sin_addr.s_addr)
348 #endif
349         if ((notnull(remaddr) && (flags&NETSTAT_CONNECTED)) ||
350                 (!notnull(remaddr) && (flags&NETSTAT_LISTENING)))
351         {
352                 snprint_ip_port(local_addr, sizeof(local_addr),
353                                                 (struct sockaddr *) &localaddr, local_port,
354                                                 "raw", flags&NETSTAT_NUMERIC);
355
356                 snprint_ip_port(rem_addr, sizeof(rem_addr),
357                                                 (struct sockaddr *) &remaddr, rem_port,
358                                                 "raw", flags&NETSTAT_NUMERIC);
359
360                 printf("raw   %6ld %6ld %-23s %-23s %-12s\n",
361                            rxq, txq, local_addr, rem_addr, state_str);
362
363         }
364 }
365
366 #define HAS_INODE 1
367
368 static void unix_do_one(int nr, const char *line)
369 {
370         static int has = 0;
371         char path[PATH_MAX], ss_flags[32];
372         char *ss_proto, *ss_state, *ss_type;
373         int num, state, type, inode;
374         void *d;
375         unsigned long refcnt, proto, unix_flags;
376
377         if (nr == 0) {
378                 if (strstr(line, "Inode"))
379                         has |= HAS_INODE;
380                 return;
381         }
382         path[0] = '\0';
383         num = sscanf(line, "%p: %lX %lX %lX %X %X %d %s",
384                                  &d, &refcnt, &proto, &unix_flags, &type, &state, &inode, path);
385         if (num < 6) {
386                 bb_error_msg("warning, got bogus unix line.");
387                 return;
388         }
389         if (!(has & HAS_INODE))
390                 snprintf(path,sizeof(path),"%d",inode);
391
392         if ((flags&(NETSTAT_LISTENING|NETSTAT_CONNECTED))!=(NETSTAT_LISTENING|NETSTAT_CONNECTED)) {
393                 if ((state == SS_UNCONNECTED) && (unix_flags & SO_ACCEPTCON)) {
394                         if (!(flags&NETSTAT_LISTENING))
395                                 return;
396                 } else {
397                         if (!(flags&NETSTAT_CONNECTED))
398                                 return;
399                 }
400         }
401
402         switch (proto) {
403                 case 0:
404                         ss_proto = "unix";
405                         break;
406
407                 default:
408                         ss_proto = "??";
409         }
410
411         switch (type) {
412                 case SOCK_STREAM:
413                         ss_type = "STREAM";
414                         break;
415
416                 case SOCK_DGRAM:
417                         ss_type = "DGRAM";
418                         break;
419
420                 case SOCK_RAW:
421                         ss_type = "RAW";
422                         break;
423
424                 case SOCK_RDM:
425                         ss_type = "RDM";
426                         break;
427
428                 case SOCK_SEQPACKET:
429                         ss_type = "SEQPACKET";
430                         break;
431
432                 default:
433                         ss_type = "UNKNOWN";
434         }
435
436         switch (state) {
437                 case SS_FREE:
438                         ss_state = "FREE";
439                         break;
440
441                 case SS_UNCONNECTED:
442                         /*
443                          * Unconnected sockets may be listening
444                          * for something.
445                          */
446                         if (unix_flags & SO_ACCEPTCON) {
447                                 ss_state = "LISTENING";
448                         } else {
449                                 ss_state = "";
450                         }
451                         break;
452
453                 case SS_CONNECTING:
454                         ss_state = "CONNECTING";
455                         break;
456
457                 case SS_CONNECTED:
458                         ss_state = "CONNECTED";
459                         break;
460
461                 case SS_DISCONNECTING:
462                         ss_state = "DISCONNECTING";
463                         break;
464
465                 default:
466                         ss_state = "UNKNOWN";
467         }
468
469         strcpy(ss_flags, "[ ");
470         if (unix_flags & SO_ACCEPTCON)
471                 strcat(ss_flags, "ACC ");
472         if (unix_flags & SO_WAITDATA)
473                 strcat(ss_flags, "W ");
474         if (unix_flags & SO_NOSPACE)
475                 strcat(ss_flags, "N ");
476
477         strcat(ss_flags, "]");
478
479         printf("%-5s %-6ld %-11s %-10s %-13s ",
480                    ss_proto, refcnt, ss_flags, ss_type, ss_state);
481         if (has & HAS_INODE)
482                 printf("%-6d ",inode);
483         else
484                 printf("-      ");
485         puts(path);
486 }
487
488 #define _PATH_PROCNET_UDP "/proc/net/udp"
489 #define _PATH_PROCNET_UDP6 "/proc/net/udp6"
490 #define _PATH_PROCNET_TCP "/proc/net/tcp"
491 #define _PATH_PROCNET_TCP6 "/proc/net/tcp6"
492 #define _PATH_PROCNET_RAW "/proc/net/raw"
493 #define _PATH_PROCNET_RAW6 "/proc/net/raw6"
494 #define _PATH_PROCNET_UNIX "/proc/net/unix"
495
496 static void do_info(const char *file, const char *name, void (*proc)(int, const char *))
497 {
498         char buffer[8192];
499         int lnr = 0;
500         FILE *procinfo;
501
502         procinfo = fopen(file, "r");
503         if (procinfo == NULL) {
504                 if (errno != ENOENT) {
505                         perror(file);
506                 } else {
507                 bb_error_msg("no support for `%s' on this system.", name);
508                 }
509         } else {
510                 do {
511                         if (fgets(buffer, sizeof(buffer), procinfo))
512                                 (proc)(lnr++, buffer);
513                 } while (!feof(procinfo));
514                 fclose(procinfo);
515         }
516 }
517
518 /*
519  * Our main function.
520  */
521
522 int netstat_main(int argc, char **argv)
523 {
524         int opt;
525         int new_flags=0;
526         int showroute = 0, extended = 0;
527 #ifdef CONFIG_FEATURE_IPV6
528         int inet=1;
529         int inet6=1;
530 #else
531 # define inet 1
532 # define inet6 0
533 #endif
534         while ((opt = getopt(argc, argv, "laenrtuwx")) != -1)
535                 switch (opt) {
536                 case 'l':
537                         flags &= ~NETSTAT_CONNECTED;
538                         flags |= NETSTAT_LISTENING;
539                         break;
540                 case 'a':
541                         flags |= NETSTAT_LISTENING | NETSTAT_CONNECTED;
542                         break;
543                 case 'n':
544                         flags |= NETSTAT_NUMERIC;
545                         break;
546                 case 'r':
547                         showroute = 1;
548                         break;
549                 case 'e':
550                         extended = 1;
551                         break;
552                 case 't':
553                         new_flags |= NETSTAT_TCP;
554                         break;
555                 case 'u':
556                         new_flags |= NETSTAT_UDP;
557                         break;
558                 case 'w':
559                         new_flags |= NETSTAT_RAW;
560                         break;
561                 case 'x':
562                         new_flags |= NETSTAT_UNIX;
563                         break;
564                 default:
565                         bb_show_usage();
566                 }
567         if ( showroute ) {
568 #ifdef CONFIG_ROUTE
569                 displayroutes ( flags & NETSTAT_NUMERIC, !extended );
570                 return 0;
571 #else
572                 bb_error_msg_and_die( "-r (display routing table) is not compiled in." );
573 #endif
574         }
575
576         if (new_flags) {
577                 flags &= ~(NETSTAT_TCP|NETSTAT_UDP|NETSTAT_RAW|NETSTAT_UNIX);
578                 flags |= new_flags;
579         }
580         if (flags&(NETSTAT_TCP|NETSTAT_UDP|NETSTAT_RAW)) {
581                 printf("Active Internet connections "); /* xxx */
582
583                 if ((flags&(NETSTAT_LISTENING|NETSTAT_CONNECTED))==(NETSTAT_LISTENING|NETSTAT_CONNECTED))
584                         printf("(servers and established)");
585                 else {
586                         if (flags&NETSTAT_LISTENING)
587                                 printf("(only servers)");
588                         else
589                                 printf("(w/o servers)");
590                 }
591                 printf("\nProto Recv-Q Send-Q Local Address           Foreign Address         State      \n");
592         }
593         if (inet && flags&NETSTAT_TCP)
594                 do_info(_PATH_PROCNET_TCP,"AF INET (tcp)",tcp_do_one);
595 #ifdef CONFIG_FEATURE_IPV6
596         if (inet6 && flags&NETSTAT_TCP)
597                 do_info(_PATH_PROCNET_TCP6,"AF INET6 (tcp)",tcp_do_one);
598 #endif
599         if (inet && flags&NETSTAT_UDP)
600                 do_info(_PATH_PROCNET_UDP,"AF INET (udp)",udp_do_one);
601 #ifdef CONFIG_FEATURE_IPV6
602         if (inet6 && flags&NETSTAT_UDP)
603                 do_info(_PATH_PROCNET_UDP6,"AF INET6 (udp)",udp_do_one);
604 #endif
605         if (inet && flags&NETSTAT_RAW)
606                 do_info(_PATH_PROCNET_RAW,"AF INET (raw)",raw_do_one);
607 #ifdef CONFIG_FEATURE_IPV6
608         if (inet6 && flags&NETSTAT_RAW)
609                 do_info(_PATH_PROCNET_RAW6,"AF INET6 (raw)",raw_do_one);
610 #endif
611         if (flags&NETSTAT_UNIX) {
612                 printf("Active UNIX domain sockets ");
613                 if ((flags&(NETSTAT_LISTENING|NETSTAT_CONNECTED))==(NETSTAT_LISTENING|NETSTAT_CONNECTED))
614                         printf("(servers and established)");
615                 else {
616                         if (flags&NETSTAT_LISTENING)
617                                 printf("(only servers)");
618                         else
619                                 printf("(w/o servers)");
620                 }
621
622                 printf("\nProto RefCnt Flags       Type       State         I-Node Path\n");
623                 do_info(_PATH_PROCNET_UNIX,"AF UNIX",unix_do_one);
624         }
625         return 0;
626 }