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