Imported Upstream version 4.88
[platform/upstream/lsof.git] / dialects / linux / dsock.c
1 /*
2  * dsock.c - Linux socket processing functions for /proc-based lsof
3  */
4
5
6 /*
7  * Copyright 1997 Purdue Research Foundation, West Lafayette, Indiana
8  * 47907.  All rights reserved.
9  *
10  * Written by Victor A. Abell
11  *
12  * This software is not subject to any license of the American Telephone
13  * and Telegraph Company or the Regents of the University of California.
14  *
15  * Permission is granted to anyone to use this software for any purpose on
16  * any computer system, and to alter it and redistribute it freely, subject
17  * to the following restrictions:
18  *
19  * 1. Neither the authors nor Purdue University are responsible for any
20  *    consequences of the use of this software.
21  *
22  * 2. The origin of this software must not be misrepresented, either by
23  *    explicit claim or by omission.  Credit to the authors and Purdue
24  *    University must appear in documentation and sources.
25  *
26  * 3. Altered versions must be plainly marked as such, and must not be
27  *    misrepresented as being the original software.
28  *
29  * 4. This notice may not be removed or altered.
30  */
31
32 #ifndef lint
33 static char copyright[] =
34 "@(#) Copyright 1997 Purdue Research Foundation.\nAll rights reserved.\n";
35 static char *rcsid = "$Id: dsock.c,v 1.40 2014/10/13 22:25:58 abe Exp $";
36 #endif
37
38
39 #include "lsof.h"
40 #include <sys/xattr.h>
41
42
43 /*
44  * Local definitions
45  */
46
47 #define INOBUCKS        128             /* inode hash bucket count -- must be
48                                          * a power of two */
49 #define INOHASH(ino)    ((int)((ino * 31415) >> 3) & (INOBUCKS - 1))
50 #define TCPUDPHASH(ino) ((int)((ino * 31415) >> 3) & (TcpUdp_bucks - 1))
51 #define TCPUDP6HASH(ino) ((int)((ino * 31415) >> 3) & (TcpUdp6_bucks - 1))
52
53
54 /*
55  * Local structures
56  */
57
58 struct ax25sin {                        /* AX25 socket information */
59         char *da;                       /* destination address */
60         char *dev_ch;                   /* device characters */
61         char *sa;                       /* source address */
62         INODETYPE inode;
63         unsigned long sq, rq;           /* send and receive queue values */
64         unsigned char sqs, rqs;         /* send and receive queue states */
65         int state;
66         struct ax25sin *next;
67 };
68
69 struct icmpin {
70         INODETYPE inode;                /* node number */
71         char *la;                       /* local address */
72         char *ra;                       /* remote address */
73         MALLOC_S lal;                   /* strlen(la) */
74         MALLOC_S ral;                   /* strlen(ra) */
75         struct icmpin *next;
76 };
77
78 struct ipxsin {                         /* IPX socket information */
79         INODETYPE inode;
80         char *la;                       /* local address */
81         char *ra;                       /* remote address */
82         int state;
83         unsigned long txq, rxq;         /* transmit and receive queue values */
84         struct ipxsin *next;
85 };
86
87 struct nlksin {                         /* Netlink socket information */
88         INODETYPE inode;                /* node number */
89         unsigned int pr;                /* protocol */
90         struct nlksin *next;
91 };
92
93 struct packin {                         /* packet information */
94         INODETYPE inode;
95         int ty;                         /* socket type */
96         int pr;                         /* protocol */
97         struct packin *next;
98 };
99
100 struct rawsin {                         /* raw socket information */
101         INODETYPE inode;
102         char *la;                       /* local address */
103         char *ra;                       /* remote address */
104         char *sp;                       /* state characters */
105         MALLOC_S lal;                   /* strlen(la) */
106         MALLOC_S ral;                   /* strlen(ra) */
107         MALLOC_S spl;                   /* strlen(sp) */
108         struct rawsin *next;
109 };
110
111 struct sctpsin {                        /* SCTP socket information */
112         INODETYPE inode;
113         int type;                       /* type: 0 = assoc
114                                          *       1 = eps
115                                          *       2  assoc and eps */
116         char *addr;                     /* association or endpoint address */
117         char *assocID;                  /* association ID */
118         char *lport;                    /* local port */
119         char *rport;                    /* remote port */
120         char *laddrs;                   /* local address */
121         char *raddrs;                   /* remote address */
122         struct sctpsin *next;
123 };
124
125 struct tcp_udp {                        /* IPv4 TCP and UDP socket
126                                          * information */
127         INODETYPE inode;
128         unsigned long faddr, laddr;     /* foreign & local IPv6 addresses */
129         int fport, lport;               /* foreign & local ports */
130         unsigned long txq, rxq;         /* transmit & receive queue values */
131         int proto;                      /* 0 = TCP, 1 = UDP, 2 = UDPLITE */
132         int state;                      /* protocol state */
133         struct tcp_udp *next;
134 };
135
136 #if     defined(HASIPv6)
137 struct tcp_udp6 {                       /* IPv6 TCP and UDP socket
138                                          * information */
139         INODETYPE inode;
140         struct in6_addr faddr, laddr;   /* foreign and local IPv6 addresses */
141         int fport, lport;               /* foreign & local ports */
142         unsigned long txq, rxq;         /* transmit & receive queue values */
143         int proto;                      /* 0 = TCP, 1 = UDP, 2 = UDPLITE */
144         int state;                      /* protocol state */
145         struct tcp_udp6 *next;
146 };
147 #endif  /* defined(HASIPv6) */
148
149 struct uxsin {                          /* UNIX socket information */
150         INODETYPE inode;                /* node number */
151         char *pcb;                      /* protocol control block */
152         char *path;                     /* file path */
153         unsigned char sb_def;           /* stat(2) buffer definitions */
154         dev_t sb_dev;                   /* stat(2) buffer device */
155         INODETYPE sb_ino;               /* stat(2) buffer node number */
156         dev_t sb_rdev;                  /* stat(2) raw device number */
157         uint32_t ty;                    /* socket type */
158         struct uxsin *next;
159 };
160
161
162 /*
163  * Local static values
164  */
165
166 static char *AX25path = (char *)NULL;   /* path to AX25 /proc information */
167 static struct ax25sin **AX25sin = (struct ax25sin **)NULL;
168                                         /* AX25 socket info, hashed by inode */
169 static char *ax25st[] = {
170         "LISTENING",                    /* 0 */
171         "SABM SENT",                    /* 1 */
172         "DISC SENT",                    /* 2 */
173         "ESTABLISHED",                  /* 3 */
174         "RECOVERY"                      /* 4 */
175 };
176 #define NAX25ST (sizeof(ax25st) / sizeof(char *))
177 static char *ICMPpath = (char *)NULL;   /* path to ICMP /proc information */
178 static struct icmpin **Icmpin = (struct icmpin **)NULL;
179                                         /* ICMP socket info, hashed by inode */
180 static char *Ipxpath = (char *)NULL;    /* path to IPX /proc information */
181 static struct ipxsin **Ipxsin = (struct ipxsin **)NULL;
182                                         /* IPX socket info, hashed by inode */
183 static char *Nlkpath = (char *)NULL;    /* path to Netlink /proc information */
184 static struct nlksin **Nlksin = (struct nlksin **)NULL;
185                                         /* Netlink socket info, hashed by
186                                          * inode */
187 static struct packin **Packin = (struct packin **)NULL;
188                                         /* packet info, hashed by inode */
189 static char *Packpath = (char *)NULL;   /* path to packet /proc information */
190 static char *Rawpath = (char *)NULL;    /* path to raw socket /proc
191                                          * information */
192 static struct rawsin **Rawsin = (struct rawsin **)NULL;
193                                         /* raw socket info, hashed by inode */
194 static char *SCTPPath[] = {             /* paths to /proc/net STCP info */
195         (char *)NULL,                   /* 0 = /proc/net/sctp/assocs */
196         (char *)NULL                    /* 1 = /proc/net/sctp/eps */
197 };
198 #define NSCTPPATHS sizeof(SCTPPath)/sizeof(char *)
199 static char *SCTPSfx[] = {              /* /proc/net suffixes */
200         "sctp/assocs",                  /* 0 = /proc/net/sctp/assocs */
201         "sctp/eps"                      /* 1 = /proc/net/sctp/eps */
202 };
203 static struct sctpsin **SCTPsin = (struct sctpsin **)NULL;
204                                         /* SCTP info, hashed by inode */
205 static char *SockStatPath = (char *)NULL;
206                                         /* path to /proc/net socket status */
207 static char *TCPpath = (char *)NULL;    /* path to TCP /proc information */
208 static struct tcp_udp **TcpUdp = (struct tcp_udp **)NULL;
209                                         /* IPv4 TCP & UDP info, hashed by
210                                          * inode */
211 static int TcpUdp_bucks = 0;            /* dynamically sized hash bucket
212                                          * count for TCP and UDP -- will
213                                          * be a power of two */
214
215 #if     defined(HASIPv6)
216 static char *Raw6path = (char *)NULL;   /* path to raw IPv6 /proc information */
217 static struct rawsin **Rawsin6 = (struct rawsin **)NULL;
218                                         /* IPv6 raw socket info, hashed by
219                                          * inode */
220 static char *SockStatPath6 = (char *)NULL;
221                                         /* path to /proc/net IPv6 socket
222                                          * status */
223 static char *TCP6path = (char *)NULL;   /* path to IPv6 TCP /proc information */
224 static struct tcp_udp6 **TcpUdp6 = (struct tcp_udp6 **)NULL;
225                                         /* IPv6 TCP & UDP info, hashed by
226                                          * inode */
227 static int TcpUdp6_bucks = 0;           /* dynamically sized hash bucket
228                                          * count for IPv6 TCP and UDP -- will
229                                          * be a power of two */
230 static char *UDP6path = (char *)NULL;   /* path to IPv6 UDP /proc information */
231 static char *UDPLITE6path = (char *)NULL;
232                                         /* path to IPv6 UDPLITE /proc
233                                          * information */
234 #endif  /* defined(HASIPv6) */
235
236 static char *UDPpath = (char *)NULL;    /* path to UDP /proc information */
237 static char *UDPLITEpath = (char *)NULL;
238                                         /* path to UDPLITE /proc information */
239 static char *UNIXpath = (char *)NULL;   /* path to UNIX /proc information */
240 static struct uxsin **Uxsin = (struct uxsin **)NULL;
241                                         /* UNIX socket info, hashed by inode */
242
243
244 /*
245  * Local function prototypes
246  */
247
248 _PROTOTYPE(static struct ax25sin *check_ax25,(INODETYPE i));
249 _PROTOTYPE(static struct icmpin *check_icmp,(INODETYPE i));
250 _PROTOTYPE(static struct ipxsin *check_ipx,(INODETYPE i));
251 _PROTOTYPE(static struct nlksin *check_netlink,(INODETYPE i));
252 _PROTOTYPE(static struct packin *check_pack,(INODETYPE i));
253 _PROTOTYPE(static struct rawsin *check_raw,(INODETYPE i));
254 _PROTOTYPE(static struct sctpsin *check_sctp,(INODETYPE i));
255 _PROTOTYPE(static struct tcp_udp *check_tcpudp,(INODETYPE i, char **p));
256 _PROTOTYPE(static struct uxsin *check_unix,(INODETYPE i));
257 _PROTOTYPE(static void get_ax25,(char *p));
258 _PROTOTYPE(static void get_icmp,(char *p));
259 _PROTOTYPE(static void get_ipx,(char *p));
260 _PROTOTYPE(static void get_netlink,(char *p));
261 _PROTOTYPE(static void get_pack,(char *p));
262 _PROTOTYPE(static void get_raw,(char *p));
263 _PROTOTYPE(static void get_sctp,(void));
264 _PROTOTYPE(static char *get_sctpaddrs,(char **fp, int i, int nf, int *x));
265 _PROTOTYPE(static void get_tcpudp,(char *p, int pr, int clr));
266 _PROTOTYPE(static void get_unix,(char *p));
267 _PROTOTYPE(static int isainb,(char *a, char *b));
268 _PROTOTYPE(static void print_ax25info,(struct ax25sin *ap));
269 _PROTOTYPE(static void print_ipxinfo,(struct ipxsin *ip));
270 _PROTOTYPE(static char *sockty2str,(uint32_t ty, int *rf));
271
272 #if     defined(HASIPv6)
273 _PROTOTYPE(static struct rawsin *check_raw6,(INODETYPE i));
274 _PROTOTYPE(static struct tcp_udp6 *check_tcpudp6,(INODETYPE i, char **p));
275 _PROTOTYPE(static void get_raw6,(char *p));
276 _PROTOTYPE(static void get_tcpudp6,(char *p, int pr, int clr));
277 _PROTOTYPE(static int net6a2in6,(char *as, struct in6_addr *ad));
278 #endif  /* defined(HASIPv6) */
279
280
281 /*
282  * build_IPstates() -- build the TCP and UDP state tables
283  */
284
285 void
286 build_IPstates()
287 {
288         if (!TcpSt) {
289             (void) enter_IPstate("TCP", "ESTABLISHED", TCP_ESTABLISHED);
290             (void) enter_IPstate("TCP", "SYN_SENT", TCP_SYN_SENT);
291             (void) enter_IPstate("TCP", "SYN_RECV", TCP_SYN_RECV);
292             (void) enter_IPstate("TCP", "FIN_WAIT1", TCP_FIN_WAIT1);
293             (void) enter_IPstate("TCP", "FIN_WAIT2", TCP_FIN_WAIT2);
294             (void) enter_IPstate("TCP", "TIME_WAIT", TCP_TIME_WAIT);
295             (void) enter_IPstate("TCP", "CLOSE", TCP_CLOSE);
296             (void) enter_IPstate("TCP", "CLOSE_WAIT", TCP_CLOSE_WAIT);
297             (void) enter_IPstate("TCP", "LAST_ACK", TCP_LAST_ACK);
298             (void) enter_IPstate("TCP", "LISTEN", TCP_LISTEN);
299             (void) enter_IPstate("TCP", "CLOSING", TCP_CLOSING);
300             (void) enter_IPstate("TCP", "CLOSED", 0);
301             (void) enter_IPstate("TCP", (char *)NULL, 0);
302         }
303 }
304
305
306 /*
307  * check_ax25() - check for AX25 socket file
308  */
309
310 static struct ax25sin *
311 check_ax25(i)
312         INODETYPE i;                    /* socket file's inode number */
313 {
314         struct ax25sin *ap;
315         int h;
316
317         h = INOHASH(i);
318         for (ap = AX25sin[h]; ap; ap = ap->next) {
319             if (i == ap->inode)
320                 return(ap);
321         }
322         return((struct ax25sin *)NULL);
323 }
324
325
326
327 /*
328  * check_icmp() - check for ICMP socket
329  */
330
331 static struct icmpin *
332 check_icmp(i)
333         INODETYPE i;                    /* socket file's inode number */
334 {
335         int h;
336         struct icmpin *icmpp;
337
338         h = INOHASH(i);
339         for (icmpp = Icmpin[h]; icmpp; icmpp = icmpp->next) {
340             if (i == icmpp->inode)
341                 return(icmpp);
342         }
343         return((struct icmpin *)NULL);
344 }
345
346
347 /*
348  * check_ipx() - check for IPX socket file
349  */
350
351 static struct ipxsin *
352 check_ipx(i)
353         INODETYPE i;                    /* socket file's inode number */
354 {
355         int h;
356         struct ipxsin *ip;
357
358         h = INOHASH(i);
359         for (ip = Ipxsin[h]; ip; ip = ip->next) {
360             if (i == ip->inode)
361                 return(ip);
362         }
363         return((struct ipxsin *)NULL);
364 }
365
366
367 /*
368  * check_netlink() - check for Netlink socket file
369  */
370
371 static struct nlksin *
372 check_netlink(i)
373         INODETYPE i;                    /* socket file's inode number */
374 {
375         int h;
376         struct nlksin *lp;
377
378         h = INOHASH(i);
379         for (lp = Nlksin[h]; lp; lp = lp->next) {
380             if (i == lp->inode)
381                 return(lp);
382         }
383         return((struct nlksin *)NULL);
384 }
385
386
387 /*
388  * check_pack() - check for packet file
389  */
390
391 static struct packin *
392 check_pack(i)
393         INODETYPE i;                    /* packet file's inode number */
394 {
395         int h;
396         struct packin *pp;
397
398         h = INOHASH(i);
399         for (pp = Packin[h]; pp; pp = pp->next) {
400             if (i == pp->inode)
401                 return(pp);
402         }
403         return((struct packin *)NULL);
404 }
405
406
407 /*
408  * check_raw() - check for raw socket file
409  */
410
411 static struct rawsin *
412 check_raw(i)
413         INODETYPE i;                    /* socket file's inode number */
414 {
415         int h;
416         struct rawsin *rp;
417
418         h = INOHASH(i);
419         for (rp = Rawsin[h]; rp; rp = rp->next) {
420             if (i == rp->inode)
421                 return(rp);
422         }
423         return((struct rawsin *)NULL);
424 }
425
426
427 /*
428  * check_sctp() - check for SCTP socket file
429  */
430
431 static struct sctpsin *
432 check_sctp(i)
433         INODETYPE i;                    /* socket file's inode number */
434 {
435         int h;
436         struct sctpsin *sp;
437
438         h = INOHASH(i);
439         for (sp = SCTPsin[h]; sp; sp = sp->next) {
440             if (i == sp->inode)
441                 return(sp);
442         }
443         return((struct sctpsin *)NULL);
444 }
445
446
447 /*
448  * check_tcpudp() - check for IPv4 TCP or UDP socket file
449  */
450
451 static struct tcp_udp *
452 check_tcpudp(i, p)
453         INODETYPE i;                    /* socket file's inode number */
454         char **p;                       /* protocol return */
455 {
456         int h;
457         struct tcp_udp *tp;
458
459         h = TCPUDPHASH(i);
460         for (tp = TcpUdp[h]; tp; tp = tp->next) {
461             if (i == tp->inode) {
462                 switch (tp->proto) {
463                 case 0:
464                     *p = "TCP";
465                     break;
466                 case 1:
467                     *p = "UDP";
468                     break;
469                 case 2:
470                     *p = "UDPLITE";
471                     break;
472                 default:
473                    *p = "unknown";
474                 }
475                 return(tp);
476             }
477         }
478         return((struct tcp_udp *)NULL);
479 }
480
481
482 #if     defined(HASIPv6)
483 /*
484  * check_raw6() - check for raw IPv6 socket file
485  */
486
487 static struct rawsin *
488 check_raw6(i)
489         INODETYPE i;                    /* socket file's inode number */
490 {
491         int h;
492         struct rawsin *rp;
493
494         h = INOHASH(i);
495         for (rp = Rawsin6[h]; rp; rp = rp->next) {
496             if (i == rp->inode)
497                 return(rp);
498         }
499         return((struct rawsin *)NULL);
500 }
501
502
503 /*
504  * check_tcpudp6() - check for IPv6 TCP or UDP socket file
505  */
506
507 static struct tcp_udp6 *
508 check_tcpudp6(i, p)
509         INODETYPE i;                    /* socket file's inode number */
510         char **p;                       /* protocol return */
511 {
512         int h;
513         struct tcp_udp6 *tp6;
514
515         h = TCPUDP6HASH(i);
516         for (tp6 = TcpUdp6[h]; tp6; tp6 = tp6->next) {
517             if (i == tp6->inode) {
518                 switch (tp6->proto) {
519                 case 0:
520                     *p = "TCP";
521                     break;
522                 case 1:
523                     *p = "UDP";
524                     break;
525                 case 2:
526                     *p = "UDPLITE";
527                     break;
528                 default:
529                    *p = "unknown";
530                 }
531                 return(tp6);
532             }
533         }
534         return((struct tcp_udp6 *)NULL);
535 }
536 #endif  /* defined(HASIPv6) */
537
538
539 /*
540  * check_unix() - check for UNIX domain socket
541  */
542
543 static struct uxsin *
544 check_unix(i)
545         INODETYPE i;                    /* socket file's inode number */
546 {
547         int h;
548         struct uxsin *up;
549
550         h = INOHASH(i);
551         for (up = Uxsin[h]; up; up = up->next) {
552             if (i == up->inode)
553                 return(up);
554         }
555         return((struct uxsin *)NULL);
556 }
557
558
559 /*
560  * get_ax25() - get /proc/net/ax25 info
561  */
562
563 static void
564 get_ax25(p)
565         char *p;                        /* /proc/net/ipx path */
566 {
567         struct ax25sin *ap, *np;
568         FILE *as;
569         char buf[MAXPATHLEN], *da, *dev_ch, *ep, **fp, *sa;
570         int h, nf;
571         INODETYPE inode;
572         unsigned long rq, sq, state;
573         MALLOC_S len;
574         unsigned char rqs, sqs;
575         static char *vbuf = (char *)NULL;
576         static size_t vsz = (size_t)0;
577 /*
578  * Do second time cleanup or first time setup.
579  */
580         if (AX25sin) {
581             for (h = 0; h < INOBUCKS; h++) {
582                 for (ap = AX25sin[h]; ap; ap = np) {
583                     np = ap->next;
584                     if (ap->da)
585                         (void) free((FREE_P *)ap->da);
586                     if (ap->dev_ch)
587                         (void) free((FREE_P *)ap->dev_ch);
588                     if (ap->sa)
589                         (void) free((FREE_P *)ap->sa);
590                     (void) free((FREE_P *)ap);
591                 }
592                 AX25sin[h] = (struct ax25sin *)NULL;
593             }
594         } else {
595             AX25sin = (struct ax25sin **)calloc(INOBUCKS,
596                                               sizeof(struct ax25sin *));
597             if (!AX25sin) {
598                 (void) fprintf(stderr,
599                     "%s: can't allocate %d AX25 hash pointer bytes\n",
600                     Pn, (int)(INOBUCKS * sizeof(struct ax25sin *)));
601                 Exit(1);
602             }
603         }
604 /*
605  * Open the /proc/net/ax25 file, assign a page size buffer to the stream,
606  * and read it.  Store AX25 socket info in the AX25sin[] hash buckets.
607  */
608         if (!(as = open_proc_stream(p, "r", &vbuf, &vsz, 0)))
609             return;
610         while (fgets(buf, sizeof(buf) - 1, as)) {
611             if ((nf = get_fields(buf, (char *)NULL, &fp, (int *)NULL, 0)) < 24)
612                 continue;
613         /*
614          * /proc/net/ax25 has no title line, a very poor deficiency in its
615          * implementation.
616          *
617          * The ax25_get_info() function in kern module .../net/ax25/af_ax25.c
618          * says the format of the lines in the file is:
619          *
620          *     magic dev src_addr dest_addr,digi1,digi2,.. st vs vr va t1 t1 \
621          *     t2  t2 t3 t3 idle idle n2 n2 rtt window paclen Snd-Q Rcv-Q \
622          *     inode
623          *
624          * The code in this function is forced to assume that format is in
625          * effect..
626          */
627
628         /*
629          * Assemble the inode number and see if it has already been recorded.
630          * If it has, skip this line.
631          */
632             ep = (char *)NULL;
633             if (!fp[23] || !*fp[23]
634             ||  (inode = strtoull(fp[23], &ep, 0)) == ULONG_MAX
635             ||  !ep || *ep)
636                 continue;
637             h = INOHASH((INODETYPE)inode);
638             for (ap = AX25sin[h]; ap; ap = ap->next) {
639                 if (inode == ap->inode)
640                     break;
641             }
642             if (ap)
643                 continue;
644         /*
645          * Assemble the send and receive queue values and the state.
646          */
647             rq = sq = (unsigned long)0;
648             rqs = sqs = (unsigned char)0;
649             ep = (char *)NULL;
650             if (!fp[21] || !*fp[21]
651             ||  (sq = strtoul(fp[21], &ep, 0)) == ULONG_MAX || !ep || *ep)
652                 continue;
653             sqs = (unsigned char)1;
654             ep = (char *)NULL;
655             if (!fp[22] || !*fp[22]
656             ||  (rq = strtoul(fp[22], &ep, 0)) == ULONG_MAX || !ep || *ep)
657                 continue;
658             rqs = (unsigned char)1;
659             ep = (char *)NULL;
660             if (!fp[4] || !*fp[4]
661             ||  (state = strtoul(fp[4], &ep, 0)) == ULONG_MAX || !ep || *ep)
662                 continue;
663         /*
664          * Allocate space for the destination address.
665          */
666             if (!fp[3] || !*fp[3])
667                 da = (char *)NULL;
668             else if ((len = strlen(fp[3]))) {
669                 if (!(da = (char *)malloc(len + 1))) {
670                     (void) fprintf(stderr,
671                       "%s: can't allocate %d destination AX25 addr bytes: %s\n",
672                       Pn, (int)(len + 1), fp[3]);
673                     Exit(1);
674                 }
675                 (void) snpf(da, len + 1, "%s", fp[3]);
676             } else
677                 da = (char *)NULL;
678         /*
679          * Allocate space for the source address.
680          */
681             if (!fp[2] || !*fp[2])
682                 sa = (char *)NULL;
683             else if ((len = strlen(fp[2]))) {
684                 if (!(sa = (char *)malloc(len + 1))) {
685                     (void) fprintf(stderr,
686                         "%s: can't allocate %d source AX25 address bytes: %s\n",
687                         Pn, (int)(len + 1), fp[2]);
688                     Exit(1);
689                 }
690                 (void) snpf(sa, len + 1, "%s", fp[2]);
691             } else
692                 sa = (char *)NULL;
693         /*
694          * Allocate space for the device characters.
695          */
696             if (!fp[1] || !*fp[1])
697                 dev_ch = (char *)NULL;
698             else if ((len = strlen(fp[1]))) {
699                 if (!(dev_ch = (char *)malloc(len + 1))) {
700                     (void) fprintf(stderr,
701                       "%s: can't allocate %d destination AX25 dev bytes: %s\n",
702                       Pn, (int)(len + 1), fp[1]);
703                     Exit(1);
704                 }
705                 (void) snpf(dev_ch, len + 1, "%s", fp[1]);
706             } else
707                 dev_ch = (char *)NULL;
708         /*
709          * Allocate space for an ax25sin entry, fill it, and link it to its
710          * hash bucket.
711          */
712             if (!(ap = (struct ax25sin *)malloc(sizeof(struct ax25sin)))) {
713                 (void) fprintf(stderr,
714                     "%s: can't allocate %d byte ax25sin structure\n",
715                     Pn, (int)sizeof(struct ax25sin));
716                 Exit(1);
717             }
718             ap->da = da;
719             ap->dev_ch = dev_ch;
720             ap->inode = inode;
721             ap->rq = rq;
722             ap->rqs = rqs;
723             ap->sa = sa;
724             ap->sq = sq;
725             ap->sqs = sqs;
726             ap->state = (int)state;
727             ap->next = AX25sin[h];
728             AX25sin[h] = ap;
729         }
730         (void) fclose(as);
731 }
732  
733  
734 /*
735  * get_icmp() - get ICMP net info
736  */
737
738 static void
739 get_icmp(p)
740         char *p;                        /* /proc/net/icmp path */
741 {
742         char buf[MAXPATHLEN], *ep, **fp, *la, *ra;
743         int fl = 1;
744         int h;
745         INODETYPE inode;
746         struct icmpin *np, *icmpp;
747         unsigned long pr;
748         MALLOC_S lal, ral, spl;
749         static char *vbuf = (char *)NULL;
750         static size_t vsz = (size_t)0;
751         FILE *xs;
752 /*
753  * Do second time cleanup or first time setup.
754  */
755         if (Icmpin) {
756             for (h = 0; h < INOBUCKS; h++) {
757                 for (icmpp = Icmpin[h]; icmpp; icmpp = np) {
758                     np = icmpp->next;
759                     (void) free((FREE_P *)icmpp);
760                 }
761                 Icmpin[h] = (struct icmpin *)NULL;
762             }
763         } else {
764             Icmpin = (struct icmpin **)calloc(INOBUCKS,
765                                               sizeof(struct icmpin *));
766             if (!Icmpin) {
767                 (void) fprintf(stderr,
768                     "%s: can't allocate %d icmp hash pointer bytes\n",
769                     Pn, (int)(INOBUCKS * sizeof(struct icmpin *)));
770                 Exit(1);
771             }
772         }
773 /*
774  * Open the /proc/net/icmp file, assign a page size buffer to its stream,
775  * and read the file.  Store icmp info in the Icmpin[] hash buckets.
776  */
777         if (!(xs = open_proc_stream(p, "r", &vbuf, &vsz, 0)))
778             return;
779         while (fgets(buf, sizeof(buf) - 1, xs)) {
780             if (get_fields(buf, (char *)NULL, &fp, (int *)NULL, 0) < 11)
781                 continue;
782             if (fl) {
783
784             /*
785              * Check the column labels in the first line.
786              *
787              * NOTE:
788              *       In column header, "inode" is at the 11th column.
789              *       However, in data rows, inode appears at the 9th column.
790              *
791              *       In column header, "tx_queue" and "rx_queue" are separated
792              *       by a space.  It is the same for "tr" and "tm->when"; in
793              *       data rows they are connected with ":".
794              */
795                 if (!fp[1]  || strcmp(fp[1], "local_address")
796                 ||  !fp[2]  || strcmp(fp[2], "rem_address")
797                 ||  !fp[11] || strcmp(fp[11], "inode"))
798                 {
799                     if (!Fwarn) {
800                         (void) fprintf(stderr,
801                             "%s: WARNING: unsupported format: %s\n",
802                             Pn, p);
803                     }
804                     break;
805                 }
806                 fl = 0;
807                 continue;
808             }
809         /*
810          * Assemble the inode number and see if the inode is already
811          * recorded.
812          */
813             ep = (char *)NULL;
814             if (!fp[9] || !*fp[9]
815             ||  (inode = strtoull(fp[9], &ep, 0)) == ULONG_MAX
816             ||  !ep || *ep)
817                 continue;
818             h = INOHASH(inode);
819             for (icmpp = Icmpin[h]; icmpp; icmpp = icmpp->next) {
820                 if (inode == icmpp->inode)
821                     break;
822             }
823             if (icmpp)
824                 continue;
825         /*
826          * Save the local address, and remote address.
827          */
828             if (!fp[1] || !*fp[1] || (lal = strlen(fp[1])) < 1) {
829                 la = (char *)NULL;
830                 lal = (MALLOC_S)0;
831             } else {
832                 if (!(la = (char *)malloc(lal + 1))) {
833                     (void) fprintf(stderr,
834                         "%s: can't allocate %d local icmp address bytes: %s\n",
835                         Pn, (int)(lal + 1), fp[1]);
836                     Exit(1);
837                 }
838                 (void) snpf(la, lal + 1, "%s", fp[1]);
839             }
840             if (!fp[2] || !*fp[2] || (ral = strlen(fp[2])) < 1) {
841                 ra = (char *)NULL;
842                 ral = (MALLOC_S)0;
843             } else {
844                 if (!(ra = (char *)malloc(ral + 1))) {
845                     (void) fprintf(stderr,
846                         "%s: can't allocate %d remote icmp address bytes: %s\n",
847                         Pn, (int)(ral + 1), fp[2]);
848                     Exit(1);
849                 }
850                 (void) snpf(ra, ral + 1, "%s", fp[2]);
851             }
852         /*
853          * Allocate space for a icmpin entry, fill it, and link it to its
854          * hash bucket.
855          */
856             if (!(icmpp = (struct icmpin *)malloc(sizeof(struct icmpin)))) {
857                 (void) fprintf(stderr,
858                     "%s: can't allocate %d byte icmp structure\n",
859                     Pn, (int)sizeof(struct icmpin));
860                 Exit(1);
861             }
862             icmpp->inode = inode;
863             icmpp->la = la;
864             icmpp->lal = lal;
865             icmpp->ra = ra;
866             icmpp->ral = ral;
867             icmpp->next = Icmpin[h];
868             Icmpin[h] = icmpp;
869         }
870         (void) fclose(xs);
871 }
872
873
874
875 /*
876  * get_ipx() - get /proc/net/ipx info
877  */
878
879 static void
880 get_ipx(p)
881         char *p;                        /* /proc/net/ipx path */
882 {
883         char buf[MAXPATHLEN], *ep, **fp, *la, *ra;
884         int fl = 1;
885         int h;
886         INODETYPE inode;
887         unsigned long rxq, state, txq;
888         struct ipxsin *ip, *np;
889         MALLOC_S len;
890         static char *vbuf = (char *)NULL;
891         static size_t vsz = (size_t)0;
892         FILE *xs;
893 /*
894  * Do second time cleanup or first time setup.
895  */
896         if (Ipxsin) {
897             for (h = 0; h < INOBUCKS; h++) {
898                 for (ip = Ipxsin[h]; ip; ip = np) {
899                     np = ip->next;
900                     if (ip->la)
901                         (void) free((FREE_P *)ip->la);
902                     if (ip->ra)
903                         (void) free((FREE_P *)ip->ra);
904                     (void) free((FREE_P *)ip);
905                 }
906                 Ipxsin[h] = (struct ipxsin *)NULL;
907             }
908         } else {
909             Ipxsin = (struct ipxsin **)calloc(INOBUCKS,
910                                               sizeof(struct ipxsin *));
911             if (!Ipxsin) {
912                 (void) fprintf(stderr,
913                     "%s: can't allocate %d IPX hash pointer bytes\n",
914                     Pn, (int)(INOBUCKS * sizeof(struct ipxsin *)));
915                 Exit(1);
916             }
917         }
918 /*
919  * Open the /proc/net/ipx file, assign a page size buffer to the stream,
920  * and read it.  Store IPX socket info in the Ipxsin[] hash buckets.
921  */
922         if (!(xs = open_proc_stream(p, "r", &vbuf, &vsz, 0)))
923             return;
924         while (fgets(buf, sizeof(buf) - 1, xs)) {
925             if (get_fields(buf, (char *)NULL, &fp, (int *)NULL, 0) < 7)
926                 continue;
927             if (fl) {
928
929             /*
930              * Check the column labels in the first line.
931              */
932                 if (!fp[0] || strcmp(fp[0], "Local_Address")
933                 ||  !fp[1] || strcmp(fp[1], "Remote_Address")
934                 ||  !fp[2] || strcmp(fp[2], "Tx_Queue")
935                 ||  !fp[3] || strcmp(fp[3], "Rx_Queue")
936                 ||  !fp[4] || strcmp(fp[4], "State")
937                 ||  !fp[5] || strcmp(fp[5], "Uid")
938                 ||  !fp[6] || strcmp(fp[6], "Inode"))
939                 {
940                     if (!Fwarn) {
941                         (void) fprintf(stderr,
942                             "%s: WARNING: unsupported format: %s\n",
943                             Pn, p);
944                     }
945                     break;
946                 }
947                 fl = 0;
948                 continue;
949             }
950         /*
951          * Assemble the inode number and see if the inode is already
952          * recorded.
953          */
954             ep = (char *)NULL;
955             if (!fp[6] || !*fp[6]
956             ||  (inode = strtoull(fp[6], &ep, 0)) == ULONG_MAX
957             ||  !ep || *ep)
958                 continue;
959             h = INOHASH(inode);
960             for (ip = Ipxsin[h]; ip; ip = ip->next) {
961                 if (inode == ip->inode)
962                     break;
963             }
964             if (ip)
965                 continue;
966         /*
967          * Assemble the transmit and receive queue values and the state.
968          */
969             ep = (char *)NULL;
970             if (!fp[2] || !*fp[2]
971             ||  (txq = strtoul(fp[2], &ep, 16)) == ULONG_MAX || !ep || *ep)
972                 continue;
973             ep = (char *)NULL;
974             if (!fp[3] || !*fp[3]
975             ||  (rxq = strtoul(fp[3], &ep, 16)) == ULONG_MAX || !ep || *ep)
976                 continue;
977             ep = (char *)NULL;
978             if (!fp[4] || !*fp[4]
979             ||  (state = strtoul(fp[4], &ep, 16)) == ULONG_MAX || !ep || *ep)
980                 continue;
981         /*
982          * Allocate space for the local address, unless it is "Not_Connected".
983          */
984             if (!fp[0] || !*fp[0] || strcmp(fp[0], "Not_Connected") == 0)
985                 la = (char *)NULL;
986             else if ((len = strlen(fp[0]))) {
987                 if (!(la = (char *)malloc(len + 1))) {
988                     (void) fprintf(stderr,
989                         "%s: can't allocate %d local IPX address bytes: %s\n",
990                         Pn, (int)(len + 1), fp[0]);
991                     Exit(1);
992                 }
993                 (void) snpf(la, len + 1, "%s", fp[0]);
994             } else
995                 la = (char *)NULL;
996         /*
997          * Allocate space for the remote address, unless it is "Not_Connected".
998          */
999             if (!fp[1] || !*fp[1] || strcmp(fp[1], "Not_Connected") == 0)
1000                 ra = (char *)NULL;
1001             else if ((len = strlen(fp[1]))) {
1002                 if (!(ra = (char *)malloc(len + 1))) {
1003                     (void) fprintf(stderr,
1004                         "%s: can't allocate %d remote IPX address bytes: %s\n",
1005                         Pn, (int)(len + 1), fp[1]);
1006                     Exit(1);
1007                 }
1008                 (void) snpf(ra, len + 1, "%s", fp[1]);
1009             } else
1010                 ra = (char *)NULL;
1011         /*
1012          * Allocate space for an ipxsin entry, fill it, and link it to its
1013          * hash bucket.
1014          */
1015             if (!(ip = (struct ipxsin *)malloc(sizeof(struct ipxsin)))) {
1016                 (void) fprintf(stderr,
1017                     "%s: can't allocate %d byte ipxsin structure\n",
1018                     Pn, (int)sizeof(struct ipxsin));
1019                 Exit(1);
1020             }
1021             ip->inode = inode;
1022             ip->la = la;
1023             ip->ra = ra;
1024             ip->txq = txq;
1025             ip->rxq = rxq;
1026             ip->state = (int)state;
1027             ip->next = Ipxsin[h];
1028             Ipxsin[h] = ip;
1029         }
1030         (void) fclose(xs);
1031 }
1032
1033  
1034 /*
1035  * get_netlink() - get /proc/net/netlink info
1036  */
1037
1038 static void
1039 get_netlink(p)
1040         char *p;                        /* /proc/net/netlink path */
1041 {
1042         char buf[MAXPATHLEN], *ep, **fp;
1043         int fr = 1;
1044         int h, pr;
1045         INODETYPE inode;
1046         struct nlksin *np, *lp;
1047         static char *vbuf = (char *)NULL;
1048         static size_t vsz = (size_t)0;  
1049         FILE *xs;
1050 /*
1051  * Do second time cleanup or first time setup.
1052  */
1053         if (Nlksin) {
1054             for (h = 0; h < INOBUCKS; h++) {
1055                 for (lp = Nlksin[h]; lp; lp = np) {
1056                     np = lp->next;
1057                     (void) free((FREE_P *)lp);
1058                 }
1059                 Nlksin[h] = (struct nlksin *)NULL;
1060             }
1061         } else {
1062             Nlksin = (struct nlksin **)calloc(INOBUCKS,sizeof(struct nlksin *));
1063             if (!Nlksin) {
1064                 (void) fprintf(stderr,
1065                     "%s: can't allocate %d netlink hash pointer bytes\n",
1066                     Pn, (int)(INOBUCKS * sizeof(struct nlksin *)));
1067                 Exit(1);
1068             }
1069         }
1070 /*
1071  * Open the /proc/net/netlink file, assign a page size buffer to its stream,
1072  * and read the file.  Store Netlink info in the Nlksin[] hash buckets.
1073  */
1074         if (!(xs = open_proc_stream(p, "r", &vbuf, &vsz, 0)))
1075             return;
1076         while (fgets(buf, sizeof(buf) - 1, xs)) {
1077             if (get_fields(buf, (char *)NULL, &fp, (int *)NULL, 0) < 10)
1078                 continue;
1079             if (fr) {
1080
1081             /*
1082              * Check the column labels in the first line.
1083              */
1084                 if (!fp[1] || strcmp(fp[1], "Eth")
1085                 ||  !fp[9] || strcmp(fp[9], "Inode"))
1086                 {
1087                     if (!Fwarn) {
1088                         (void) fprintf(stderr,
1089                             "%s: WARNING: unsupported format: %s\n",
1090                             Pn, p);
1091                     }
1092                     break;
1093                 }
1094                 fr = 0;
1095                 continue;
1096             }
1097         /*
1098          * Assemble the inode number and see if the inode is already
1099          * recorded.
1100          */
1101             ep = (char *)NULL;
1102             if (!fp[9] || !*fp[9]
1103             ||  (inode = strtoull(fp[9], &ep, 0)) == ULONG_MAX
1104             ||  !ep || *ep)
1105                 continue;
1106             h = INOHASH(inode);
1107             for (lp = Nlksin[h]; lp; lp = lp->next) {
1108                 if (inode == lp->inode)
1109                     break;
1110             }
1111             if (lp)
1112                 continue;
1113         /*
1114          * Save the protocol from the Eth column.
1115          */
1116             if (!fp[1] || !*fp[1] || (strlen(fp[1])) < 1)
1117                 continue;
1118             pr = atoi(fp[1]);
1119         /*
1120          * Allocate space for a nlksin entry, fill it, and link it to its
1121          * hash bucket.
1122          */
1123             if (!(lp = (struct nlksin *)malloc(sizeof(struct nlksin)))) {
1124                 (void) fprintf(stderr,
1125                     "%s: can't allocate %d byte Netlink structure\n",
1126                     Pn, (int)sizeof(struct nlksin));
1127                 Exit(1);
1128             }
1129             lp->inode = inode;
1130             lp->pr = pr;
1131             lp->next = Nlksin[h];
1132             Nlksin[h] = lp;
1133         }
1134         (void) fclose(xs);
1135 }
1136
1137
1138 /*
1139  * get_pack() - get /proc/net/packet info
1140  */
1141
1142 static void
1143 get_pack(p)
1144         char *p;                        /* /proc/net/raw path */
1145 {
1146         char buf[MAXPATHLEN], *ep, **fp;
1147         int fl = 1;
1148         int h, ty;
1149         INODETYPE inode;
1150         struct packin *np, *pp;
1151         unsigned long pr;
1152         static char *vbuf = (char *)NULL;
1153         static size_t vsz = (size_t)0;
1154         FILE *xs;
1155 /*
1156  * Do second time cleanup or first time setup.
1157  */
1158         if (Packin) {
1159             for (h = 0; h < INOBUCKS; h++) {
1160                 for (pp = Packin[h]; pp; pp = np) {
1161                     np = pp->next;
1162                     (void) free((FREE_P *)pp);
1163                 }
1164                 Packin[h] = (struct packin *)NULL;
1165             }
1166         } else {
1167             Packin = (struct packin **)calloc(INOBUCKS,
1168                                               sizeof(struct packin *));
1169             if (!Packin) {
1170                 (void) fprintf(stderr,
1171                     "%s: can't allocate %d packet hash pointer bytes\n",
1172                     Pn, (int)(INOBUCKS * sizeof(struct packin *)));
1173                 Exit(1);
1174             }
1175         }
1176 /*
1177  * Open the /proc/net/packet file, assign a page size buffer to its stream,
1178  * and read the file.  Store packet info in the Packin[] hash buckets.
1179  */
1180         if (!(xs = open_proc_stream(p, "r", &vbuf, &vsz, 0)))
1181             return;
1182         while (fgets(buf, sizeof(buf) - 1, xs)) {
1183             if (get_fields(buf, (char *)NULL, &fp, (int *)NULL, 0) < 9)
1184                 continue;
1185             if (fl) {
1186
1187             /*
1188              * Check the column labels in the first line.
1189              */
1190                 if (!fp[2]  || strcmp(fp[2], "Type")
1191                 ||  !fp[3]  || strcmp(fp[3], "Proto")
1192                 ||  !fp[8] || strcmp(fp[8], "Inode"))
1193                 {
1194                     if (!Fwarn) {
1195                         (void) fprintf(stderr,
1196                             "%s: WARNING: unsupported format: %s\n",
1197                             Pn, p);
1198                     }
1199                     break;
1200                 }
1201                 fl = 0;
1202                 continue;
1203             }
1204         /*
1205          * Assemble the inode number and see if the inode is already
1206          * recorded.
1207          */
1208             ep = (char *)NULL;
1209             if (!fp[8] || !*fp[8]
1210             ||  (inode = strtoull(fp[8], &ep, 0)) == ULONG_MAX
1211             ||  !ep || *ep)
1212                 continue;
1213             h = INOHASH(inode);
1214             for (pp = Packin[h]; pp; pp = pp->next) {
1215                 if (inode == pp->inode)
1216                     break;
1217             }
1218             if (pp)
1219                 continue;
1220         /*
1221          * Save the socket type and protocol.
1222          */
1223             if (!fp[2] || !*fp[2] || (strlen(fp[2])) < 1)
1224                 continue;
1225             ty = atoi(fp[2]);
1226             ep = (char *)NULL;
1227             if (!fp[3] || !*fp[3] || (strlen(fp[3]) < 1)
1228             ||  ((pr = strtoul(fp[3], &ep, 16)) == ULONG_MAX) || !ep || *ep)
1229                 continue;
1230         /*
1231          * Allocate space for a packin entry, fill it, and link it to its
1232          * hash bucket.
1233          */
1234             if (!(pp = (struct packin *)malloc(sizeof(struct packin)))) {
1235                 (void) fprintf(stderr,
1236                     "%s: can't allocate %d byte packet structure\n",
1237                     Pn, (int)sizeof(struct packin));
1238                 Exit(1);
1239             }
1240             pp->inode = inode;
1241             pp->pr = (int)pr;
1242             pp->ty = ty;
1243             pp->next = Packin[h];
1244             Packin[h] = pp;
1245         }
1246         (void) fclose(xs);
1247 }
1248
1249
1250 /*
1251  * get_raw() - get /proc/net/raw info
1252  */
1253
1254 static void
1255 get_raw(p)
1256         char *p;                        /* /proc/net/raw path */
1257 {
1258         char buf[MAXPATHLEN], *ep, **fp, *la, *ra, *sp;
1259         int h;
1260         INODETYPE inode;
1261         int nf = 12;
1262         struct rawsin *np, *rp;
1263         MALLOC_S lal, ral, spl;
1264         static char *vbuf = (char *)NULL;
1265         static size_t vsz = (size_t)0;
1266         FILE *xs;
1267 /*
1268  * Do second time cleanup or first time setup.
1269  */
1270         if (Rawsin) {
1271             for (h = 0; h < INOBUCKS; h++) {
1272                 for (rp = Rawsin[h]; rp; rp = np) {
1273                     np = rp->next;
1274                     if (rp->la)
1275                         (void) free((FREE_P *)rp->la);
1276                     if (rp->ra)
1277                         (void) free((FREE_P *)rp->ra);
1278                     (void) free((FREE_P *)rp);
1279                 }
1280                 Rawsin[h] = (struct rawsin *)NULL;
1281             }
1282         } else {
1283             Rawsin = (struct rawsin **)calloc(INOBUCKS,
1284                                               sizeof(struct rawsin *));
1285             if (!Rawsin) {
1286                 (void) fprintf(stderr,
1287                     "%s: can't allocate %d raw hash pointer bytes\n",
1288                     Pn, (int)(INOBUCKS * sizeof(struct rawsin *)));
1289                 Exit(1);
1290             }
1291         }
1292 /*
1293  * Open the /proc/net/raw file, assign a page size buffer to its stream,
1294  * and read the file.  Store raw socket info in the Rawsin[] hash buckets.
1295  */
1296         if (!(xs = open_proc_stream(p, "r", &vbuf, &vsz, 0)))
1297             return;
1298         while (fgets(buf, sizeof(buf) - 1, xs)) {
1299             if (get_fields(buf, (char *)NULL, &fp, (int *)NULL, 0) < nf)
1300                 continue;
1301             if (nf == 12) {
1302
1303             /*
1304              * Check the column labels in the first line.
1305              */
1306                 if (!fp[1]  || strcmp(fp[1],  "local_address")
1307                 ||  !fp[2]  || strcmp(fp[2],  "rem_address")
1308                 ||  !fp[3]  || strcmp(fp[3],  "st")
1309                 ||  !fp[11] || strcmp(fp[11], "inode"))
1310                 {
1311                     if (!Fwarn) {
1312                         (void) fprintf(stderr,
1313                             "%s: WARNING: unsupported format: %s\n",
1314                             Pn, p);
1315                     }
1316                     break;
1317                 }
1318                 nf = 10;
1319                 continue;
1320             }
1321         /*
1322          * Assemble the inode number and see if the inode is already
1323          * recorded.
1324          */
1325             ep = (char *)NULL;
1326             if (!fp[9] || !*fp[9]
1327             ||  (inode = strtoull(fp[9], &ep, 0)) == ULONG_MAX
1328             ||  !ep || *ep)
1329                 continue;
1330             h = INOHASH(inode);
1331             for (rp = Rawsin[h]; rp; rp = rp->next) {
1332                 if (inode == rp->inode)
1333                     break;
1334             }
1335             if (rp)
1336                 continue;
1337         /*
1338          * Save the local address, remote address, and state.
1339          */
1340             if (!fp[1] || !*fp[1] || (lal = strlen(fp[1])) < 1) {
1341                 la = (char *)NULL;
1342                 lal = (MALLOC_S)0;
1343             } else {
1344                 if (!(la = (char *)malloc(lal + 1))) {
1345                     (void) fprintf(stderr,
1346                         "%s: can't allocate %d local raw address bytes: %s\n",
1347                         Pn, (int)(lal + 1), fp[1]);
1348                     Exit(1);
1349                 }
1350                 (void) snpf(la, lal + 1, "%s", fp[1]);
1351             }
1352             if (!fp[2] || !*fp[2] || (ral = strlen(fp[2])) < 1) {
1353                 ra = (char *)NULL;
1354                 ral = (MALLOC_S)0;
1355             } else {
1356                 if (!(ra = (char *)malloc(ral + 1))) {
1357                     (void) fprintf(stderr,
1358                         "%s: can't allocate %d remote raw address bytes: %s\n",
1359                         Pn, (int)(ral + 1), fp[2]);
1360                     Exit(1);
1361                 }
1362                 (void) snpf(ra, ral + 1, "%s", fp[2]);
1363             }
1364             if (!fp[3] || !*fp[3] || (spl = strlen(fp[3])) < 1) {
1365                 sp = (char *)NULL;
1366                 spl = (MALLOC_S)0;
1367             } else {
1368                 if (!(sp = (char *)malloc(spl + 1))) {
1369                     (void) fprintf(stderr,
1370                         "%s: can't allocate %d remote raw state bytes: %s\n",
1371                         Pn, (int)(spl + 1), fp[2]);
1372                     Exit(1);
1373                 }
1374                 (void) snpf(sp, spl + 1, "%s", fp[3]);
1375             }
1376         /*
1377          * Allocate space for an rawsin entry, fill it, and link it to its
1378          * hash bucket.
1379          */
1380             if (!(rp = (struct rawsin *)malloc(sizeof(struct rawsin)))) {
1381                 (void) fprintf(stderr,
1382                     "%s: can't allocate %d byte rawsin structure\n",
1383                     Pn, (int)sizeof(struct rawsin));
1384                 Exit(1);
1385             }
1386             rp->inode = inode;
1387             rp->la = la;
1388             rp->lal = lal;
1389             rp->ra = ra;
1390             rp->ral = ral;
1391             rp->sp = sp;
1392             rp->spl = spl;
1393             rp->next = Rawsin[h];
1394             Rawsin[h] = rp;
1395         }
1396         (void) fclose(xs);
1397 }
1398
1399
1400 /*
1401  * get_sctp() - get /proc/net/sctp/assocs info
1402  */
1403
1404 static void
1405 get_sctp()
1406 {
1407         char buf[MAXPATHLEN], *a, *ep, **fp, *id, *la, *lp, *ra, *rp, *ta;
1408         int d, err, fl, h, i, j, nf, ty, x;
1409         INODETYPE inode;
1410         MALLOC_S len, plen;
1411         struct sctpsin *sp, *np;
1412         FILE *ss;
1413         static char *vbuf = (char *)NULL;
1414         static size_t vsz = (size_t)0;
1415 /*
1416  * Do second time cleanup or first time setup.
1417  */
1418         if (SCTPsin) {
1419             for (h = 0; h < INOBUCKS; h++) {
1420                 for (sp = SCTPsin[h]; sp; sp = np) {
1421                     np = sp->next;
1422                     if (sp->addr)
1423                         (void) free((FREE_P *)sp->addr);
1424                     if (sp->assocID)
1425                         (void) free((FREE_P *)sp->assocID);
1426                     if (sp->lport)
1427                         (void) free((FREE_P *)sp->lport);
1428                     if (sp->rport)
1429                         (void) free((FREE_P *)sp->rport);
1430                     if (sp->laddrs)
1431                         (void) free((FREE_P *)sp->laddrs);
1432                     if (sp->raddrs)
1433                         (void) free((FREE_P *)sp->raddrs);
1434                     (void) free((FREE_P *)sp);
1435                 }
1436                 SCTPsin[h] = (struct sctpsin *)NULL;
1437             }
1438         } else {
1439             SCTPsin = (struct sctpsin **)calloc(INOBUCKS,
1440                                               sizeof(struct sctpsin *));
1441             if (!SCTPsin) {
1442                 (void) fprintf(stderr,
1443                     "%s: can't allocate %d SCTP hash pointer bytes\n",
1444                     Pn, (int)(INOBUCKS * sizeof(struct sctpsin *)));
1445                 Exit(1);
1446             }
1447         }
1448 /*
1449  * Open the /proc/net/sctp files, assign a page size buffer to the streams,
1450  * and read them.  Store SCTP socket info in the SCTPsin[] hash buckets.
1451  */
1452         for (i = 0; i < NSCTPPATHS; i++ ) {
1453             if (!(ss = open_proc_stream(SCTPPath[i], "r", &vbuf, &vsz, 0)))
1454                 continue;
1455             fl = 1;
1456             while (fgets(buf, sizeof(buf) - 1, ss)) {
1457                 if ((nf = get_fields(buf, (char *)NULL, &fp, (int *)NULL, 0))
1458                 <   (i ? 9 : 16)
1459                 ) {
1460                     continue;
1461                 }
1462                 if (fl) {
1463
1464                 /*
1465                  * Check the column labels in the first line.
1466                  */
1467                     err = 0;
1468                     switch (i) {
1469                     case 0:
1470                         if (!fp[0]  || strcmp(fp[0],  "ASSOC")
1471                         ||  !fp[6]  || strcmp(fp[6],  "ASSOC-ID")
1472                         ||  !fp[10] || strcmp(fp[10], "INODE")
1473                         ||  !fp[11] || strcmp(fp[11], "LPORT")
1474                         ||  !fp[12] || strcmp(fp[12], "RPORT")
1475                         ||  !fp[13] || strcmp(fp[13], "LADDRS")
1476                         ||  !fp[14] || strcmp(fp[14], "<->")
1477                         ||  !fp[15] || strcmp(fp[15], "RADDRS")
1478                         ) {
1479                             err = 1;
1480                         }
1481                         break;
1482                     case 1:
1483                         if (!fp[0]  || strcmp(fp[0],  "ENDPT")
1484                         ||  !fp[5]  || strcmp(fp[5],  "LPORT")
1485                         ||  !fp[7]  || strcmp(fp[7],  "INODE")
1486                         ||  !fp[8]  || strcmp(fp[8],  "LADDRS")
1487                         ) {
1488                             err = 1;
1489                         }
1490                     }
1491                     if (err) {
1492                         if (!Fwarn)
1493                             (void) fprintf(stderr,
1494                                 "%s: WARNING: unsupported format: %s\n",
1495                                 Pn, SCTPPath[i]);
1496                         break;
1497                     }
1498                     fl = 0;
1499                     continue;
1500                 }
1501             /*
1502              * Assemble the inode number and see if it has already been
1503              * recorded.
1504              */
1505                 ep = (char *)NULL;
1506                 j = i ? 7 : 10;
1507                 if (!fp[j] || !*fp[j]
1508                 ||  (inode = strtoull(fp[j], &ep, 0)) == ULONG_MAX
1509                 ||  !ep || *ep)
1510                     continue;
1511                 h = INOHASH((INODETYPE)inode);
1512                 for (sp = SCTPsin[h]; sp; sp = sp->next) {
1513                     if (inode == sp->inode)
1514                         break;
1515                 }
1516             /*
1517              * Set the entry type.
1518              */
1519                 if (sp)
1520                     ty = (sp->type == i) ? i : 3;
1521                 else
1522                     ty = i;
1523             /*
1524              * Allocate space for this line's sctpsin members.
1525              *
1526              * The association or endpoint address is in the first field.
1527              */
1528                 a = sp ? sp->addr : (char *)NULL;
1529                 if (fp[0] && *fp[0] && (len = strlen(fp[0]))) {
1530                     if (a) {
1531                         if (isainb(fp[0], a)) {
1532                             plen = strlen(a);
1533                             a = (char *)realloc((MALLOC_P *)a, plen + len + 2);
1534                             d = 0;
1535                         } else
1536                             d = 1;
1537                     } else {
1538                         plen = (MALLOC_S)0;
1539                         a = (char *)malloc(len + 1);
1540                         d = 0;
1541                     }
1542                     if (!a) {
1543                         (void) fprintf(stderr,
1544                           "%s: can't allocate %d SCTP ASSOC bytes: %s\n",
1545                           Pn, (int)(len + 1), fp[0]);
1546                         Exit(1);
1547                     }
1548                     if (!d) {
1549                         if (plen)
1550                             (void) snpf((a + plen), len + 2, ",%s", fp[0]);
1551                         else
1552                             (void) snpf(a, len + 1, "%s", fp[0]);
1553                     }
1554                 }
1555             /*
1556              * The association ID is in the seventh field.
1557              */
1558                 id = sp ? sp->assocID : (char *)NULL;
1559                 if (!i && fp[6] && *fp[6] && (len = strlen(fp[6]))) {
1560                     if (id) {
1561                         if (isainb(fp[6], id)) {
1562                             plen = strlen(id);
1563                             id = (char *)realloc((MALLOC_P *)id,plen+len+2);
1564                             d = 0;
1565                         } else
1566                             d = 1;
1567                     } else {
1568                         plen = (MALLOC_S)0;
1569                         id = (char *)malloc(len + 1);
1570                         d = 0;
1571                     }
1572                     if (!id) {
1573                         (void) fprintf(stderr,
1574                           "%s: can't allocate %d SCTP ASSOC-ID bytes: %s\n",
1575                           Pn, (int)(len + 1), fp[6]);
1576                         Exit(1);
1577                     }
1578                     if (!d) {
1579                         if (plen)
1580                             (void) snpf((id + plen), len + 2, ",%s", fp[6]);
1581                         else
1582                             (void) snpf(id, len + 1, "%s", fp[6]);
1583                     }
1584                 }
1585             /*
1586              * The field number for the local port depends on the entry type.
1587              */
1588                 j = i ? 5 : 11;
1589                 lp = sp ? sp->lport : (char *)NULL;
1590                 if (fp[j] && *fp[j] && (len = strlen(fp[j]))) {
1591                     if (lp) {
1592                         if (isainb(fp[j], lp)) {
1593                             plen = strlen(lp);
1594                             lp = (char *)realloc((MALLOC_P *)lp,plen+len+2);
1595                             d = 0;
1596                         } else
1597                             d = 1;
1598                     } else {
1599                         plen = (MALLOC_S)0;
1600                         lp = (char *)malloc(len + 1);
1601                         d = 0;
1602                     }
1603                     if (!lp) {
1604                         (void) fprintf(stderr,
1605                           "%s: can't allocate %d SCTP LPORT bytes: %s\n",
1606                           Pn, (int)(len + 1), fp[j]);
1607                         Exit(1);
1608                     }
1609                     if (!d) {
1610                         if (plen)
1611                             (void) snpf((lp + plen), len + 2, ",%s", fp[j]);
1612                         else
1613                             (void) snpf(lp, len + 1, "%s", fp[j]);
1614                     }
1615                 }
1616             /*
1617              * The field number for the remote port depends on the entry type.
1618              */
1619                 rp = sp ? sp->rport : (char *)NULL;
1620                 if (!i && fp[12] && *fp[12] && (len = strlen(fp[12]))) {
1621                     if (rp) {
1622                         if (isainb(fp[12], rp)) {
1623                             plen = strlen(rp);
1624                             rp = (char *)realloc((MALLOC_P *)rp,plen+len+2);
1625                             d = 0;
1626                         } else
1627                             d = 1;
1628                     } else {
1629                         plen = (MALLOC_S)0;
1630                         rp = (char *)malloc(len + 1);
1631                         d = 0;
1632                     }
1633                     if (!rp) {
1634                         (void) fprintf(stderr,
1635                           "%s: can't allocate %d SCTP RPORT bytes: %s\n",
1636                           Pn, (int)(len + 1), fp[12]);
1637                         Exit(1);
1638                     }
1639                     if (!d) {
1640                         if (plen)
1641                             (void) snpf((rp + plen), len + 2, ",%s", fp[12]);
1642                         else
1643                             (void) snpf(rp, len + 1, "%s", fp[12]);
1644                     }
1645                 }
1646             /*
1647              * The local addresses begin in a field whose number depends on
1648              * the entry type.
1649              */
1650                 j = i ? 8 : 13;
1651                 la = sp ? sp->laddrs : (char *)NULL;
1652                 if (fp[j] && *fp[j] && (len = strlen(fp[j]))) {
1653                     if (!(ta = get_sctpaddrs(fp, j, nf, &x))) {
1654                         (void) fprintf(stderr,
1655                           "%s: can't allocate %d SCTP LADDRS bytes\n",
1656                           Pn, (int)len);
1657                         Exit(1);
1658                     }
1659                     if (la) {
1660                         if (isainb(ta, la)) {
1661                             len = strlen(ta);
1662                             plen = strlen(la);
1663                             if (!(la=(char *)realloc((MALLOC_P *)la,plen+len+2))
1664                             ) {
1665                                 (void) fprintf(stderr,
1666                                   "%s: can't reallocate %d SCTP LADDRS bytes\n",
1667                                   Pn, (int)len);
1668                                 Exit(1);
1669                             }
1670                             (void) snpf(la + plen, len + 2, ",%s", ta);
1671                             (void) free((FREE_P *)ta);
1672                         }
1673                     } else
1674                         la = ta;
1675                 }
1676             /*
1677              * The remote addresses begin after the local addresses, but only
1678              * for the ASSOC type.
1679              */
1680                 ra = sp ? sp->raddrs : (char *)NULL;
1681                 if (!i && x && fp[x+1] && *fp[x+1] && (len = strlen(fp[x+1]))) {
1682                     if (!(ta = get_sctpaddrs(fp, x + 1, nf, &x))) {
1683                         (void) fprintf(stderr,
1684                           "%s: can't allocate %d SCTP RADDRS bytes\n",
1685                           Pn, (int)len);
1686                         Exit(1);
1687                     }
1688                     if (ra) {
1689                         if (isainb(ta, ra)) {
1690                             len = strlen(ta);
1691                             plen = strlen(ra);
1692                             if (!(ra=(char *)realloc((MALLOC_P *)ra,plen+len+2))
1693                             ) {
1694                                 (void) fprintf(stderr,
1695                                   "%s: can't reallocate %d SCTP RADDRS bytes\n",
1696                                   Pn, (int)len);
1697                                 Exit(1);
1698                             }
1699                             (void) snpf(ra + plen, len + 2, ",%s", ta);
1700                             (void) free((FREE_P *)ta);
1701                         }
1702                     } else
1703                         ra = ta;
1704                 }
1705             /*
1706              * If no matching sctpsin entry was found for this inode, allocate
1707              * space for a new sctpsin entry, fill it, and link it to its hash
1708              * bucket.  Update a matching entry.
1709              */
1710                 if (!sp) {
1711                     if (!(sp = (struct sctpsin *)malloc(sizeof(struct sctpsin)))                    ) {
1712                         (void) fprintf(stderr,
1713                             "%s: can't allocate %d byte sctpsin structure\n",
1714                             Pn, (int)sizeof(struct sctpsin));
1715                         Exit(1);
1716                     }
1717                     sp->inode = inode;
1718                     sp->next = SCTPsin[h];
1719                     SCTPsin[h] = sp;
1720                 }
1721                 sp->addr = a;
1722                 sp->assocID = id;
1723                 sp->lport = lp;
1724                 sp->rport = rp;
1725                 sp->laddrs = la;
1726                 sp->raddrs = ra;
1727                 sp->type = ty;
1728             }
1729             (void) fclose(ss);
1730         }
1731 }
1732
1733
1734 static char *
1735 get_sctpaddrs(fp, i, nf, x)
1736         char **fp;                      /* field pointers */
1737         int i;                          /* first address field index in fp */
1738         int nf;                         /* number of fields */
1739         int *x;                         /* index of first "<->" field entry */
1740 {
1741         MALLOC_S al = (MALLOC_S)0;
1742         char *cp = (char *)NULL;
1743         MALLOC_S tl;
1744
1745         *x = 0;
1746         do {
1747             if ((i >= nf) || !fp[i] || !*fp[i] || !(tl = strlen(fp[i])))
1748                 break;
1749             if (!strcmp(fp[i], "<->")) {
1750                 *x = i;
1751                 break;
1752             }
1753             if (!strchr(fp[i], (int)'.') && !strchr(fp[i], (int)':'))
1754                 break;
1755             if (cp)
1756                 cp = (char *)realloc((MALLOC_P *)cp, al + tl + 1);
1757             else 
1758                 cp = (char *)malloc(al + tl + 1);
1759             if (!cp)
1760                 break;
1761             if (al)
1762                 *(cp + al - 1) = ',';
1763             (void) strncpy(al ? (cp + al) : cp, fp[i], tl);
1764             al += (tl + 1);
1765             *(cp + al - 1) = '\0';
1766         } while (++i < nf);
1767         return(cp);
1768 }
1769
1770
1771 /*
1772  * get_tcpudp() - get IPv4 TCP, UDP or UDPLITE net info
1773  */
1774
1775 static void
1776 get_tcpudp(p, pr, clr)
1777         char *p;                        /* /proc/net/{tcp,udp} path */
1778         int pr;                         /* protocol: 0 = TCP, 1 = UDP,
1779                                          *           2 = UDPLITE */
1780         int clr;                        /* 1 == clear the table */
1781 {
1782         char buf[MAXPATHLEN], *ep, **fp;
1783         unsigned long faddr, fport, laddr, lport, rxq, state, txq;
1784         FILE *fs;
1785         int h, nf;
1786         INODETYPE inode;
1787         struct tcp_udp *np, *tp;
1788         static char *vbuf = (char *)NULL;
1789         static size_t vsz = (size_t)0;
1790 /*
1791  * Delete previous table contents.
1792  */
1793         if (TcpUdp) {
1794             if (clr) {
1795                 for (h = 0; h < TcpUdp_bucks; h++) {
1796                     for (tp = TcpUdp[h]; tp; tp = np) {
1797                         np = tp->next;
1798                         (void) free((FREE_P *)tp);
1799                     }
1800                     TcpUdp[h] = (struct tcp_udp *)NULL;
1801                 }
1802             }
1803 /*
1804  * If no hash buckets have been allocated, do so now.
1805  */
1806         } else {
1807         
1808         /*
1809          * Open the /proc/net/sockstat file and establish the hash bucket
1810          * count from its "sockets: used" line.
1811          */
1812             TcpUdp_bucks = INOBUCKS;
1813             if ((fs = fopen(SockStatPath, "r"))) {
1814                 while(fgets(buf, sizeof(buf) - 1, fs)) {
1815                     if (get_fields(buf, (char *)NULL, &fp, (int *)NULL, 0) != 3)
1816                         continue;
1817                     if (!fp[0] || strcmp(fp[0], "sockets:")
1818                     ||  !fp[1] || strcmp(fp[1], "used")
1819                     ||  !fp[2] || !*fp[2])
1820                         continue;
1821                     if ((h = atoi(fp[2])) < 1)
1822                         h = INOBUCKS;
1823                     while (TcpUdp_bucks < h)
1824                         TcpUdp_bucks *= 2;
1825                     break;
1826                 }
1827                 (void) fclose(fs);
1828             }
1829             if (!(TcpUdp = (struct tcp_udp **)calloc(TcpUdp_bucks,
1830                                                      sizeof(struct tcp_udp *))))
1831             {
1832                 (void) fprintf(stderr,
1833                     "%s: can't allocate %d bytes for TCP&UDP hash buckets\n",
1834                     Pn, (int)(TcpUdp_bucks * sizeof(struct tcp_udp *)));
1835                 Exit(1);
1836             }
1837         }
1838 /*
1839  * Open the /proc/net file, assign a page size buffer to the stream, and
1840  * read it.
1841  */ 
1842         if (!(fs = open_proc_stream(p, "r", &vbuf, &vsz, 0)))
1843             return;
1844         nf = 12;
1845         while(fgets(buf, sizeof(buf) - 1, fs)) {
1846             if (get_fields(buf,
1847                            (nf == 12) ? (char *)NULL : ":",
1848                            &fp, (int *)NULL, 0)
1849             < nf)
1850                 continue;
1851             if (nf == 12) {
1852                 if (!fp[1]  || strcmp(fp[1],  "local_address")
1853                 ||  !fp[2]  || strcmp(fp[2],  "rem_address")
1854                 ||  !fp[3]  || strcmp(fp[3],  "st")
1855                 ||  !fp[4]  || strcmp(fp[4],  "tx_queue")
1856                 ||  !fp[5]  || strcmp(fp[5],  "rx_queue")
1857                 ||  !fp[11] || strcmp(fp[11], "inode"))
1858                 {
1859                     if (!Fwarn) {
1860                         (void) fprintf(stderr,
1861                             "%s: WARNING: unsupported format: %s\n",
1862                             Pn, p);
1863                     }
1864                     break;
1865                 }
1866                 nf = 14;
1867                 continue;
1868             }
1869         /*
1870          * Get the local and remote addresses.
1871          */
1872             ep = (char *)NULL;
1873             if (!fp[1] || !*fp[1]
1874             ||  (laddr = strtoul(fp[1], &ep, 16)) == ULONG_MAX || !ep || *ep)
1875                 continue;
1876             ep = (char *)NULL;
1877             if (!fp[2] || !*fp[2]
1878             ||  (lport = strtoul(fp[2], &ep, 16)) == ULONG_MAX || !ep || *ep)
1879                 continue;
1880             ep = (char *)NULL;
1881             if (!fp[3] || !*fp[3]
1882             ||  (faddr = strtoul(fp[3], &ep, 16)) == ULONG_MAX || !ep || *ep)
1883                 continue;
1884             ep = (char *)NULL;
1885             if (!fp[4] || !*fp[4]
1886             ||  (fport = strtoul(fp[4], &ep, 16)) == ULONG_MAX || !ep || *ep)
1887                 continue;
1888         /*
1889          * Get the state and queue sizes.
1890          */
1891             ep = (char *)NULL;
1892             if (!fp[5] || !*fp[5]
1893             ||  (state = strtoul(fp[5], &ep, 16)) == ULONG_MAX || !ep || *ep)
1894                 continue;
1895             ep = (char *)NULL;
1896             if (!fp[6] || !*fp[6]
1897             ||  (txq = strtoul(fp[6], &ep, 16)) == ULONG_MAX || !ep || *ep)
1898                 continue;
1899             ep = (char *)NULL;
1900             if (!fp[7] || !*fp[7]
1901             ||  (rxq = strtoul(fp[7], &ep, 16)) == ULONG_MAX || !ep || *ep)
1902                 continue;
1903         /*
1904          * Get the inode and use it for hashing and searching.
1905          */
1906             ep = (char *)NULL;
1907             if (!fp[13] || !*fp[13]
1908             ||  (inode = strtoull(fp[13], &ep, 0)) == ULONG_MAX || !ep || *ep)
1909                 continue;
1910             h = TCPUDPHASH(inode);
1911             for (tp = TcpUdp[h]; tp; tp = tp->next) {
1912                 if (tp->inode == inode)
1913                     break;
1914             }
1915             if (tp)
1916                 continue;
1917         /*
1918          * Create a new entry and link it to its hash bucket.
1919          */
1920             if (!(tp = (struct tcp_udp *)malloc(sizeof(struct tcp_udp)))) {
1921                 (void) fprintf(stderr,
1922                     "%s: can't allocate %d bytes for tcp_udp struct\n",
1923                     Pn, (int)sizeof(struct tcp_udp));
1924                 Exit(1);
1925             }
1926             tp->inode = inode;
1927             tp->faddr = faddr;
1928             tp->fport = (int)(fport & 0xffff);
1929             tp->laddr = laddr;
1930             tp->lport = (int)(lport & 0xffff);
1931             tp->txq = txq;
1932             tp->rxq = rxq;
1933             tp->proto = pr;
1934             tp->state = (int)state;
1935             tp->next = TcpUdp[h];
1936             TcpUdp[h] = tp;
1937         }
1938         (void) fclose(fs);
1939 }
1940
1941
1942 #if     defined(HASIPv6)
1943 /*
1944  * get_raw6() - get /proc/net/raw6 info
1945  */
1946
1947 static void
1948 get_raw6(p)
1949         char *p;                        /* /proc/net/raw path */
1950 {
1951         char buf[MAXPATHLEN], *ep, **fp, *la, *ra, *sp;
1952         int h;
1953         INODETYPE inode;
1954         int nf = 12;
1955         struct rawsin *np, *rp;
1956         MALLOC_S lal, ral, spl;
1957         static char *vbuf = (char *)NULL;
1958         static size_t vsz = (size_t)0;
1959         FILE *xs;
1960 /*
1961  * Do second time cleanup or first time setup.
1962  */
1963         if (Rawsin6) {
1964             for (h = 0; h < INOBUCKS; h++) {
1965                 for (rp = Rawsin6[h]; rp; rp = np) {
1966                     np = rp->next;
1967                     if (rp->la)
1968                         (void) free((FREE_P *)rp->la);
1969                     if (rp->ra)
1970                         (void) free((FREE_P *)rp->ra);
1971                     (void) free((FREE_P *)rp);
1972                 }
1973                 Rawsin6[h] = (struct rawsin *)NULL;
1974             }
1975         } else {
1976             Rawsin6 = (struct rawsin **)calloc(INOBUCKS,
1977                                                sizeof(struct rawsin *));
1978             if (!Rawsin6) {
1979                 (void) fprintf(stderr,
1980                     "%s: can't allocate %d raw6 hash pointer bytes\n",
1981                     Pn, (int)(INOBUCKS * sizeof(struct rawsin *)));
1982                 Exit(1);
1983             }
1984         }
1985 /*
1986  * Open the /proc/net/raw6 file, assign a page size buffer to the stream,
1987  * and read it.  Store raw6 socket info in the Rawsin6[] hash buckets.
1988  */
1989         if (!(xs = open_proc_stream(p, "r", &vbuf, &vsz, 0)))
1990             return;
1991         while (fgets(buf, sizeof(buf) - 1, xs)) {
1992             if (get_fields(buf, (char *)NULL, &fp, (int *)NULL, 0) < nf)
1993                 continue;
1994             if (nf == 12) {
1995
1996             /*
1997              * Check the column labels in the first line.
1998              */
1999                 if (!fp[1]  || strcmp(fp[1],  "local_address")
2000                 ||  !fp[2]  || strcmp(fp[2],  "remote_address")
2001                 ||  !fp[3]  || strcmp(fp[3],  "st")
2002                 ||  !fp[11] || strcmp(fp[11], "inode"))
2003                 {
2004                     if (!Fwarn) {
2005                         (void) fprintf(stderr,
2006                             "%s: WARNING: unsupported format: %s\n",
2007                             Pn, p);
2008                     }
2009                     break;
2010                 }
2011                 nf = 10;
2012                 continue;
2013             }
2014         /*
2015          * Assemble the inode number and see if the inode is already
2016          * recorded.
2017          */
2018             ep = (char *)NULL;
2019             if (!fp[9] || !*fp[9]
2020             ||  (inode = strtoull(fp[9], &ep, 0)) == ULONG_MAX
2021             ||  !ep || *ep)
2022                 continue;
2023             h = INOHASH(inode);
2024             for (rp = Rawsin6[h]; rp; rp = rp->next) {
2025                 if (inode == rp->inode)
2026                     break;
2027             }
2028             if (rp)
2029                 continue;
2030         /*
2031          * Save the local address, remote address, and state.
2032          */
2033             if (!fp[1] || !*fp[1] || (lal = strlen(fp[1])) < 1) {
2034                 la = (char *)NULL;
2035                 lal = (MALLOC_S)0;
2036             } else {
2037                 if (!(la = (char *)malloc(lal + 1))) {
2038                     (void) fprintf(stderr,
2039                         "%s: can't allocate %d local raw6 address bytes: %s\n",
2040                         Pn, (int)(lal + 1), fp[1]);
2041                     Exit(1);
2042                 }
2043                 (void) snpf(la, lal + 1, "%s", fp[1]);
2044             }
2045             if (!fp[2] || !*fp[2] || (ral = strlen(fp[2])) < 1) {
2046                 ra = (char *)NULL;
2047                 ral = (MALLOC_S)0;
2048             } else {
2049                 if (!(ra = (char *)malloc(ral + 1))) {
2050                     (void) fprintf(stderr,
2051                         "%s: can't allocate %d remote raw6 address bytes: %s\n",
2052                         Pn, (int)(ral + 1), fp[2]);
2053                     Exit(1);
2054                 }
2055                 (void) snpf(ra, ral + 1, "%s", fp[2]);
2056             }
2057             if (!fp[3] || !*fp[3] || (spl = strlen(fp[3])) < 1) {
2058                 sp = (char *)NULL;
2059                 spl = (MALLOC_S)0;
2060             } else {
2061                 if (!(sp = (char *)malloc(spl + 1))) {
2062                     (void) fprintf(stderr,
2063                         "%s: can't allocate %d remote raw6 state bytes: %s\n",
2064                         Pn, (int)(spl + 1), fp[2]);
2065                     Exit(1);
2066                 }
2067                 (void) snpf(sp, spl + 1, "%s", fp[3]);
2068             }
2069         /*
2070          * Allocate space for an rawsin entry, fill it, and link it to its
2071          * hash bucket.
2072          */
2073             if (!(rp = (struct rawsin *)malloc(sizeof(struct rawsin)))) {
2074                 (void) fprintf(stderr,
2075                     "%s: can't allocate %d byte rawsin structure for IPv6\n",
2076                     Pn, (int)sizeof(struct rawsin));
2077                 Exit(1);
2078             }
2079             rp->inode = inode;
2080             rp->la = la;
2081             rp->lal = lal;
2082             rp->ra = ra;
2083             rp->ral = ral;
2084             rp->sp = sp;
2085             rp->spl = spl;
2086             rp->next = Rawsin6[h];
2087             Rawsin6[h] = rp;
2088         }
2089         (void) fclose(xs);
2090 }
2091
2092
2093 /*
2094  * get_tcpudp6() - get IPv6 TCP, UDP or UDPLITE net info
2095  */
2096
2097 static void
2098 get_tcpudp6(p, pr, clr)
2099         char *p;                        /* /proc/net/{tcp,udp} path */
2100         int pr;                         /* protocol: 0 = TCP, 1 = UDP */
2101         int clr;                        /* 1 == clear the table */
2102 {
2103         char buf[MAXPATHLEN], *ep, **fp;
2104         struct in6_addr faddr, laddr;
2105         unsigned long fport, lport, rxq, state, txq;
2106         FILE *fs;
2107         int h, i, nf;
2108         INODETYPE inode;
2109         struct tcp_udp6 *np6, *tp6;
2110         static char *vbuf = (char *)NULL;
2111         static size_t vsz = (size_t)0;
2112 /*
2113  * Delete previous table contents.  Allocate a table for the first time.
2114  */
2115         if (TcpUdp6) {
2116             if (clr) {
2117                 for (h = 0; h < TcpUdp6_bucks; h++) {
2118                     for (tp6 = TcpUdp6[h]; tp6; tp6 = np6) {
2119                         np6 = tp6->next;
2120                         (void) free((FREE_P *)tp6);
2121                     }
2122                     TcpUdp6[h] = (struct tcp_udp6 *)NULL;
2123                 }
2124             }
2125         } else {
2126         
2127         /*
2128          * Open the /proc/net/sockstat6 file and establish the hash bucket
2129          * count from its "TCP6: inuse" and "UDP6: inuse" lines.
2130          */
2131             TcpUdp6_bucks = INOBUCKS;
2132             h = i = nf = 0;
2133             if ((fs = fopen(SockStatPath6, "r"))) {
2134                 while(fgets(buf, sizeof(buf) - 1, fs)) {
2135                     if (get_fields(buf, (char *)NULL, &fp, (int *)NULL, 0) != 3)
2136                         continue;
2137                     if (!fp[0]
2138                     ||  !fp[1] || strcmp(fp[1], "inuse")
2139                     ||  !fp[2] || !*fp[2])
2140                         continue;
2141                     if (!strcmp(fp[0], "TCP6:")) {
2142                         nf |= 1;
2143                         if ((h = atoi(fp[2])) < 1)
2144                             h = INOBUCKS;
2145                         i += h;
2146                     } else if (!strcmp(fp[0], "UDP6:")) {
2147                         nf |= 2;
2148                         if ((h = atoi(fp[2])) < 1)
2149                             h = INOBUCKS;
2150                         i += h;
2151                     } else
2152                         continue;
2153                     if (nf == 3) {
2154                         while (TcpUdp6_bucks < i)
2155                             TcpUdp6_bucks *= 2;
2156                         break;
2157                     }
2158                 }
2159                 (void) fclose(fs);
2160             }
2161             if (!(TcpUdp6 = (struct tcp_udp6 **)calloc(TcpUdp6_bucks,
2162                                                 sizeof(struct tcp_udp6 *))))
2163             {
2164                 (void) fprintf(stderr,
2165                     "%s: can't allocate %d bytes for TCP6&UDP6 hash buckets\n",
2166                     Pn, (int)(TcpUdp6_bucks * sizeof(struct tcp_udp6 *)));
2167                 Exit(1);
2168             }
2169         }
2170 /*
2171  * Open the /proc/net file, assign a page size buffer to the stream,
2172  * and read it.
2173  */
2174         if (!(fs = open_proc_stream(p, "r", &vbuf, &vsz, 0)))
2175             return;
2176         nf = 12;
2177         while(fgets(buf, sizeof(buf) - 1, fs)) {
2178             if (get_fields(buf,
2179                            (nf == 12) ? (char *)NULL : ":",
2180                            &fp, (int *)NULL, 0)
2181             < nf)
2182                 continue;
2183             if (nf == 12) {
2184                 if (!fp[1]  || strcmp(fp[1],  "local_address")
2185                 ||  !fp[2]  || strcmp(fp[2],  "remote_address")
2186                 ||  !fp[3]  || strcmp(fp[3],  "st")
2187                 ||  !fp[4]  || strcmp(fp[4],  "tx_queue")
2188                 ||  !fp[5]  || strcmp(fp[5],  "rx_queue")
2189                 ||  !fp[11] || strcmp(fp[11], "inode"))
2190                 {
2191                     if (!Fwarn) {
2192                         (void) fprintf(stderr,
2193                             "%s: WARNING: unsupported format: %s\n",
2194                             Pn, p);
2195                     }
2196                     break;
2197                 }
2198                 nf = 14;
2199                 continue;
2200             }
2201         /*
2202          * Get the local and remote addresses.
2203          */
2204             if (!fp[1] || !*fp[1] || net6a2in6(fp[1], &laddr))
2205                 continue;
2206             ep = (char *)NULL;
2207             if (!fp[2] || !*fp[2]
2208             ||  (lport = strtoul(fp[2], &ep, 16)) == ULONG_MAX || !ep || *ep)
2209                 continue;
2210             if (!fp[3] || !*fp[3] || net6a2in6(fp[3], &faddr))
2211                 continue;
2212             ep = (char *)NULL;
2213             if (!fp[4] || !*fp[4]
2214             ||  (fport = strtoul(fp[4], &ep, 16)) == ULONG_MAX || !ep || *ep)
2215                 continue;
2216         /*
2217          * Get the state and queue sizes.
2218          */
2219             ep = (char *)NULL;
2220             if (!fp[5] || !*fp[5]
2221             ||  (state = strtoul(fp[5], &ep, 16)) == ULONG_MAX || !ep || *ep)
2222                 continue;
2223             ep = (char *)NULL;
2224             if (!fp[6] || !*fp[6]
2225             ||  (txq = strtoul(fp[6], &ep, 16)) == ULONG_MAX || !ep || *ep)
2226                 continue;
2227             ep = (char *)NULL;
2228             if (!fp[7] || !*fp[7]
2229             ||  (rxq = strtoul(fp[7], &ep, 16)) == ULONG_MAX || !ep || *ep)
2230                 continue;
2231         /*
2232          * Get the inode and use it for hashing and searching.
2233          */
2234             ep = (char *)NULL;
2235             if (!fp[13] || !*fp[13]
2236             ||  (inode = strtoull(fp[13], &ep, 0)) == ULONG_MAX || !ep || *ep)
2237                 continue;
2238             h = TCPUDP6HASH(inode);
2239             for (tp6 = TcpUdp6[h]; tp6; tp6 = tp6->next) {
2240                 if (tp6->inode == inode)
2241                     break;
2242             }
2243             if (tp6)
2244                 continue;
2245         /*
2246          * Create a new entry and link it to its hash bucket.
2247          */
2248             if (!(tp6 = (struct tcp_udp6 *)malloc(sizeof(struct tcp_udp6)))) {
2249                 (void) fprintf(stderr,
2250                     "%s: can't allocate %d bytes for tcp_udp6 struct\n",
2251                     Pn, (int)sizeof(struct tcp_udp6));
2252                 Exit(1);
2253             }
2254             tp6->inode = inode;
2255             tp6->faddr = faddr;
2256             tp6->fport = (int)(fport & 0xffff);
2257             tp6->laddr = laddr;
2258             tp6->lport = (int)(lport & 0xffff);
2259             tp6->txq = txq;
2260             tp6->rxq = rxq;
2261             tp6->proto = pr;
2262             tp6->state = (int)state;
2263             tp6->next = TcpUdp6[h];
2264             TcpUdp6[h] = tp6;
2265         }
2266         (void) fclose(fs);
2267 }
2268 #endif  /* defined(HASIPv6) */
2269
2270
2271 /*
2272  * get_unix() - get UNIX net info
2273  */
2274
2275 static void
2276 get_unix(p)
2277         char *p;                        /* /proc/net/unix path */
2278 {
2279         char buf[MAXPATHLEN], *ep, **fp, *path, *pcb;
2280         int fl = 1;
2281         int h, nf;
2282         INODETYPE inode;
2283         MALLOC_S len;
2284         struct uxsin *np, *up;
2285         FILE *us;
2286         uint32_t ty;
2287         static char *vbuf = (char *)NULL;
2288         static size_t vsz = (size_t)0;
2289 /*
2290  * Do second time cleanup or first time setup.
2291  */
2292         if (Uxsin) {
2293             for (h = 0; h < INOBUCKS; h++) {
2294                 for (up = Uxsin[h]; up; up = np) {
2295                     np = up->next;
2296                     if (up->path)
2297                         (void) free((FREE_P *)up->path);
2298                     if (up->pcb)
2299                         (void) free((FREE_P *)up->pcb);
2300                     (void) free((FREE_P *)up);
2301                 }
2302                 Uxsin[h] = (struct uxsin *)NULL;
2303             }
2304         } else {
2305             Uxsin = (struct uxsin **)calloc(INOBUCKS, sizeof(struct uxsin *));
2306             if (!Uxsin) {
2307                 (void) fprintf(stderr,
2308                     "%s: can't allocate %d bytes for Unix socket info\n",
2309                     Pn, (int)(INOBUCKS * sizeof(struct uxsin *)));
2310             }
2311         }
2312 /*
2313  * Open the /proc/net/unix file, assign a page size buffer to the stream,
2314  * read the file's contents, and add them to the Uxsin hash buckets.
2315  */
2316         if (!(us = open_proc_stream(p, "r", &vbuf, &vsz, 0)))
2317             return;
2318         while (fgets(buf, sizeof(buf) - 1, us)) {
2319             if ((nf = get_fields(buf, ":", &fp, (int *)NULL, 0)) < 7)
2320                 continue;
2321             if (fl) {
2322
2323             /*
2324              * Check the first line for header words.
2325              */
2326                 if (!fp[0] || strcmp(fp[0], "Num")
2327                 ||  !fp[1] || strcmp(fp[1], "RefCount")
2328                 ||  !fp[2] || strcmp(fp[2], "Protocol")
2329                 ||  !fp[3] || strcmp(fp[3], "Flags")
2330                 ||  !fp[4] || strcmp(fp[4], "Type")
2331                 ||  !fp[5] || strcmp(fp[5], "St")
2332                 ||  !fp[6] || strcmp(fp[6], "Inode")
2333                 ||  nf < 8
2334                 ||  !fp[7] || strcmp(fp[7], "Path"))
2335                 {
2336                     if (!Fwarn) {
2337                         (void) fprintf(stderr,
2338                             "%s: WARNING: unsupported format: %s\n",
2339                             Pn, p);
2340                     }
2341                     break;
2342                 }
2343                 fl = 0;
2344                 continue;
2345             }
2346         /*
2347          * Assemble PCB address, inode number, and path name.  If this
2348          * inode is already represented in Uxsin, skip it.
2349          */
2350             ep = (char *)NULL;
2351             if (!fp[6] || !*fp[6]
2352             ||  (inode = strtoull(fp[6], &ep, 0)) == ULONG_MAX || !ep || *ep)
2353                 continue;
2354             h = INOHASH(inode);
2355             for (up = Uxsin[h]; up; up = up->next) {
2356                 if (inode == up->inode)
2357                     break;
2358             }
2359             if (up)
2360                 continue;
2361             if (!fp[0] || !*fp[0])
2362                 pcb = (char *)NULL;
2363             else {
2364                 len = strlen(fp[0]) + 2;
2365                 if (!(pcb = (char *)malloc(len + 1))) {
2366                     (void) fprintf(stderr,
2367                         "%s: can't allocate %d bytes for UNIX PCB: %s\n",
2368                         Pn, (int)(len + 1), fp[0]);
2369                     Exit(1);
2370                 }
2371                 (void) snpf(pcb, len + 1, "0x%s", fp[0]);
2372             }
2373             if (nf >= 8 && fp[7] && *fp[7] && (len = strlen(fp[7]))) {
2374                 if (!(path = (char *)malloc(len + 1))) {
2375                     (void) fprintf(stderr,
2376                         "%s: can't allocate %d bytes for UNIX path \"%s\"\n",
2377                         Pn, (int)(len + 1), fp[7]);
2378                     Exit(1);
2379                 }
2380                 (void) snpf(path, len + 1, "%s", fp[7]);
2381             } else
2382                 path = (char *)NULL;
2383         /*
2384          * Assemble socket type.
2385          */
2386             ep = (char *)NULL;
2387             if (!fp[4] || !*fp[4]
2388             ||  (ty = (uint32_t)strtoul(fp[4], &ep, 16)) == (uint32_t)UINT32_MAX
2389             ||  !ep || *ep)
2390             {
2391                 ty = (uint32_t)UINT_MAX;
2392             }
2393         /*
2394          * Allocate and fill a Unix socket info structure; link it to its
2395          * hash bucket.
2396          */
2397             if (!(up = (struct uxsin *)malloc(sizeof(struct uxsin)))) {
2398                 (void) fprintf(stderr,
2399                     "%s: can't allocate %d bytes for uxsin struct\n",
2400                     Pn, (int)sizeof(struct uxsin));
2401                 Exit(1);
2402             }
2403             up->inode = inode;
2404             up->pcb = pcb;
2405             up->sb_def = 0;
2406             up->ty = ty;
2407             if ((up->path = path) && (*path == '/')) {
2408
2409             /*
2410              * If an absolute path (i.e., one that begins with a '/') exists
2411              * for the line, attempt to stat(2) it and save the device and
2412              * node numbers reported in the stat buffer.
2413              */
2414                 struct stat sb;
2415                 int sr;
2416
2417                 if (HasNFS)
2418                     sr = statsafely(path, &sb);
2419                 else
2420                     sr = stat(path, &sb);
2421                 if (sr && ((sb.st_mode & S_IFMT) == S_IFSOCK)) {
2422                     up->sb_def = 1;
2423                     up->sb_dev = sb.st_dev;
2424                     up->sb_ino = (INODETYPE)sb.st_ino;
2425                     up->sb_rdev = sb.st_rdev;
2426                 }
2427             }
2428             up->next = Uxsin[h];
2429             Uxsin[h] = up;
2430         }
2431         (void) fclose(us);
2432 }
2433
2434
2435 #if     defined(HASIPv6)
2436 /*
2437  * net6a2in6() - convert ASCII IPv6 address in /proc/net/{tcp,udp} form to
2438  *               an in6_addr
2439  */
2440
2441 static int
2442 net6a2in6(as, ad)
2443         char *as;                       /* address source */
2444         struct in6_addr *ad;            /* address destination */
2445 {
2446         char buf[9], *ep;
2447         int i;
2448         size_t len;
2449 /*
2450  * Assemble four uint32_t's from 4 X 8 hex digits into s6_addr32[].
2451  */
2452         for (i = 0, len = strlen(as);
2453              (i < 4) && (len >= 8);
2454              as += 8, i++, len -= 8)
2455         {
2456             (void) strncpy(buf, as, 8);
2457             buf[8] = '\0';
2458             ep = (char *)NULL;
2459             if ((ad->s6_addr32[i] = (uint32_t)strtoul(buf, &ep, 16))
2460             ==  (uint32_t)UINT32_MAX || !ep || *ep)
2461                 break;
2462         }
2463         return((*as || (i != 4) || len) ? 1 : 0);
2464 }
2465 #endif  /* defined(HASIPv6) */
2466
2467
2468 /*
2469  * isainb(a,b) is string a in string b
2470  */
2471
2472 static int
2473 isainb(a, b)
2474         char *a;                        /*string a */
2475         char *b;                        /* string b */
2476 {
2477         char *cp, *pp;
2478         MALLOC_S la, lb, lt;
2479
2480         if (!a || !b)
2481             return(1);
2482         if (!(la = strlen(a)) || !(lb = strlen(b)))
2483             return(1);
2484         if (!(cp = strchr(b, (int)','))) {
2485             if (la != lb)
2486                 return(1);
2487             return(strcmp(a, b));
2488         }
2489         for (pp = b; pp && *pp; ) {
2490             lt = (MALLOC_S)(cp - pp);
2491             if ((la == lt) && !strncmp(a, pp, lt))
2492                 return(0);
2493             if (*cp) {
2494                 pp = cp + 1;
2495                 if (!(cp = strchr(pp, (int)',')))
2496                     cp = b + lb;
2497             } else
2498                 pp = cp;
2499         }
2500         return(1);
2501 }
2502
2503
2504 /*
2505  * print_ax25info() - print AX25 socket info
2506  */
2507
2508 static void
2509 print_ax25info(ap)
2510         struct ax25sin *ap;             /* AX25 socket info */
2511 {
2512         char *cp, pbuf[1024];
2513         int ds;
2514         MALLOC_S pl = (MALLOC_S)0;
2515
2516         if (Lf->nma)
2517             return;
2518         if (ap->sa) {
2519             ds = (ap->da && strcmp(ap->da, "*")) ? 1 : 0;
2520             (void) snpf(&pbuf[pl], sizeof(pbuf) - pl, "%s%s%s ", ap->sa,
2521                 ds ? "->" : "",
2522                 ds ? ap->da : "");
2523             pl = strlen(pbuf);
2524         }
2525         if (ap->sqs) {
2526             (void) snpf(&pbuf[pl], sizeof(pbuf) - pl, "(Sq=%lu ", ap->sq);
2527             pl = strlen(pbuf);
2528             cp = "";
2529         } else 
2530             cp = "(";
2531         if (ap->rqs) {
2532             (void) snpf(&pbuf[pl], sizeof(pbuf) - pl, "%sRq=%lu ", cp, ap->rq);
2533             pl = strlen(pbuf);
2534             cp = "";
2535         }
2536         (void) snpf(&pbuf[pl], sizeof(pbuf) - pl, "%sState=%d", cp, ap->state);
2537         pl = strlen(pbuf);
2538         if ((ap->state >= 0) && (ap->state < NAX25ST))
2539             cp = ax25st[ap->state];
2540         else
2541             cp = NULL;
2542         (void) snpf(&pbuf[pl], sizeof(pbuf) - pl, "%s%s)",
2543             cp ? ", " : "",
2544             cp ? cp : "");
2545         pl = strlen(pbuf);
2546         if (!(cp = (char *)malloc(pl + 1))) {
2547             (void) fprintf(stderr,
2548                 "%s: can't allocate %d bytes for AX25 sock state, PID: %d\n",
2549                 Pn, (int)(pl + 1), Lp->pid);
2550             Exit(1);
2551         }
2552         (void) snpf(cp, pl + 1, "%s", pbuf);
2553         Lf->nma = cp;
2554 }
2555
2556
2557 /*
2558  * print_ipxinfo() - print IPX socket info
2559  */
2560
2561 static void
2562 print_ipxinfo(ip)
2563         struct ipxsin *ip;              /* IPX socket info */
2564 {
2565         char *cp, pbuf[256];
2566         MALLOC_S pl;
2567
2568         if (Lf->nma)
2569             return;
2570         (void) snpf(pbuf, sizeof(pbuf), "(Tx=%lx Rx=%lx State=%02x)",
2571             ip->txq, ip->rxq, ip->state);
2572         pl = strlen(pbuf);
2573         if (!(cp = (char *)malloc(pl + 1))) {
2574             (void) fprintf(stderr,
2575                 "%s: can't allocate %d bytes for IPX sock state, PID: %d\n",
2576                 Pn, (int)(pl + 1), Lp->pid);
2577             Exit(1);
2578         }
2579         (void) snpf(cp, pl + 1, "%s", pbuf);
2580         Lf->nma = cp;
2581 }
2582
2583
2584 /*
2585  * print_tcptpi() - print TCP/TPI state
2586  */
2587
2588 void
2589 print_tcptpi(nl)
2590         int nl;                         /* 1 == '\n' required */
2591 {
2592         char buf[128];
2593         char *cp = (char *)NULL;
2594         int ps = 0;
2595         int s;
2596
2597         if ((Ftcptpi & TCPTPI_STATE) && Lf->lts.type == 0) {
2598             if (!TcpSt)
2599                 (void) build_IPstates();
2600             if ((s = Lf->lts.state.i + TcpStOff) < 0 || s >= TcpNstates) {
2601                 (void) snpf(buf, sizeof(buf), "UNKNOWN_TCP_STATE_%d",
2602                     Lf->lts.state.i);
2603                 cp = buf;
2604             } else
2605                 cp = TcpSt[s];
2606             if (cp) {
2607                 if (Ffield)
2608                     (void) printf("%cST=%s%c", LSOF_FID_TCPTPI, cp, Terminator);
2609                 else {
2610                     putchar('(');
2611                     (void) fputs(cp, stdout);
2612                 }
2613                 ps++;
2614             }
2615         }
2616
2617 # if    defined(HASTCPTPIQ)
2618         if (Ftcptpi & TCPTPI_QUEUES) {
2619             if (Lf->lts.rqs) {
2620                 if (Ffield)
2621                     putchar(LSOF_FID_TCPTPI);
2622                 else {
2623                     if (ps)
2624                         putchar(' ');
2625                     else
2626                         putchar('(');
2627                 }
2628                 (void) printf("QR=%lu", Lf->lts.rq);
2629                 if (Ffield)
2630                     putchar(Terminator);
2631                 ps++;
2632             }
2633             if (Lf->lts.sqs) {
2634                 if (Ffield)
2635                     putchar(LSOF_FID_TCPTPI);
2636                 else {
2637                     if (ps)
2638                         putchar(' ');
2639                     else
2640                         putchar('(');
2641                 }
2642                 (void) printf("QS=%lu", Lf->lts.sq);
2643                 if (Ffield)
2644                     putchar(Terminator);
2645                 ps++;
2646             }
2647         }
2648 # endif /* defined(HASTCPTPIQ) */
2649
2650 # if    defined(HASTCPTPIW)
2651         if (Ftcptpi & TCPTPI_WINDOWS) {
2652             if (Lf->lts.rws) {
2653                 if (Ffield)
2654                     putchar(LSOF_FID_TCPTPI);
2655                 else {
2656                     if (ps)
2657                         putchar(' ');
2658                     else
2659                         putchar('(');
2660                 }
2661                 (void) printf("WR=%lu", Lf->lts.rw);
2662                 if (Ffield)
2663                     putchar(Terminator);
2664                 ps++;
2665             }
2666             if (Lf->lts.wws) {
2667                 if (Ffield)
2668                     putchar(LSOF_FID_TCPTPI);
2669                 else {
2670                     if (ps)
2671                         putchar(' ');
2672                     else
2673                         putchar('(');
2674                 }
2675                 (void) printf("WW=%lu", Lf->lts.ww);
2676                 if (Ffield)
2677                     putchar(Terminator);
2678                 ps++;
2679             }
2680         }
2681 # endif /* defined(HASTCPTPIW) */
2682
2683         if (!Ffield && ps)
2684             putchar(')');
2685         if (nl)
2686             putchar('\n');
2687 }
2688
2689
2690 /*
2691  * process_proc_sock() - process /proc-based socket
2692  */
2693
2694 void
2695 process_proc_sock(p, pbr, s, ss, l, lss)
2696         char *p;                        /* node's readlink() path */
2697         char *pbr;                      /* node's path before readlink() */
2698         struct stat *s;                 /* stat() result for path */
2699         int ss;                         /* *s status -- i.e, SB_* values */
2700         struct stat *l;                 /* lstat() result for FD (NULL for
2701                                          * others) */
2702         int lss;                        /* *l status -- i.e, SB_* values */
2703 {
2704         struct ax25sin *ap;
2705         char *cp, *path, tbuf[64];
2706         unsigned char *fa, *la;
2707         struct in_addr fs, ls;
2708         struct icmpin *icmpp;
2709         struct ipxsin *ip;
2710         int i, len, nl, rf;
2711         struct nlksin *np;
2712         struct packin *pp;
2713         char *pr;
2714         static char *prp = (char *)NULL;
2715         struct rawsin *rp;
2716         struct sctpsin *sp;
2717         static ssize_t sz;
2718         struct tcp_udp *tp;
2719         struct uxsin *up;
2720
2721 #if     defined(HASIPv6)
2722         int af;
2723         struct tcp_udp6 *tp6;
2724 #endif  /* defined(HASIPv6) */
2725
2726 /*
2727  * Enter offset, if possible.
2728  */
2729         if (Foffset || !Fsize) {
2730             if (l && (lss & SB_SIZE) && OffType) {
2731                 Lf->off = (SZOFFTYPE)l->st_size;
2732                 Lf->off_def = 1;
2733             }
2734         }
2735 /*
2736  * Check for socket's inode presence in the protocol info caches.
2737  */
2738         if (AX25path) {
2739             (void) get_ax25(AX25path);
2740             (void) free((FREE_P *)AX25path);
2741             AX25path = (char *)NULL;
2742         }
2743         if ((ss & SB_INO)
2744         &&  (ap = check_ax25((INODETYPE)s->st_ino))
2745         ) {
2746         
2747         /*
2748          * The inode is connected to an AX25 /proc record.
2749          *
2750          * Set the type to "ax25"; save the device name; save the inode number;
2751          * save the destination and source addresses; save the send and receive
2752          * queue sizes; and save the connection state.
2753          */
2754             (void) snpf(Lf->type, sizeof(Lf->type), "ax25");
2755             if (ap->dev_ch)
2756                 (void) enter_dev_ch(ap->dev_ch);
2757             Lf->inode = ap->inode;
2758             Lf->inp_ty = 1;
2759             print_ax25info(ap);
2760             return;
2761         }
2762         if (Ipxpath) {
2763             (void) get_ipx(Ipxpath);
2764             (void) free((FREE_P *)Ipxpath);
2765             Ipxpath = (char *)NULL;
2766         }
2767         if ((ss & SB_INO)
2768         &&  (ip = check_ipx((INODETYPE)s->st_ino))
2769         ) {
2770
2771         /*
2772          * The inode is connected to an IPX /proc record.
2773          *
2774          * Set the type to "ipx"; enter the inode and device numbers; store
2775          * the addresses, queue sizes, and state in the NAME column.
2776          */
2777             (void) snpf(Lf->type, sizeof(Lf->type), "ipx");
2778             if (ss & SB_INO) {
2779                 Lf->inode = (INODETYPE)s->st_ino;
2780                 Lf->inp_ty = 1;
2781             }
2782             if (ss & SB_DEV) {
2783                 Lf->dev = s->st_dev;
2784                 Lf->dev_def = 1;
2785             }
2786             cp = Namech;
2787             nl = Namechl;
2788             *cp = '\0';
2789             if (ip->la && nl) {
2790
2791             /*
2792              * Store the local IPX address.
2793              */
2794                 len = strlen(ip->la);
2795                 if (len > nl)
2796                     len = nl;
2797                 (void) strncpy(cp, ip->la, len);
2798                 cp += len;
2799                 *cp = '\0';
2800                 nl -= len;
2801             }
2802             if (ip->ra && nl) {
2803
2804             /*
2805              * Store the remote IPX address, prefixed with "->".
2806              */
2807                 if (nl > 2) {
2808                     (void) snpf(cp, nl, "->");
2809                     cp += 2;
2810                     nl -= 2;
2811                 }
2812                 if (nl) {
2813                     (void) snpf(cp, nl, "%s", ip->ra);
2814                     cp += len;
2815                     nl -= len;
2816                 }
2817             }
2818             (void) print_ipxinfo(ip);
2819             if (Namech[0])
2820                 enter_nm(Namech);
2821             return;
2822         }
2823         if (Rawpath) {
2824             (void) get_raw(Rawpath);
2825             (void) free((FREE_P *)Rawpath);
2826             Rawpath = (char *)NULL;
2827         }
2828         if ((ss & SB_INO)
2829         &&  (rp = check_raw((INODETYPE)s->st_ino))
2830         ) {
2831
2832         /*
2833          * The inode is connected to a raw /proc record.
2834          *
2835          * Set the type to "raw"; enter the inode number; store the local
2836          * address, remote address, and state in the NAME column.
2837          */
2838             (void) snpf(Lf->type, sizeof(Lf->type), "raw");
2839             if (ss & SB_INO) {
2840                 Lf->inode = (INODETYPE)s->st_ino;
2841                 Lf->inp_ty = 1;
2842             }
2843             cp = Namech;
2844             nl = Namechl - 2;
2845             *cp = '\0';
2846             if (rp->la && rp->lal) {
2847
2848             /*
2849              * Store the local raw address.
2850              */
2851                 if (nl > rp->lal) {
2852                     (void) snpf(cp, nl, "%s", rp->la);
2853                     cp += rp->lal;
2854                     *cp = '\0';
2855                     nl -= rp->lal;
2856                 }
2857             }
2858             if (rp->ra && rp->ral) {
2859
2860             /*
2861              * Store the remote raw address, prefixed with "->".
2862              */
2863                 if (nl > (rp->ral + 2)) {
2864                     (void) snpf(cp, nl, "->%s", rp->ra);
2865                     cp += (rp->ral + 2);
2866                     *cp = '\0';
2867                     nl -= (rp->ral + 2);
2868                 }
2869             }
2870             if (rp->sp && rp->spl) {
2871
2872             /*
2873              * Store the state, optionally prefixed by a space, in the
2874              * form "st=x...x".
2875              */
2876             
2877                 if (nl > (len = ((cp == Namech) ? 0 : 1) + 3 + rp->spl)) {
2878                     (void) snpf(cp, nl, "%sst=%s",
2879                         (cp == Namech) ? "" : " ", rp->sp);
2880                     cp += len;
2881                     *cp = '\0';
2882                     nl -= len;
2883                 }
2884             }
2885             if (Namech[0])
2886                 enter_nm(Namech);
2887             return;
2888         }
2889         if (Nlkpath) {
2890             (void) get_netlink(Nlkpath);
2891             (void) free((FREE_P *) Nlkpath);
2892             Nlkpath = (char *)NULL;
2893         }
2894         if ((ss & SB_INO)
2895             &&  (np = check_netlink((INODETYPE)s->st_ino))
2896         ) {
2897             /*
2898              * The inode is connected to a Netlink /proc record.
2899              *
2900              * Set the type to "netlink" and store the protocol in the NAME
2901              * column.  Save the inode number.
2902              */
2903
2904             (void) snpf(Lf->type, sizeof(Lf->type), "netlink");
2905             switch (np->pr) {
2906
2907 #if     defined(NETLINK_ROUTE)
2908             case NETLINK_ROUTE:
2909                 cp = "ROUTE";
2910                 break;
2911 #endif  /* defined(NETLINK_ROUTE) */
2912
2913 #if     defined(NETLINK_UNUSED)
2914             case NETLINK_UNUSED:
2915                 cp = "UNUSED";
2916                 break;
2917 #endif  /* defined(NETLINK_UNUSED) */
2918
2919 #if     defined(NETLINK_USERSOCK)
2920             case NETLINK_USERSOCK:
2921                 cp = "USERSOCK";
2922                 break;
2923 #endif  /* defined(NETLINK_USERSOCK) */
2924
2925 #if     defined(NETLINK_FIREWALL)
2926             case NETLINK_FIREWALL:
2927                 cp = "FIREWALL";
2928                 break;
2929 #endif  /* defined(NETLINK_FIREWALL) */
2930
2931 #if     defined(NETLINK_INET_DIAG)
2932             case NETLINK_INET_DIAG:
2933                 cp = "INET_DIAG";
2934                 break;
2935 #endif  /* defined(NETLINK_INET_DIAG) */
2936
2937 #if     defined(NETLINK_NFLOG)
2938             case NETLINK_NFLOG:
2939                 cp = "NFLOG";
2940                 break;
2941 #endif  /* defined(NETLINK_NFLOG) */
2942
2943 #if     defined(NETLINK_XFRM)
2944             case NETLINK_XFRM:
2945                 cp = "XFRM";
2946                 break;
2947 #endif  /* defined(NETLINK_XFRM) */
2948
2949 #if     defined(NETLINK_SELINUX)
2950             case NETLINK_SELINUX:
2951                 cp = "SELINUX";
2952                 break;
2953 #endif  /* defined(NETLINK_SELINUX) */
2954
2955 #if     defined(NETLINK_ISCSI)
2956             case NETLINK_ISCSI:
2957                 cp = "ISCSI";
2958                 break;
2959 #endif  /* defined(NETLINK_ISCSI) */
2960
2961 #if     defined(NETLINK_AUDIT)
2962             case NETLINK_AUDIT:
2963                 cp = "AUDIT";
2964                 break;
2965 #endif  /* defined(NETLINK_AUDIT) */
2966
2967 #if     defined(NETLINK_FIB_LOOKUP)
2968             case NETLINK_FIB_LOOKUP:
2969                 cp = "FIB_LOOKUP";
2970                 break;
2971 #endif  /* defined(NETLINK_FIB_LOOKUP) */
2972
2973 #if     defined(NETLINK_CONNECTOR)
2974             case NETLINK_CONNECTOR:
2975                 cp = "CONNECTOR";
2976                 break;
2977 #endif  /* defined(NETLINK_CONNECTOR) */
2978
2979 #if     defined(NETLINK_NETFILTER)
2980             case NETLINK_NETFILTER:
2981                 cp = "NETFILTER";
2982                 break;
2983 #endif  /* defined(NETLINK_NETFILTER) */
2984
2985 #if     defined(NETLINK_IP6_FW)
2986             case NETLINK_IP6_FW:
2987                 cp = "IP6_FW";
2988                 break;
2989 #endif  /* defined(NETLINK_IP6_FW) */
2990
2991 #if     defined(NETLINK_DNRTMSG)
2992             case NETLINK_DNRTMSG:
2993                 cp = "DNRTMSG";
2994                 break;
2995 #endif  /* defined(NETLINK_DNRTMSG) */
2996
2997 #if     defined(NETLINK_KOBJECT_UEVENT)
2998             case NETLINK_KOBJECT_UEVENT:
2999                 cp = "KOBJECT_UEVENT";
3000                 break;
3001 #endif  /* defined(NETLINK_KOBJECT_UEVENT) */
3002
3003 #if     defined(NETLINK_GENERIC)
3004             case NETLINK_GENERIC:
3005                 cp = "GENERIC";
3006                 break;
3007 #endif  /* defined(NETLINK_GENERIC) */
3008
3009 #if     defined(NETLINK_SCSITRANSPORT)
3010             case NETLINK_SCSITRANSPORT:
3011                 cp = "SCSITRANSPORT";
3012                 break;
3013 #endif  /* defined(NETLINK_SCSITRANSPORT) */
3014
3015 #if     defined(NETLINK_ECRYPTFS)
3016             case NETLINK_ECRYPTFS:
3017                 cp = "ECRYPTFS";
3018                 break;
3019 #endif  /* defined(NETLINK_ECRYPTFS) */
3020
3021             default:
3022                 (void) snpf(Namech, Namechl, "unknown protocol: %d", np->pr);
3023                 cp = (char *)NULL;
3024             }
3025             if (cp)
3026                 (void) snpf(Namech, Namechl, "%s", cp);
3027             Lf->inode = (INODETYPE)s->st_ino;
3028             Lf->inp_ty = 1;
3029             if (Namech[0])
3030                 enter_nm(Namech);
3031             return;
3032         }
3033         if (Packpath) {
3034             (void) get_pack(Packpath);
3035             (void) free((FREE_P *)Packpath);
3036             Packpath = (char *)NULL;
3037         }
3038         if ((ss & SB_INO)
3039         &&  (pp = check_pack((INODETYPE)s->st_ino))
3040         ) {
3041
3042         /*
3043          * The inode is connected to a packet /proc record.
3044          *
3045          * Set the type to "pack" and store the socket type in the NAME
3046          * column.  Put the protocol name in the NODE column and the inode
3047          * number in the DEVICE column.
3048          */
3049             (void) snpf(Lf->type, sizeof(Lf->type), "pack");
3050             cp = sockty2str(pp->ty, &rf);
3051             (void) snpf(Namech, Namechl, "type=%s%s", rf ? "" : "SOCK_", cp);
3052             switch (pp->pr) {
3053
3054 #if     defined(ETH_P_LOOP)
3055             case ETH_P_LOOP:
3056                 cp = "LOOP";
3057                 break;
3058 #endif  /* defined(ETH_P_LOOP) */
3059
3060 #if     defined(ETH_P_PUP)
3061             case ETH_P_PUP:
3062                 cp = "PUP";
3063                 break;
3064 #endif  /* defined(ETH_P_PUP) */
3065
3066 #if     defined(ETH_P_PUPAT)
3067             case ETH_P_PUPAT:
3068                 cp = "PUPAT";
3069                 break;
3070 #endif  /* defined(ETH_P_PUPAT) */
3071
3072 #if     defined(ETH_P_IP)
3073             case ETH_P_IP:
3074                 cp = "IP";
3075                 break;
3076 #endif  /* defined(ETH_P_IP) */
3077
3078 #if     defined(ETH_P_X25)
3079             case ETH_P_X25:
3080                 cp = "X25";
3081                 break;
3082 #endif  /* defined(ETH_P_X25) */
3083
3084 #if     defined(ETH_P_ARP)
3085             case ETH_P_ARP:
3086                 cp = "ARP";
3087                 break;
3088 #endif  /* defined(ETH_P_ARP) */
3089
3090 #if     defined(ETH_P_BPQ)
3091             case ETH_P_BPQ:
3092                 cp = "BPQ";
3093                 break;
3094 #endif  /* defined(ETH_P_BPQ) */
3095
3096 #if     defined(ETH_P_IEEEPUP)
3097             case ETH_P_IEEEPUP:
3098                 cp = "I3EPUP";
3099                 break;
3100 #endif  /* defined(ETH_P_IEEEPUP) */
3101
3102 #if     defined(ETH_P_IEEEPUPAT)
3103             case ETH_P_IEEEPUPAT:
3104                 cp = "I3EPUPA";
3105                 break;
3106 #endif  /* defined(ETH_P_IEEEPUPAT) */
3107
3108 #if     defined(ETH_P_DEC)
3109             case ETH_P_DEC:
3110                 cp = "DEC";
3111                 break;
3112 #endif  /* defined(ETH_P_DEC) */
3113
3114 #if     defined(ETH_P_DNA_DL)
3115             case ETH_P_DNA_DL:
3116                 cp = "DNA_DL";
3117                 break;
3118 #endif  /* defined(ETH_P_DNA_DL) */
3119
3120 #if     defined(ETH_P_DNA_RC)
3121             case ETH_P_DNA_RC:
3122                 cp = "DNA_RC";
3123                 break;
3124 #endif  /* defined(ETH_P_DNA_RC) */
3125
3126 #if     defined(ETH_P_DNA_RT)
3127             case ETH_P_DNA_RT:
3128                 cp = "DNA_RT";
3129                 break;
3130 #endif  /* defined(ETH_P_DNA_RT) */
3131
3132 #if     defined(ETH_P_LAT)
3133             case ETH_P_LAT:
3134                 cp = "LAT";
3135                 break;
3136 #endif  /* defined(ETH_P_LAT) */
3137
3138 #if     defined(ETH_P_DIAG)
3139             case ETH_P_DIAG:
3140                 cp = "DIAG";
3141                 break;
3142 #endif  /* defined(ETH_P_DIAG) */
3143
3144 #if     defined(ETH_P_CUST)
3145             case ETH_P_CUST:
3146                 cp = "CUST";
3147                 break;
3148 #endif  /* defined(ETH_P_CUST) */
3149
3150 #if     defined(ETH_P_SCA)
3151             case ETH_P_SCA:
3152                 cp = "SCA";
3153                 break;
3154 #endif  /* defined(ETH_P_SCA) */
3155
3156 #if     defined(ETH_P_RARP)
3157             case ETH_P_RARP:
3158                 cp = "RARP";
3159                 break;
3160 #endif  /* defined(ETH_P_RARP) */
3161
3162 #if     defined(ETH_P_ATALK)
3163             case ETH_P_ATALK:
3164                 cp = "ATALK";
3165                 break;
3166 #endif  /* defined(ETH_P_ATALK) */
3167
3168 #if     defined(ETH_P_AARP)
3169             case ETH_P_AARP:
3170                 cp = "AARP";
3171                 break;
3172 #endif  /* defined(ETH_P_AARP) */
3173
3174 #if     defined(ETH_P_8021Q)
3175             case ETH_P_8021Q:
3176                 cp = "8021Q";
3177                 break;
3178 #endif  /* defined(ETH_P_8021Q) */
3179
3180 #if     defined(ETH_P_IPX)
3181             case ETH_P_IPX:
3182                 cp = "IPX";
3183                 break;
3184 #endif  /* defined(ETH_P_IPX) */
3185
3186 #if     defined(ETH_P_IPV6)
3187             case ETH_P_IPV6:
3188                 cp = "IPV6";
3189                 break;
3190 #endif  /* defined(ETH_P_IPV6) */
3191
3192 #if     defined(ETH_P_SLOW)
3193             case ETH_P_SLOW:
3194                 cp = "SLOW";
3195                 break;
3196 #endif  /* defined(ETH_P_SLOW) */
3197         
3198 #if     defined(ETH_P_WCCP)
3199             case ETH_P_WCCP:
3200                 cp = "WCCP";
3201                 break;
3202 #endif  /* defined(ETH_P_WCCP) */
3203
3204 #if     defined(ETH_P_PPP_DISC)
3205             case ETH_P_PPP_DISC:
3206                 cp = "PPP_DIS";
3207                 break;
3208 #endif  /* defined(ETH_P_PPP_DISC) */
3209
3210 #if     defined(ETH_P_PPP_SES)
3211             case ETH_P_PPP_SES:
3212                 cp = "PPP_SES";
3213                 break;
3214 #endif  /* defined(ETH_P_PPP_SES) */
3215
3216 #if     defined(ETH_P_MPLS_UC)
3217             case ETH_P_MPLS_UC:
3218                 cp = "MPLS_UC";
3219                 break;
3220 #endif  /* defined(ETH_P_MPLS_UC) */
3221
3222 #if     defined(ETH_P_ATMMPOA)
3223             case ETH_P_ATMMPOA:
3224                 cp = "ATMMPOA";
3225                 break;
3226 #endif  /* defined(ETH_P_ATMMPOA) */
3227
3228 #if     defined(ETH_P_MPLS_MC)
3229             case ETH_P_MPLS_MC:
3230                 cp = "MPLS_MC";
3231                 break;
3232 #endif  /* defined(ETH_P_MPLS_MC) */
3233
3234 #if     defined(ETH_P_ATMFATE)
3235             case ETH_P_ATMFATE:
3236                 cp = "ATMFATE";
3237                 break;
3238 #endif  /* defined(ETH_P_ATMFATE) */
3239
3240 #if     defined(ETH_P_AOE)
3241             case ETH_P_AOE:
3242                 cp = "AOE";
3243                 break;
3244 #endif  /* defined(ETH_P_AOE) */
3245
3246 #if     defined(ETH_P_TIPC)
3247             case ETH_P_TIPC:
3248                 cp = "TIPC";
3249                 break;
3250 #endif  /* defined(ETH_P_TIPC) */
3251
3252 #if     defined(ETH_P_802_3)
3253             case ETH_P_802_3:
3254                 cp = "802.3";
3255                 break;
3256 #endif  /* defined(ETH_P_802_3) */
3257
3258 #if     defined(ETH_P_AX25)
3259             case ETH_P_AX25:
3260                 cp = "AX25";
3261                 break;
3262 #endif  /* defined(ETH_P_AX25) */
3263
3264 #if     defined(ETH_P_ALL)
3265             case ETH_P_ALL:
3266                 cp = "ALL";
3267                 break;
3268 #endif  /* defined(ETH_P_ALL) */
3269
3270 #if     defined(ETH_P_802_2)
3271             case ETH_P_802_2:
3272                 cp = "802.2";
3273                 break;
3274 #endif  /* defined(ETH_P_802_2) */
3275
3276 #if     defined(ETH_P_SNAP)
3277             case ETH_P_SNAP:
3278                 cp = "SNAP";
3279                 break;
3280 #endif  /* defined(ETH_P_SNAP) */
3281
3282 #if     defined(ETH_P_DDCMP)
3283             case ETH_P_DDCMP:
3284                 cp = "DDCMP";
3285                 break;
3286 #endif  /* defined(ETH_P_DDCMP) */
3287
3288 #if     defined(ETH_P_WAN_PPP)
3289             case ETH_P_WAN_PPP:
3290                 cp = "WAN_PPP";
3291                 break;
3292 #endif  /* defined(ETH_P_WAN_PPP) */
3293
3294 #if     defined(ETH_P_PPP_MP)
3295             case ETH_P_PPP_MP:
3296                 cp = "PPP MP";
3297                 break;
3298 #endif  /* defined(ETH_P_PPP_MP) */
3299
3300 #if     defined(ETH_P_LOCALTALK)
3301             case ETH_P_LOCALTALK:
3302                 cp = "LCLTALK";
3303                 break;
3304 #endif  /* defined(ETH_P_LOCALTALK) */
3305
3306 #if     defined(ETH_P_PPPTALK)
3307             case ETH_P_PPPTALK:
3308                 cp = "PPPTALK";
3309                 break;
3310 #endif  /* defined(ETH_P_PPPTALK) */
3311
3312 #if     defined(ETH_P_TR_802_2)
3313             case ETH_P_TR_802_2:
3314                 cp = "802.2";
3315                 break;
3316 #endif  /* defined(ETH_P_TR_802_2) */
3317
3318 #if     defined(ETH_P_MOBITEX)
3319             case ETH_P_MOBITEX:
3320                 cp = "MOBITEX";
3321                 break;
3322 #endif  /* defined(ETH_P_MOBITEX) */
3323
3324 #if     defined(ETH_P_CONTROL)
3325             case ETH_P_CONTROL:
3326                 cp = "CONTROL";
3327                 break;
3328 #endif  /* defined(ETH_P_CONTROL) */
3329
3330 #if     defined(ETH_P_IRDA)
3331             case ETH_P_IRDA:
3332                 cp = "IRDA";
3333                 break;
3334 #endif  /* defined(ETH_P_IRDA) */
3335
3336 #if     defined(ETH_P_ECONET)
3337             case ETH_P_ECONET:
3338                 cp = "ECONET";
3339                 break;
3340 #endif  /* defined(ETH_P_ECONET) */
3341
3342 #if     defined(ETH_P_HDLC)
3343             case ETH_P_HDLC:
3344                 cp = "HDLC";
3345                 break;
3346 #endif  /* defined(ETH_P_HDLC) */
3347
3348 #if     defined(ETH_P_ARCNET)
3349             case ETH_P_ARCNET:
3350                 cp = "ARCNET";
3351                 break;
3352 #endif  /* defined(ETH_P_ARCNET) */
3353
3354             default:
3355                 (void) snpf(tbuf, sizeof(tbuf) - 1, "%d", pp->pr);
3356                 tbuf[sizeof(tbuf) - 1] = '\0';
3357                 cp = tbuf;
3358             }
3359             (void) snpf(Lf->iproto, sizeof(Lf->iproto), "%.*s", IPROTOL-1, cp);
3360             Lf->inp_ty = 2;
3361             if (ss & SB_INO) {
3362                 (void) snpf(tbuf, sizeof(tbuf), InodeFmt_d,
3363                     (INODETYPE)s->st_ino);
3364                 tbuf[sizeof(tbuf) - 1] = '\0';
3365                 enter_dev_ch(tbuf);
3366             }
3367             if (Namech[0])
3368                 enter_nm(Namech);
3369             return;
3370         }
3371         if (UNIXpath) {
3372             (void) get_unix(UNIXpath);
3373             (void) free((FREE_P *)UNIXpath);
3374             UNIXpath = (char *)NULL;
3375         }
3376         if ((ss & SB_INO)
3377         &&  (up = check_unix((INODETYPE)s->st_ino))
3378         ) {
3379
3380         /*
3381          * The inode is connected to a UNIX /proc record.
3382          *
3383          * Set the type to "unix"; enter the PCB address in the DEVICE column;
3384          * enter the inode number; and save the optional path.
3385          */
3386             if (Funix)
3387                 Lf->sf |= SELUNX;
3388             (void) snpf(Lf->type, sizeof(Lf->type), "unix");
3389             if (up->pcb)
3390                 enter_dev_ch(up->pcb);
3391             if (ss & SB_INO) {
3392                 Lf->inode = (INODETYPE)s->st_ino;
3393                 Lf->inp_ty = 1;
3394             }
3395             cp = sockty2str(up->ty, &rf);
3396             (void) snpf(Namech, Namechl - 1, "%s%stype=%s",
3397                 up->path ? up->path : "",
3398                 up->path ? " " : "",
3399                 cp);
3400             Namech[Namechl - 1] = '\0';
3401             (void) enter_nm(Namech);
3402             if (Sfile) {
3403             
3404             /*
3405              * See if this UNIX domain socket was specified as a search
3406              * argument.
3407              *
3408              * Search first by device and node numbers, if that is possible;
3409              * then search by name.
3410              */
3411                 unsigned char f = 0;            /* file-found flag */
3412
3413                 if (up->sb_def) {
3414
3415                 /*
3416                  * If the UNIX socket information includes stat(2) results, do
3417                  * a device and node number search.
3418                  *
3419                  * Note: that requires the saving, temporary modification and
3420                  *       restoration of some *Lf values.
3421                  */
3422                     unsigned char sv_dev_def;   /* saved dev_def */
3423                     unsigned char sv_inp_ty;    /* saved inp_ty */
3424                     unsigned char sv_rdev_def;  /* saved rdev_def */
3425                     dev_t sv_dev;               /* saved dev */
3426                     INODETYPE sv_inode;         /* saved inode */
3427                     dev_t sv_rdev;              /* saved rdev */
3428
3429                     sv_dev_def = Lf->dev_def;
3430                     sv_dev = Lf->dev;
3431                     sv_inode = Lf->inode;
3432                     sv_inp_ty = Lf->inp_ty;
3433                     sv_rdev_def = Lf->rdev_def;
3434                     sv_rdev = Lf->rdev;
3435                     Lf->dev_def = Lf->inp_ty = Lf->rdev_def = 1;
3436                     Lf->dev = up->sb_dev;
3437                     Lf->inode = up->sb_ino;
3438                     Lf->rdev = up->sb_rdev;
3439                     if (is_file_named(0, path, (struct mounts *)NULL, 0)) {
3440                         f = 1;
3441                         Lf->sf |= SELNM;
3442                     }
3443                     Lf->dev_def = sv_dev_def;
3444                     Lf->dev = sv_dev;
3445                     Lf->inode = sv_inode;
3446                     Lf->inp_ty = sv_inp_ty;
3447                     Lf->rdev_def = sv_rdev_def;
3448                     Lf->rdev = sv_rdev;
3449                 }
3450                 if (!f && (ss & SB_MODE)) {
3451
3452                 /*
3453                  * If the file has not yet been found and the stat buffer has
3454                  * st_mode, search for the file by full path.
3455                  */
3456                     if (is_file_named(2, path, (struct mounts *)NULL,
3457                         ((s->st_mode & S_IFMT) == S_IFCHR)) ? 1 : 0)
3458                     {
3459                         Lf->sf |= SELNM;
3460                     }
3461                 }
3462             }
3463             return;
3464         }
3465
3466 #if     defined(HASIPv6)
3467         if (Raw6path) {
3468             if (!Fxopt)
3469                 (void) get_raw6(Raw6path);
3470             (void) free((FREE_P *)Raw6path);
3471             Raw6path = (char *)NULL;
3472         }
3473         if (!Fxopt && (ss & SB_INO)
3474         &&  (rp = check_raw6((INODETYPE)s->st_ino))
3475         ) {
3476
3477         /*
3478          * The inode is connected to a raw IPv6 /proc record.
3479          *
3480          * Set the type to "raw6"; enter the inode number; store the local
3481          * address, remote address, and state in the NAME column.
3482          */
3483             (void) snpf(Lf->type, sizeof(Lf->type), "raw6");
3484             if (ss & SB_INO) {
3485                 Lf->inode = (INODETYPE)s->st_ino;
3486                 Lf->inp_ty = 1;
3487             }
3488             cp = Namech;
3489             nl = MAXPATHLEN - 2;
3490             if (rp->la && rp->lal) {
3491
3492             /*
3493              * Store the local raw IPv6 address.
3494              */
3495                 if (nl > rp->lal) {
3496                     (void) snpf(cp, nl, "%s", rp->la);
3497                     cp += rp->lal;
3498                     *cp = '\0';
3499                     nl -= rp->lal;
3500                 }
3501             }
3502             if (rp->ra && rp->ral) {
3503
3504             /*
3505              * Store the remote raw address, prefixed with "->".
3506              */
3507                 if (nl > (rp->ral + 2)) {
3508                     (void) snpf(cp, nl, "->%s", rp->ra);
3509                     cp += (rp->ral + 2);
3510                     nl -= (rp->ral + 2);
3511                 }
3512             }
3513             if (rp->sp && rp->spl) {
3514
3515             /*
3516              * Store the state, optionally prefixed by a space, in the
3517              * form "st=x...x".
3518              */
3519             
3520                 if (nl > (len = ((cp == Namech) ? 0 : 1) + 3 + rp->spl)) {
3521                     (void) snpf(cp, nl, "%sst=%s",
3522                         (cp == Namech) ? "" : " ", rp->sp);
3523                     cp += len;
3524                     *cp = '\0';
3525                     nl -= len;
3526                 }
3527             }
3528             if (Namech[0])
3529                 enter_nm(Namech);
3530             return;
3531         }
3532         if (TCP6path) {
3533             if (!Fxopt)
3534                 (void) get_tcpudp6(TCP6path, 0, 1);
3535             (void) free((FREE_P *)TCP6path);
3536             TCP6path = (char *)NULL;
3537         }
3538         if (UDP6path) {
3539             if (!Fxopt)
3540                 (void) get_tcpudp6(UDP6path, 1, 0);
3541             (void) free((FREE_P *)UDP6path);
3542             UDP6path = (char *)NULL;
3543         }
3544         if (UDPLITE6path) {
3545             if (!Fxopt)
3546                 (void) get_tcpudp6(UDPLITE6path, 2, 0);
3547             (void) free((FREE_P *)UDPLITE6path);
3548             UDPLITE6path = (char *)NULL;
3549         }
3550         if (!Fxopt && (ss & SB_INO)
3551         &&  (tp6 = check_tcpudp6((INODETYPE)s->st_ino, &pr))
3552         ) {
3553
3554         /*
3555          * The inode is connected to an IPv6 TCP or UDP /proc record.
3556          *
3557          * Set the type to "IPv6"; enter the protocol; put the inode number
3558          * in the DEVICE column in lieu of the PCB address; save the local
3559          * and foreign IPv6 addresses; save the type and protocol; and
3560          * (optionally) save the queue sizes.
3561          */
3562             i = tp6->state + TcpStOff;
3563             if (TcpStXn) {
3564
3565             /*
3566              * Check for state exclusion.
3567              */
3568                 if (i >= 0 && i < TcpNstates) {
3569                     if (TcpStX[i]) {
3570                         Lf->sf |= SELEXCLF;
3571                         return;
3572                     }
3573                 }
3574             }
3575             if (TcpStIn) {
3576
3577             /*
3578              * Check for state inclusion.
3579              */
3580                 if (i >= 0 && i < TcpNstates) {
3581                     if (TcpStI[i])
3582                         TcpStI[i] = 2;
3583                     else {
3584                         Lf->sf |= SELEXCLF;
3585                         return;
3586                    }
3587                 }
3588             }
3589             if (Fnet && (FnetTy != 4))
3590                 Lf->sf |= SELNET;
3591             (void) snpf(Lf->type, sizeof(Lf->type), "IPv6");
3592             (void) snpf(Lf->iproto, sizeof(Lf->iproto), "%.*s", IPROTOL-1, pr);
3593             Lf->inp_ty = 2;
3594             if (ss & SB_INO) {
3595                 (void) snpf(tbuf, sizeof(tbuf), InodeFmt_d,
3596                     (INODETYPE)s->st_ino);
3597                 tbuf[sizeof(tbuf) - 1] = '\0';
3598                 enter_dev_ch(tbuf);
3599             }
3600             af = AF_INET6;
3601             if (!IN6_IS_ADDR_UNSPECIFIED(&tp6->faddr) || tp6->fport)
3602                 fa = (unsigned char *)&tp6->faddr;
3603             else
3604                 fa = (unsigned char *)NULL;
3605             if (!IN6_IS_ADDR_UNSPECIFIED(&tp6->laddr) || tp6->lport)
3606                 la = (unsigned char *)&tp6->laddr;
3607             else
3608                 la = (unsigned char *)NULL;
3609             if ((fa && IN6_IS_ADDR_V4MAPPED(&tp6->faddr))
3610             ||  (la && IN6_IS_ADDR_V4MAPPED(&tp6->laddr))) {
3611                 af = AF_INET;
3612                 if (fa)
3613                     fa += 12;
3614                 if (la)
3615                     la += 12;
3616             }
3617             ent_inaddr(la, tp6->lport, fa, tp6->fport, af);
3618             Lf->lts.type = tp6->proto;
3619             Lf->lts.state.i = tp6->state;
3620
3621 #if     defined(HASTCPTPIQ)
3622             Lf->lts.rq = tp6->rxq;
3623             Lf->lts.sq = tp6->txq;
3624             Lf->lts.rqs = Lf->lts.sqs = 1;
3625 #endif  /* defined(HASTCPTPIQ) */
3626
3627             return;
3628         }
3629 #endif  /* defined(HASIPv6) */
3630
3631         if (TCPpath) {
3632             if (!Fxopt)
3633                 (void) get_tcpudp(TCPpath, 0, 1);
3634             (void) free((FREE_P *)TCPpath);
3635             TCPpath = (char *)NULL;
3636         }
3637         if (UDPpath) {
3638             if (!Fxopt)
3639                 (void) get_tcpudp(UDPpath, 1, 0);
3640             (void) free((FREE_P *)UDPpath);
3641             UDPpath = (char *)NULL;
3642         }
3643         if (UDPLITEpath) {
3644             if (!Fxopt)
3645                 (void) get_tcpudp(UDPLITEpath, 2, 0);
3646             (void) free((FREE_P *)UDPLITEpath);
3647             UDPLITEpath = (char *)NULL;
3648         }
3649         if (!Fxopt && (ss & SB_INO)
3650         &&  (tp = check_tcpudp((INODETYPE)s->st_ino, &pr))
3651         ) {
3652
3653         /*
3654          * The inode is connected to an IPv4 TCP or UDP /proc record.
3655          *
3656          * Set the type to "inet" or "IPv4"; enter the protocol; put the
3657          * inode number in the DEVICE column in lieu of the PCB address;
3658          * save the local and foreign IPv4 addresses; save the type and
3659          * protocol; and (optionally) save the queue sizes.
3660          */
3661             i = tp->state + TcpStOff;
3662             if (TcpStXn) {
3663
3664             /*
3665              * Check for state exclusion.
3666              */
3667                 if (i >= 0 && i < TcpNstates) {
3668                     if (TcpStX[i]) {
3669                         Lf->sf |= SELEXCLF;
3670                         return;
3671                     }
3672                 }
3673             }
3674             if (TcpStIn) {
3675
3676             /*
3677              * Check for state inclusion.
3678              */
3679                 if (i >= 0 && i < TcpNstates) {
3680                     if (TcpStI[i])
3681                         TcpStI[i] = 2;
3682                     else {
3683                         Lf->sf |= SELEXCLF;
3684                         return;
3685                     }
3686                 }
3687             }
3688             if (Fnet && (FnetTy != 6))
3689                 Lf->sf |= SELNET;
3690
3691 #if     defined(HASIPv6)
3692             (void) snpf(Lf->type, sizeof(Lf->type), "IPv4");
3693 #else   /* !defined(HASIPv6) */
3694             (void) snpf(Lf->type, sizeof(Lf->type), "inet");
3695 #endif  /* defined(HASIPv6) */
3696
3697             (void) snpf(Lf->iproto, sizeof(Lf->iproto), "%.*s", IPROTOL-1, pr);
3698             Lf->inp_ty = 2;
3699             if (ss & SB_INO) {
3700                 (void) snpf(tbuf, sizeof(tbuf), InodeFmt_d,
3701                     (INODETYPE)s->st_ino);
3702                 tbuf[sizeof(tbuf) - 1] = '\0';
3703                 enter_dev_ch(tbuf);
3704             }
3705             if (tp->faddr || tp->fport) {
3706                 fs.s_addr = tp->faddr;
3707                 fa = (unsigned char *)&fs;
3708             } else
3709                 fa = (unsigned char *)NULL;
3710             if (tp->laddr || tp->lport) {
3711                 ls.s_addr = tp->laddr;
3712                 la = (unsigned char *)&ls;
3713             } else
3714                 la = (unsigned char *)NULL;
3715             ent_inaddr(la, tp->lport, fa, tp->fport, AF_INET);
3716             Lf->lts.type = tp->proto;
3717             Lf->lts.state.i = tp->state;
3718
3719 #if     defined(HASTCPTPIQ)
3720             Lf->lts.rq = tp->rxq;
3721             Lf->lts.sq = tp->txq;
3722             Lf->lts.rqs = Lf->lts.sqs = 1;
3723 #endif  /* defined(HASTCPTPIQ) */
3724
3725             return;
3726         }
3727         if (SCTPPath[0]) {
3728             (void) get_sctp();
3729             for (i = 0; i < NSCTPPATHS; i++) {
3730                 (void) free((FREE_P *)SCTPPath[i]);
3731                 SCTPPath[i] = (char *)NULL;
3732             }
3733         }
3734         if ((ss & SB_INO) && (sp = check_sctp((INODETYPE)s->st_ino))
3735         ) {
3736
3737         /*
3738          * The inode is connected to an SCTP /proc record.
3739          *
3740          * Set the type to "sock"; enter the inode number in the DEVICE
3741          * column; set the protocol to SCTP; and fill in the NAME column
3742          * with ASSOC, ASSOC-ID, ENDPT, LADDRS, LPORT, RADDRS and RPORT.
3743          */
3744             (void) snpf(Lf->type, sizeof(Lf->type), "sock");
3745             (void) snpf(Lf->iproto, sizeof(Lf->iproto), "%.*s", IPROTOL-1,
3746                 "SCTP");
3747             Lf->inp_ty = 2;
3748             (void) snpf(tbuf, sizeof(tbuf), InodeFmt_d, (INODETYPE)s->st_ino);
3749             tbuf[sizeof(tbuf) - 1] = '\0';
3750             enter_dev_ch(tbuf);
3751             Namech[0] = '\0';
3752             if  (sp->type == 1) {
3753
3754             /*
3755              * This is an ENDPT SCTP file.
3756              */
3757                 (void) snpf(Namech, Namechl,
3758                     "ENDPT: %s%s%s%s%s%s",
3759                     sp->addr ? sp->addr : "",
3760                     (sp->laddrs || sp->lport) ? " " : "",
3761                     sp->laddrs ? sp->laddrs : "",
3762                     sp->lport ? "[" : "", 
3763                     sp->lport ? sp->lport : "", 
3764                     sp->lport ? "]" : ""
3765                  ); 
3766             } else {
3767
3768             /*
3769              * This is an ASSOC, or ASSOC and ENDPT socket file.
3770              */
3771                 (void) snpf(Namech, Namechl,
3772                     "%s: %s%s%s %s%s%s%s%s%s%s%s%s",
3773                     sp->type ? "ASSOC+ENDPT" : "ASSOC",
3774                     sp->addr ? sp->addr : "",
3775                     (sp->addr && sp->assocID) ? "," : "",
3776                     sp->assocID ? sp->assocID : "",
3777                     sp->laddrs ? sp->laddrs : "",
3778                     sp->lport ? "[" : "", 
3779                     sp->lport ? sp->lport : "", 
3780                     sp->lport ? "]" : "", 
3781                     ((sp->laddrs || sp->lport) && (sp->raddrs || sp->rport))
3782                         ? "<->" : "",
3783                     sp->raddrs ? sp->raddrs : "",
3784                     sp->rport ? "[" : "", 
3785                     sp->rport ? sp->rport : "", 
3786                     sp->rport ? "]" : ""
3787                  ); 
3788             }
3789             if (Namech[0])
3790                 enter_nm(Namech);
3791             return;
3792         }
3793         if (ICMPpath) {
3794             (void) get_icmp(ICMPpath);
3795             (void) free((FREE_P *)ICMPpath);
3796             ICMPpath = (char *)NULL;
3797         }
3798         if ((ss & SB_INO)
3799         &&  (icmpp = check_icmp((INODETYPE)s->st_ino))
3800         ) {
3801
3802         /*
3803          * The inode is connected to an ICMP /proc record.
3804          *
3805          * Set the type to "icmp" and store the type in the NAME
3806          * column.  Save the inode number.
3807          */
3808             (void) snpf(Lf->type, sizeof(Lf->type), "icmp");
3809             Lf->inode = (INODETYPE)s->st_ino;
3810             Lf->inp_ty = 1;
3811             cp = Namech;
3812             nl = Namechl- 2;
3813             *cp = '\0';
3814             if (icmpp->la && icmpp->lal) {
3815
3816             /*
3817              * Store the local raw address.
3818              */
3819                 if (nl > icmpp->lal) {
3820                     (void) snpf(cp, nl, "%s", icmpp->la);
3821                     cp += icmpp->lal;
3822                     *cp = '\0';
3823                     nl -= icmpp->lal;
3824                 }
3825             }
3826             if (icmpp->ra && icmpp->ral) {
3827
3828             /*
3829              * Store the remote raw address, prefixed with "->".
3830              */
3831                 if (nl > (icmpp->ral + 2)) {
3832                     (void) snpf(cp, nl, "->%s", icmpp->ra);
3833                     cp += (icmpp->ral + 2);
3834                     *cp = '\0';
3835                     nl -= (icmpp->ral + 2);
3836                 }
3837             }
3838             if (Namech[0])
3839                 enter_nm(Namech);
3840             return;
3841         }
3842 /*
3843  * The socket's protocol can't be identified.
3844  */
3845         (void) snpf(Lf->type, sizeof(Lf->type), "sock");
3846         if (ss & SB_INO) {
3847             Lf->inode = (INODETYPE)s->st_ino;
3848             Lf->inp_ty = 1;
3849         }
3850         if (ss & SB_DEV) {
3851             Lf->dev = s->st_dev;
3852             Lf->dev_def = 1;
3853         }
3854         if (Fxopt)
3855             enter_nm("can't identify protocol (-X specified)");
3856         else {
3857             (void) snpf(Namech, Namechl, "protocol: ");
3858             if (!prp) {
3859                 i = (int)strlen(Namech);
3860                 prp = &Namech[i];
3861                 sz = (ssize_t)(Namechl - i - 1);
3862             }
3863             if ((getxattr(pbr, "system.sockprotoname", prp, sz)) < 0) 
3864                 enter_nm("can't identify protocol");
3865             else
3866                 enter_nm(Namech);
3867         }
3868 }
3869
3870
3871 /*
3872  * set_net_paths() - set /proc/net paths
3873  */
3874
3875 void
3876 set_net_paths(p, pl)
3877         char *p;                        /* path to /proc/net/ */
3878         int pl;                         /* strlen(p) */
3879 {
3880         int i;
3881         int pathl;
3882
3883         pathl = 0;
3884         (void) make_proc_path(p, pl, &AX25path, &pathl, "ax25");
3885         pathl = 0;
3886         (void) make_proc_path(p, pl, &ICMPpath, &pathl, "icmp");
3887         pathl = 0;
3888         (void) make_proc_path(p, pl, &Ipxpath, &pathl, "ipx");
3889         pathl = 0;
3890         (void) make_proc_path(p, pl, &Nlkpath, &pathl, "netlink");
3891         pathl = 0;
3892         (void) make_proc_path(p, pl, &Packpath, &pathl, "packet");
3893         pathl = 0;
3894         (void) make_proc_path(p, pl, &Rawpath, &pathl, "raw");
3895         for (i = 0; i < NSCTPPATHS; i++) {
3896             pathl = 0;
3897             (void) make_proc_path(p, pl, &SCTPPath[i], &pathl, SCTPSfx[i]);
3898         }
3899         pathl = 0;
3900         (void) make_proc_path(p, pl, &SockStatPath, &pathl, "sockstat");
3901         pathl = 0;
3902         (void) make_proc_path(p, pl, &TCPpath, &pathl, "tcp");
3903         pathl = 0;
3904         (void) make_proc_path(p, pl, &UDPpath, &pathl, "udp");
3905         pathl = 0;
3906         (void) make_proc_path(p, pl, &UDPLITEpath, &pathl, "udplite");
3907
3908 #if     defined(HASIPv6)
3909         pathl = 0;
3910         (void) make_proc_path(p, pl, &Raw6path, &pathl, "raw6");
3911         pathl = 0;
3912         (void) make_proc_path(p, pl, &SockStatPath6, &pathl, "sockstat6");
3913         pathl = 0;
3914         (void) make_proc_path(p, pl, &TCP6path, &pathl, "tcp6");
3915         pathl = 0;
3916         (void) make_proc_path(p, pl, &UDP6path, &pathl, "udp6");
3917         pathl = 0;
3918         (void) make_proc_path(p, pl, &UDPLITE6path, &pathl, "udplite6");
3919 #endif  /* defined(HASIPv6) */
3920
3921         pathl = 0;
3922         (void) make_proc_path(p, pl, &UNIXpath, &pathl, "unix");
3923 }
3924
3925
3926 /*
3927  * Sockty2str() -- convert socket type number to a string
3928  */
3929
3930 static char *
3931 sockty2str(ty, rf)
3932         uint32_t ty;                    /* socket type number */
3933         int *rf;                        /* result flag: 0 == known
3934                                          *              1 = unknown */
3935 {
3936         int f = 0;                      /* result flag */
3937         char *sr;                       /*string result */
3938
3939         switch (ty) {
3940
3941 #if     defined(SOCK_STREAM)
3942         case SOCK_STREAM:
3943             sr = "STREAM";
3944             break;
3945 #endif  /* defined(SOCK_STREAM) */
3946
3947 #if     defined(SOCK_DGRAM)
3948         case SOCK_DGRAM:
3949             sr = "DGRAM";
3950             break;
3951 #endif  /* defined(SOCK_DGRAM) */
3952
3953 #if     defined(SOCK_RAW)
3954         case SOCK_RAW:
3955             sr = "RAW";
3956             break;
3957 #endif  /* defined(SOCK_RAW) */
3958
3959 #if     defined(SOCK_RDM)
3960         case SOCK_RDM:
3961             sr = "RDM";
3962             break;
3963 #endif  /* defined(SOCK_RDM) */
3964
3965 #if     defined(SOCK_SEQPACKET)
3966         case SOCK_SEQPACKET:
3967             sr = "SEQPACKET";
3968             break;
3969 #endif  /* defined(SOCK_SEQPACKET) */
3970
3971 #if     defined(SOCK_PACKET)
3972         case SOCK_PACKET:
3973             sr = "PACKET";
3974             break;
3975 #endif  /* defined(SOCK_PACKET) */
3976
3977         default:
3978             f = 1;
3979             sr = "unknown";
3980         }
3981         *rf = f;
3982         return(sr);
3983 }