2 * dsock.c - Linux socket processing functions for /proc-based lsof
7 * Copyright 1997 Purdue Research Foundation, West Lafayette, Indiana
8 * 47907. All rights reserved.
10 * Written by Victor A. Abell
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.
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:
19 * 1. Neither the authors nor Purdue University are responsible for any
20 * consequences of the use of this software.
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.
26 * 3. Altered versions must be plainly marked as such, and must not be
27 * misrepresented as being the original software.
29 * 4. This notice may not be removed or altered.
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 $";
40 #include <sys/xattr.h>
47 #define INOBUCKS 128 /* inode hash bucket count -- must be
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))
58 struct ax25sin { /* AX25 socket information */
59 char *da; /* destination address */
60 char *dev_ch; /* device characters */
61 char *sa; /* source address */
63 unsigned long sq, rq; /* send and receive queue values */
64 unsigned char sqs, rqs; /* send and receive queue states */
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) */
78 struct ipxsin { /* IPX socket information */
80 char *la; /* local address */
81 char *ra; /* remote address */
83 unsigned long txq, rxq; /* transmit and receive queue values */
87 struct nlksin { /* Netlink socket information */
88 INODETYPE inode; /* node number */
89 unsigned int pr; /* protocol */
93 struct packin { /* packet information */
95 int ty; /* socket type */
96 int pr; /* protocol */
100 struct rawsin { /* raw socket information */
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) */
111 struct sctpsin { /* SCTP socket information */
113 int type; /* type: 0 = assoc
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;
125 struct tcp_udp { /* IPv4 TCP and UDP socket
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;
137 struct tcp_udp6 { /* IPv6 TCP and UDP socket
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;
147 #endif /* defined(HASIPv6) */
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 */
162 * Local static values
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[] = {
172 "ESTABLISHED", /* 3 */
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
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
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 */
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 */
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
210 static int TcpUdp_bucks = 0; /* dynamically sized hash bucket
211 * count for TCP and UDP -- will
212 * be a power of two */
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
219 static char *SockStatPath6 = (char *)NULL;
220 /* path to /proc/net IPv6 socket
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
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
233 #endif /* defined(HASIPv6) */
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 */
244 * Local function prototypes
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));
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) */
280 * build_IPstates() -- build the TCP and UDP state tables
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);
305 * check_ax25() - check for AX25 socket file
308 static struct ax25sin *
310 INODETYPE i; /* socket file's inode number */
316 for (ap = AX25sin[h]; ap; ap = ap->next) {
320 return((struct ax25sin *)NULL);
326 * check_icmp() - check for ICMP socket
329 static struct icmpin *
331 INODETYPE i; /* socket file's inode number */
334 struct icmpin *icmpp;
337 for (icmpp = Icmpin[h]; icmpp; icmpp = icmpp->next) {
338 if (i == icmpp->inode)
341 return((struct icmpin *)NULL);
346 * check_ipx() - check for IPX socket file
349 static struct ipxsin *
351 INODETYPE i; /* socket file's inode number */
357 for (ip = Ipxsin[h]; ip; ip = ip->next) {
361 return((struct ipxsin *)NULL);
366 * check_netlink() - check for Netlink socket file
369 static struct nlksin *
371 INODETYPE i; /* socket file's inode number */
377 for (lp = Nlksin[h]; lp; lp = lp->next) {
381 return((struct nlksin *)NULL);
386 * check_pack() - check for packet file
389 static struct packin *
391 INODETYPE i; /* packet file's inode number */
397 for (pp = Packin[h]; pp; pp = pp->next) {
401 return((struct packin *)NULL);
406 * check_raw() - check for raw socket file
409 static struct rawsin *
411 INODETYPE i; /* socket file's inode number */
417 for (rp = Rawsin[h]; rp; rp = rp->next) {
421 return((struct rawsin *)NULL);
426 * check_sctp() - check for SCTP socket file
429 static struct sctpsin *
431 INODETYPE i; /* socket file's inode number */
437 for (sp = SCTPsin[h]; sp; sp = sp->next) {
441 return((struct sctpsin *)NULL);
446 * check_tcpudp() - check for IPv4 TCP or UDP socket file
449 static struct tcp_udp *
451 INODETYPE i; /* socket file's inode number */
452 char **p; /* protocol return */
458 for (tp = TcpUdp[h]; tp; tp = tp->next) {
459 if (i == tp->inode) {
476 return((struct tcp_udp *)NULL);
482 * check_raw6() - check for raw IPv6 socket file
485 static struct rawsin *
487 INODETYPE i; /* socket file's inode number */
493 for (rp = Rawsin6[h]; rp; rp = rp->next) {
497 return((struct rawsin *)NULL);
502 * check_tcpudp6() - check for IPv6 TCP or UDP socket file
505 static struct tcp_udp6 *
507 INODETYPE i; /* socket file's inode number */
508 char **p; /* protocol return */
511 struct tcp_udp6 *tp6;
514 for (tp6 = TcpUdp6[h]; tp6; tp6 = tp6->next) {
515 if (i == tp6->inode) {
516 switch (tp6->proto) {
532 return((struct tcp_udp6 *)NULL);
534 #endif /* defined(HASIPv6) */
538 * check_unix() - check for UNIX domain socket
541 static struct uxsin *
543 INODETYPE i; /* socket file's inode number */
549 for (up = Uxsin[h]; up; up = up->next) {
553 return((struct uxsin *)NULL);
558 * get_ax25() - get /proc/net/ax25 info
563 char *p; /* /proc/net/ipx path */
565 struct ax25sin *ap, *np;
567 char buf[MAXPATHLEN], *da, *dev_ch, *ep, **fp, *sa;
570 unsigned long rq, sq, state;
572 unsigned char rqs, sqs;
573 static char *vbuf = (char *)NULL;
574 static size_t vsz = (size_t)0;
576 * Do second time cleanup or first time setup.
579 for (h = 0; h < INOBUCKS; h++) {
580 for (ap = AX25sin[h]; ap; ap = np) {
583 (void) free((FREE_P *)ap->da);
585 (void) free((FREE_P *)ap->dev_ch);
587 (void) free((FREE_P *)ap->sa);
588 (void) free((FREE_P *)ap);
590 AX25sin[h] = (struct ax25sin *)NULL;
593 AX25sin = (struct ax25sin **)calloc(INOBUCKS,
594 sizeof(struct ax25sin *));
596 (void) fprintf(stderr,
597 "%s: can't allocate %d AX25 hash pointer bytes\n",
598 Pn, (int)(INOBUCKS * sizeof(struct ax25sin *)));
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.
606 if (!(as = open_proc_stream(p, "r", &vbuf, &vsz, 0)))
608 while (fgets(buf, sizeof(buf) - 1, as)) {
609 if ((nf = get_fields(buf, (char *)NULL, &fp, (int *)NULL, 0)) < 24)
612 * /proc/net/ax25 has no title line, a very poor deficiency in its
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:
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 \
622 * The code in this function is forced to assume that format is in
627 * Assemble the inode number and see if it has already been recorded.
628 * If it has, skip this line.
631 if (!fp[23] || !*fp[23]
632 || (inode = strtoull(fp[23], &ep, 0)) == ULONG_MAX
635 h = INOHASH((INODETYPE)inode);
636 for (ap = AX25sin[h]; ap; ap = ap->next) {
637 if (inode == ap->inode)
643 * Assemble the send and receive queue values and the state.
645 rq = sq = (unsigned long)0;
646 rqs = sqs = (unsigned char)0;
648 if (!fp[21] || !*fp[21]
649 || (sq = strtoul(fp[21], &ep, 0)) == ULONG_MAX || !ep || *ep)
651 sqs = (unsigned char)1;
653 if (!fp[22] || !*fp[22]
654 || (rq = strtoul(fp[22], &ep, 0)) == ULONG_MAX || !ep || *ep)
656 rqs = (unsigned char)1;
658 if (!fp[4] || !*fp[4]
659 || (state = strtoul(fp[4], &ep, 0)) == ULONG_MAX || !ep || *ep)
662 * Allocate space for the destination address.
664 if (!fp[3] || !*fp[3])
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]);
673 (void) snpf(da, len + 1, "%s", fp[3]);
677 * Allocate space for the source address.
679 if (!fp[2] || !*fp[2])
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]);
688 (void) snpf(sa, len + 1, "%s", fp[2]);
692 * Allocate space for the device characters.
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]);
703 (void) snpf(dev_ch, len + 1, "%s", fp[1]);
705 dev_ch = (char *)NULL;
707 * Allocate space for an ax25sin entry, fill it, and link it to its
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));
724 ap->state = (int)state;
725 ap->next = AX25sin[h];
733 * get_icmp() - get ICMP net info
738 char *p; /* /proc/net/icmp path */
740 char buf[MAXPATHLEN], *ep, **fp, *la, *ra;
744 struct icmpin *np, *icmpp;
746 MALLOC_S lal, ral, spl;
747 static char *vbuf = (char *)NULL;
748 static size_t vsz = (size_t)0;
751 * Do second time cleanup or first time setup.
754 for (h = 0; h < INOBUCKS; h++) {
755 for (icmpp = Icmpin[h]; icmpp; icmpp = np) {
757 (void) free((FREE_P *)icmpp);
759 Icmpin[h] = (struct icmpin *)NULL;
762 Icmpin = (struct icmpin **)calloc(INOBUCKS,
763 sizeof(struct icmpin *));
765 (void) fprintf(stderr,
766 "%s: can't allocate %d icmp hash pointer bytes\n",
767 Pn, (int)(INOBUCKS * sizeof(struct icmpin *)));
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.
775 if (!(xs = open_proc_stream(p, "r", &vbuf, &vsz, 0)))
777 while (fgets(buf, sizeof(buf) - 1, xs)) {
778 if (get_fields(buf, (char *)NULL, &fp, (int *)NULL, 0) < 11)
783 * Check the column labels in the first line.
786 * In column header, "inode" is at the 11th column.
787 * However, in data rows, inode appears at the 9th column.
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 ":".
793 if (!fp[1] || strcmp(fp[1], "local_address")
794 || !fp[2] || strcmp(fp[2], "rem_address")
795 || !fp[11] || strcmp(fp[11], "inode"))
798 (void) fprintf(stderr,
799 "%s: WARNING: unsupported format: %s\n",
808 * Assemble the inode number and see if the inode is already
812 if (!fp[9] || !*fp[9]
813 || (inode = strtoull(fp[9], &ep, 0)) == ULONG_MAX
817 for (icmpp = Icmpin[h]; icmpp; icmpp = icmpp->next) {
818 if (inode == icmpp->inode)
824 * Save the local address, and remote address.
826 if (!fp[1] || !*fp[1] || (lal = strlen(fp[1])) < 1) {
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]);
836 (void) snpf(la, lal + 1, "%s", fp[1]);
838 if (!fp[2] || !*fp[2] || (ral = strlen(fp[2])) < 1) {
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]);
848 (void) snpf(ra, ral + 1, "%s", fp[2]);
851 * Allocate space for a icmpin entry, fill it, and link it to its
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));
860 icmpp->inode = inode;
865 icmpp->next = Icmpin[h];
874 * get_ipx() - get /proc/net/ipx info
879 char *p; /* /proc/net/ipx path */
881 char buf[MAXPATHLEN], *ep, **fp, *la, *ra;
885 unsigned long rxq, state, txq;
886 struct ipxsin *ip, *np;
888 static char *vbuf = (char *)NULL;
889 static size_t vsz = (size_t)0;
892 * Do second time cleanup or first time setup.
895 for (h = 0; h < INOBUCKS; h++) {
896 for (ip = Ipxsin[h]; ip; ip = np) {
899 (void) free((FREE_P *)ip->la);
901 (void) free((FREE_P *)ip->ra);
902 (void) free((FREE_P *)ip);
904 Ipxsin[h] = (struct ipxsin *)NULL;
907 Ipxsin = (struct ipxsin **)calloc(INOBUCKS,
908 sizeof(struct ipxsin *));
910 (void) fprintf(stderr,
911 "%s: can't allocate %d IPX hash pointer bytes\n",
912 Pn, (int)(INOBUCKS * sizeof(struct ipxsin *)));
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.
920 if (!(xs = open_proc_stream(p, "r", &vbuf, &vsz, 0)))
922 while (fgets(buf, sizeof(buf) - 1, xs)) {
923 if (get_fields(buf, (char *)NULL, &fp, (int *)NULL, 0) < 7)
928 * Check the column labels in the first line.
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"))
939 (void) fprintf(stderr,
940 "%s: WARNING: unsupported format: %s\n",
949 * Assemble the inode number and see if the inode is already
953 if (!fp[6] || !*fp[6]
954 || (inode = strtoull(fp[6], &ep, 0)) == ULONG_MAX
958 for (ip = Ipxsin[h]; ip; ip = ip->next) {
959 if (inode == ip->inode)
965 * Assemble the transmit and receive queue values and the state.
968 if (!fp[2] || !*fp[2]
969 || (txq = strtoul(fp[2], &ep, 16)) == ULONG_MAX || !ep || *ep)
972 if (!fp[3] || !*fp[3]
973 || (rxq = strtoul(fp[3], &ep, 16)) == ULONG_MAX || !ep || *ep)
976 if (!fp[4] || !*fp[4]
977 || (state = strtoul(fp[4], &ep, 16)) == ULONG_MAX || !ep || *ep)
980 * Allocate space for the local address, unless it is "Not_Connected".
982 if (!fp[0] || !*fp[0] || strcmp(fp[0], "Not_Connected") == 0)
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]);
991 (void) snpf(la, len + 1, "%s", fp[0]);
995 * Allocate space for the remote address, unless it is "Not_Connected".
997 if (!fp[1] || !*fp[1] || strcmp(fp[1], "Not_Connected") == 0)
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]);
1006 (void) snpf(ra, len + 1, "%s", fp[1]);
1010 * Allocate space for an ipxsin entry, fill it, and link it to its
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));
1024 ip->state = (int)state;
1025 ip->next = Ipxsin[h];
1033 * get_netlink() - get /proc/net/netlink info
1038 char *p; /* /proc/net/netlink path */
1040 char buf[MAXPATHLEN], *ep, **fp;
1044 struct nlksin *np, *lp;
1045 static char *vbuf = (char *)NULL;
1046 static size_t vsz = (size_t)0;
1049 * Do second time cleanup or first time setup.
1052 for (h = 0; h < INOBUCKS; h++) {
1053 for (lp = Nlksin[h]; lp; lp = np) {
1055 (void) free((FREE_P *)lp);
1057 Nlksin[h] = (struct nlksin *)NULL;
1060 Nlksin = (struct nlksin **)calloc(INOBUCKS,sizeof(struct nlksin *));
1062 (void) fprintf(stderr,
1063 "%s: can't allocate %d netlink hash pointer bytes\n",
1064 Pn, (int)(INOBUCKS * sizeof(struct nlksin *)));
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.
1072 if (!(xs = open_proc_stream(p, "r", &vbuf, &vsz, 0)))
1074 while (fgets(buf, sizeof(buf) - 1, xs)) {
1075 if (get_fields(buf, (char *)NULL, &fp, (int *)NULL, 0) < 10)
1080 * Check the column labels in the first line.
1082 if (!fp[1] || strcmp(fp[1], "Eth")
1083 || !fp[9] || strcmp(fp[9], "Inode"))
1086 (void) fprintf(stderr,
1087 "%s: WARNING: unsupported format: %s\n",
1096 * Assemble the inode number and see if the inode is already
1100 if (!fp[9] || !*fp[9]
1101 || (inode = strtoull(fp[9], &ep, 0)) == ULONG_MAX
1105 for (lp = Nlksin[h]; lp; lp = lp->next) {
1106 if (inode == lp->inode)
1112 * Save the protocol from the Eth column.
1114 if (!fp[1] || !*fp[1] || (strlen(fp[1])) < 1)
1118 * Allocate space for a nlksin entry, fill it, and link it to its
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));
1129 lp->next = Nlksin[h];
1137 * get_pack() - get /proc/net/packet info
1142 char *p; /* /proc/net/raw path */
1144 char buf[MAXPATHLEN], *ep, **fp;
1148 struct packin *np, *pp;
1150 static char *vbuf = (char *)NULL;
1151 static size_t vsz = (size_t)0;
1154 * Do second time cleanup or first time setup.
1157 for (h = 0; h < INOBUCKS; h++) {
1158 for (pp = Packin[h]; pp; pp = np) {
1160 (void) free((FREE_P *)pp);
1162 Packin[h] = (struct packin *)NULL;
1165 Packin = (struct packin **)calloc(INOBUCKS,
1166 sizeof(struct packin *));
1168 (void) fprintf(stderr,
1169 "%s: can't allocate %d packet hash pointer bytes\n",
1170 Pn, (int)(INOBUCKS * sizeof(struct packin *)));
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.
1178 if (!(xs = open_proc_stream(p, "r", &vbuf, &vsz, 0)))
1180 while (fgets(buf, sizeof(buf) - 1, xs)) {
1181 if (get_fields(buf, (char *)NULL, &fp, (int *)NULL, 0) < 9)
1186 * Check the column labels in the first line.
1188 if (!fp[2] || strcmp(fp[2], "Type")
1189 || !fp[3] || strcmp(fp[3], "Proto")
1190 || !fp[8] || strcmp(fp[8], "Inode"))
1193 (void) fprintf(stderr,
1194 "%s: WARNING: unsupported format: %s\n",
1203 * Assemble the inode number and see if the inode is already
1207 if (!fp[8] || !*fp[8]
1208 || (inode = strtoull(fp[8], &ep, 0)) == ULONG_MAX
1212 for (pp = Packin[h]; pp; pp = pp->next) {
1213 if (inode == pp->inode)
1219 * Save the socket type and protocol.
1221 if (!fp[2] || !*fp[2] || (strlen(fp[2])) < 1)
1225 if (!fp[3] || !*fp[3] || (strlen(fp[3]) < 1)
1226 || ((pr = strtoul(fp[3], &ep, 16)) == ULONG_MAX) || !ep || *ep)
1229 * Allocate space for a packin entry, fill it, and link it to its
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));
1241 pp->next = Packin[h];
1249 * get_raw() - get /proc/net/raw info
1254 char *p; /* /proc/net/raw path */
1256 char buf[MAXPATHLEN], *ep, **fp, *la, *ra, *sp;
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;
1266 * Do second time cleanup or first time setup.
1269 for (h = 0; h < INOBUCKS; h++) {
1270 for (rp = Rawsin[h]; rp; rp = np) {
1273 (void) free((FREE_P *)rp->la);
1275 (void) free((FREE_P *)rp->ra);
1276 (void) free((FREE_P *)rp);
1278 Rawsin[h] = (struct rawsin *)NULL;
1281 Rawsin = (struct rawsin **)calloc(INOBUCKS,
1282 sizeof(struct rawsin *));
1284 (void) fprintf(stderr,
1285 "%s: can't allocate %d raw hash pointer bytes\n",
1286 Pn, (int)(INOBUCKS * sizeof(struct rawsin *)));
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.
1294 if (!(xs = open_proc_stream(p, "r", &vbuf, &vsz, 0)))
1296 while (fgets(buf, sizeof(buf) - 1, xs)) {
1297 if (get_fields(buf, (char *)NULL, &fp, (int *)NULL, 0) < nf)
1302 * Check the column labels in the first line.
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"))
1310 (void) fprintf(stderr,
1311 "%s: WARNING: unsupported format: %s\n",
1320 * Assemble the inode number and see if the inode is already
1324 if (!fp[9] || !*fp[9]
1325 || (inode = strtoull(fp[9], &ep, 0)) == ULONG_MAX
1329 for (rp = Rawsin[h]; rp; rp = rp->next) {
1330 if (inode == rp->inode)
1336 * Save the local address, remote address, and state.
1338 if (!fp[1] || !*fp[1] || (lal = strlen(fp[1])) < 1) {
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]);
1348 (void) snpf(la, lal + 1, "%s", fp[1]);
1350 if (!fp[2] || !*fp[2] || (ral = strlen(fp[2])) < 1) {
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]);
1360 (void) snpf(ra, ral + 1, "%s", fp[2]);
1362 if (!fp[3] || !*fp[3] || (spl = strlen(fp[3])) < 1) {
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]);
1372 (void) snpf(sp, spl + 1, "%s", fp[3]);
1375 * Allocate space for an rawsin entry, fill it, and link it to its
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));
1391 rp->next = Rawsin[h];
1399 * get_sctp() - get /proc/net/sctp/assocs info
1405 char buf[MAXPATHLEN], *a, *ep, **fp, *id, *la, *lp, *ra, *rp, *ta;
1406 int d, err, fl, h, i, j, nf, ty, x;
1409 struct sctpsin *sp, *np;
1411 static char *vbuf = (char *)NULL;
1412 static size_t vsz = (size_t)0;
1414 * Do second time cleanup or first time setup.
1417 for (h = 0; h < INOBUCKS; h++) {
1418 for (sp = SCTPsin[h]; sp; sp = np) {
1421 (void) free((FREE_P *)sp->addr);
1423 (void) free((FREE_P *)sp->assocID);
1425 (void) free((FREE_P *)sp->lport);
1427 (void) free((FREE_P *)sp->rport);
1429 (void) free((FREE_P *)sp->laddrs);
1431 (void) free((FREE_P *)sp->raddrs);
1432 (void) free((FREE_P *)sp);
1434 SCTPsin[h] = (struct sctpsin *)NULL;
1437 SCTPsin = (struct sctpsin **)calloc(INOBUCKS,
1438 sizeof(struct sctpsin *));
1440 (void) fprintf(stderr,
1441 "%s: can't allocate %d SCTP hash pointer bytes\n",
1442 Pn, (int)(INOBUCKS * sizeof(struct sctpsin *)));
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.
1450 for (i = 0; i < NSCTPPATHS; i++ ) {
1451 if (!(ss = open_proc_stream(SCTPPath[i], "r", &vbuf, &vsz, 0)))
1454 while (fgets(buf, sizeof(buf) - 1, ss)) {
1455 if ((nf = get_fields(buf, (char *)NULL, &fp, (int *)NULL, 0))
1463 * Check the column labels in the first line.
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")
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")
1491 (void) fprintf(stderr,
1492 "%s: WARNING: unsupported format: %s\n",
1500 * Assemble the inode number and see if it has already been
1505 if (!fp[j] || !*fp[j]
1506 || (inode = strtoull(fp[j], &ep, 0)) == ULONG_MAX
1509 h = INOHASH((INODETYPE)inode);
1510 for (sp = SCTPsin[h]; sp; sp = sp->next) {
1511 if (inode == sp->inode)
1515 * Set the entry type.
1518 ty = (sp->type == i) ? i : 3;
1522 * Allocate space for this line's sctpsin members.
1524 * The association or endpoint address is in the first field.
1526 a = sp ? sp->addr : (char *)NULL;
1527 if (fp[0] && *fp[0] && (len = strlen(fp[0]))) {
1529 if (isainb(fp[0], a)) {
1531 a = (char *)realloc((MALLOC_P *)a, plen + len + 2);
1537 a = (char *)malloc(len + 1);
1541 (void) fprintf(stderr,
1542 "%s: can't allocate %d SCTP ASSOC bytes: %s\n",
1543 Pn, (int)(len + 1), fp[0]);
1548 (void) snpf((a + plen), len + 2, ",%s", fp[0]);
1550 (void) snpf(a, len + 1, "%s", fp[0]);
1554 * The association ID is in the seventh field.
1556 id = sp ? sp->assocID : (char *)NULL;
1557 if (!i && fp[6] && *fp[6] && (len = strlen(fp[6]))) {
1559 if (isainb(fp[6], id)) {
1561 id = (char *)realloc((MALLOC_P *)id,plen+len+2);
1567 id = (char *)malloc(len + 1);
1571 (void) fprintf(stderr,
1572 "%s: can't allocate %d SCTP ASSOC-ID bytes: %s\n",
1573 Pn, (int)(len + 1), fp[6]);
1578 (void) snpf((id + plen), len + 2, ",%s", fp[6]);
1580 (void) snpf(id, len + 1, "%s", fp[6]);
1584 * The field number for the local port depends on the entry type.
1587 lp = sp ? sp->lport : (char *)NULL;
1588 if (fp[j] && *fp[j] && (len = strlen(fp[j]))) {
1590 if (isainb(fp[j], lp)) {
1592 lp = (char *)realloc((MALLOC_P *)lp,plen+len+2);
1598 lp = (char *)malloc(len + 1);
1602 (void) fprintf(stderr,
1603 "%s: can't allocate %d SCTP LPORT bytes: %s\n",
1604 Pn, (int)(len + 1), fp[j]);
1609 (void) snpf((lp + plen), len + 2, ",%s", fp[j]);
1611 (void) snpf(lp, len + 1, "%s", fp[j]);
1615 * The field number for the remote port depends on the entry type.
1617 rp = sp ? sp->rport : (char *)NULL;
1618 if (!i && fp[12] && *fp[12] && (len = strlen(fp[12]))) {
1620 if (isainb(fp[12], rp)) {
1622 rp = (char *)realloc((MALLOC_P *)rp,plen+len+2);
1628 rp = (char *)malloc(len + 1);
1632 (void) fprintf(stderr,
1633 "%s: can't allocate %d SCTP RPORT bytes: %s\n",
1634 Pn, (int)(len + 1), fp[12]);
1639 (void) snpf((rp + plen), len + 2, ",%s", fp[12]);
1641 (void) snpf(rp, len + 1, "%s", fp[12]);
1645 * The local addresses begin in a field whose number depends on
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",
1658 if (isainb(ta, la)) {
1661 if (!(la=(char *)realloc((MALLOC_P *)la,plen+len+2))
1663 (void) fprintf(stderr,
1664 "%s: can't reallocate %d SCTP LADDRS bytes\n",
1668 (void) snpf(la + plen, len + 2, ",%s", ta);
1669 (void) free((FREE_P *)ta);
1675 * The remote addresses begin after the local addresses, but only
1676 * for the ASSOC type.
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",
1687 if (isainb(ta, ra)) {
1690 if (!(ra=(char *)realloc((MALLOC_P *)ra,plen+len+2))
1692 (void) fprintf(stderr,
1693 "%s: can't reallocate %d SCTP RADDRS bytes\n",
1697 (void) snpf(ra + plen, len + 2, ",%s", ta);
1698 (void) free((FREE_P *)ta);
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.
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));
1716 sp->next = SCTPsin[h];
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 */
1739 MALLOC_S al = (MALLOC_S)0;
1740 char *cp = (char *)NULL;
1745 if ((i >= nf) || !fp[i] || !*fp[i] || !(tl = strlen(fp[i])))
1747 if (!strcmp(fp[i], "<->")) {
1751 if (!strchr(fp[i], (int)'.') && !strchr(fp[i], (int)':'))
1754 cp = (char *)realloc((MALLOC_P *)cp, al + tl + 1);
1756 cp = (char *)malloc(al + tl + 1);
1760 *(cp + al - 1) = ',';
1761 (void) strncpy(al ? (cp + al) : cp, fp[i], tl);
1763 *(cp + al - 1) = '\0';
1770 * get_tcpudp() - get IPv4 TCP, UDP or UDPLITE net info
1774 get_tcpudp(p, pr, clr)
1775 char *p; /* /proc/net/{tcp,udp} path */
1776 int pr; /* protocol: 0 = TCP, 1 = UDP,
1778 int clr; /* 1 == clear the table */
1780 char buf[MAXPATHLEN], *ep, **fp;
1781 unsigned long faddr, fport, laddr, lport, rxq, state, txq;
1785 struct tcp_udp *np, *tp;
1786 static char *vbuf = (char *)NULL;
1787 static size_t vsz = (size_t)0;
1789 * Delete previous table contents.
1793 for (h = 0; h < TcpUdp_bucks; h++) {
1794 for (tp = TcpUdp[h]; tp; tp = np) {
1796 (void) free((FREE_P *)tp);
1798 TcpUdp[h] = (struct tcp_udp *)NULL;
1802 * If no hash buckets have been allocated, do so now.
1807 * Open the /proc/net/sockstat file and establish the hash bucket
1808 * count from its "sockets: used" line.
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)
1815 if (!fp[0] || strcmp(fp[0], "sockets:")
1816 || !fp[1] || strcmp(fp[1], "used")
1817 || !fp[2] || !*fp[2])
1819 if ((h = atoi(fp[2])) < 1)
1821 while (TcpUdp_bucks < h)
1827 if (!(TcpUdp = (struct tcp_udp **)calloc(TcpUdp_bucks,
1828 sizeof(struct tcp_udp *))))
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 *)));
1837 * Open the /proc/net file, assign a page size buffer to the stream, and
1840 if (!(fs = open_proc_stream(p, "r", &vbuf, &vsz, 0)))
1843 while(fgets(buf, sizeof(buf) - 1, fs)) {
1845 (nf == 12) ? (char *)NULL : ":",
1846 &fp, (int *)NULL, 0)
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"))
1858 (void) fprintf(stderr,
1859 "%s: WARNING: unsupported format: %s\n",
1868 * Get the local and remote addresses.
1871 if (!fp[1] || !*fp[1]
1872 || (laddr = strtoul(fp[1], &ep, 16)) == ULONG_MAX || !ep || *ep)
1875 if (!fp[2] || !*fp[2]
1876 || (lport = strtoul(fp[2], &ep, 16)) == ULONG_MAX || !ep || *ep)
1879 if (!fp[3] || !*fp[3]
1880 || (faddr = strtoul(fp[3], &ep, 16)) == ULONG_MAX || !ep || *ep)
1883 if (!fp[4] || !*fp[4]
1884 || (fport = strtoul(fp[4], &ep, 16)) == ULONG_MAX || !ep || *ep)
1887 * Get the state and queue sizes.
1890 if (!fp[5] || !*fp[5]
1891 || (state = strtoul(fp[5], &ep, 16)) == ULONG_MAX || !ep || *ep)
1894 if (!fp[6] || !*fp[6]
1895 || (txq = strtoul(fp[6], &ep, 16)) == ULONG_MAX || !ep || *ep)
1898 if (!fp[7] || !*fp[7]
1899 || (rxq = strtoul(fp[7], &ep, 16)) == ULONG_MAX || !ep || *ep)
1902 * Get the inode and use it for hashing and searching.
1905 if (!fp[13] || !*fp[13]
1906 || (inode = strtoull(fp[13], &ep, 0)) == ULONG_MAX || !ep || *ep)
1908 h = TCPUDPHASH(inode);
1909 for (tp = TcpUdp[h]; tp; tp = tp->next) {
1910 if (tp->inode == inode)
1916 * Create a new entry and link it to its hash bucket.
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));
1926 tp->fport = (int)(fport & 0xffff);
1928 tp->lport = (int)(lport & 0xffff);
1932 tp->state = (int)state;
1933 tp->next = TcpUdp[h];
1940 #if defined(HASIPv6)
1942 * get_raw6() - get /proc/net/raw6 info
1947 char *p; /* /proc/net/raw path */
1949 char buf[MAXPATHLEN], *ep, **fp, *la, *ra, *sp;
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;
1959 * Do second time cleanup or first time setup.
1962 for (h = 0; h < INOBUCKS; h++) {
1963 for (rp = Rawsin6[h]; rp; rp = np) {
1966 (void) free((FREE_P *)rp->la);
1968 (void) free((FREE_P *)rp->ra);
1969 (void) free((FREE_P *)rp);
1971 Rawsin6[h] = (struct rawsin *)NULL;
1974 Rawsin6 = (struct rawsin **)calloc(INOBUCKS,
1975 sizeof(struct rawsin *));
1977 (void) fprintf(stderr,
1978 "%s: can't allocate %d raw6 hash pointer bytes\n",
1979 Pn, (int)(INOBUCKS * sizeof(struct rawsin *)));
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.
1987 if (!(xs = open_proc_stream(p, "r", &vbuf, &vsz, 0)))
1989 while (fgets(buf, sizeof(buf) - 1, xs)) {
1990 if (get_fields(buf, (char *)NULL, &fp, (int *)NULL, 0) < nf)
1995 * Check the column labels in the first line.
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"))
2003 (void) fprintf(stderr,
2004 "%s: WARNING: unsupported format: %s\n",
2013 * Assemble the inode number and see if the inode is already
2017 if (!fp[9] || !*fp[9]
2018 || (inode = strtoull(fp[9], &ep, 0)) == ULONG_MAX
2022 for (rp = Rawsin6[h]; rp; rp = rp->next) {
2023 if (inode == rp->inode)
2029 * Save the local address, remote address, and state.
2031 if (!fp[1] || !*fp[1] || (lal = strlen(fp[1])) < 1) {
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]);
2041 (void) snpf(la, lal + 1, "%s", fp[1]);
2043 if (!fp[2] || !*fp[2] || (ral = strlen(fp[2])) < 1) {
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]);
2053 (void) snpf(ra, ral + 1, "%s", fp[2]);
2055 if (!fp[3] || !*fp[3] || (spl = strlen(fp[3])) < 1) {
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]);
2065 (void) snpf(sp, spl + 1, "%s", fp[3]);
2068 * Allocate space for an rawsin entry, fill it, and link it to its
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));
2084 rp->next = Rawsin6[h];
2092 * get_tcpudp6() - get IPv6 TCP, UDP or UDPLITE net info
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 */
2101 char buf[MAXPATHLEN], *ep, **fp;
2102 struct in6_addr faddr, laddr;
2103 unsigned long fport, lport, rxq, state, txq;
2107 struct tcp_udp6 *np6, *tp6;
2108 static char *vbuf = (char *)NULL;
2109 static size_t vsz = (size_t)0;
2111 * Delete previous table contents. Allocate a table for the first time.
2115 for (h = 0; h < TcpUdp6_bucks; h++) {
2116 for (tp6 = TcpUdp6[h]; tp6; tp6 = np6) {
2118 (void) free((FREE_P *)tp6);
2120 TcpUdp6[h] = (struct tcp_udp6 *)NULL;
2126 * Open the /proc/net/sockstat6 file and establish the hash bucket
2127 * count from its "TCP6: inuse" and "UDP6: inuse" lines.
2129 TcpUdp6_bucks = INOBUCKS;
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)
2136 || !fp[1] || strcmp(fp[1], "inuse")
2137 || !fp[2] || !*fp[2])
2139 if (!strcmp(fp[0], "TCP6:")) {
2141 if ((h = atoi(fp[2])) < 1)
2144 } else if (!strcmp(fp[0], "UDP6:")) {
2146 if ((h = atoi(fp[2])) < 1)
2152 while (TcpUdp6_bucks < i)
2159 if (!(TcpUdp6 = (struct tcp_udp6 **)calloc(TcpUdp6_bucks,
2160 sizeof(struct tcp_udp6 *))))
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 *)));
2169 * Open the /proc/net file, assign a page size buffer to the stream,
2172 if (!(fs = open_proc_stream(p, "r", &vbuf, &vsz, 0)))
2175 while(fgets(buf, sizeof(buf) - 1, fs)) {
2177 (nf == 12) ? (char *)NULL : ":",
2178 &fp, (int *)NULL, 0)
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"))
2190 (void) fprintf(stderr,
2191 "%s: WARNING: unsupported format: %s\n",
2200 * Get the local and remote addresses.
2202 if (!fp[1] || !*fp[1] || net6a2in6(fp[1], &laddr))
2205 if (!fp[2] || !*fp[2]
2206 || (lport = strtoul(fp[2], &ep, 16)) == ULONG_MAX || !ep || *ep)
2208 if (!fp[3] || !*fp[3] || net6a2in6(fp[3], &faddr))
2211 if (!fp[4] || !*fp[4]
2212 || (fport = strtoul(fp[4], &ep, 16)) == ULONG_MAX || !ep || *ep)
2215 * Get the state and queue sizes.
2218 if (!fp[5] || !*fp[5]
2219 || (state = strtoul(fp[5], &ep, 16)) == ULONG_MAX || !ep || *ep)
2222 if (!fp[6] || !*fp[6]
2223 || (txq = strtoul(fp[6], &ep, 16)) == ULONG_MAX || !ep || *ep)
2226 if (!fp[7] || !*fp[7]
2227 || (rxq = strtoul(fp[7], &ep, 16)) == ULONG_MAX || !ep || *ep)
2230 * Get the inode and use it for hashing and searching.
2233 if (!fp[13] || !*fp[13]
2234 || (inode = strtoull(fp[13], &ep, 0)) == ULONG_MAX || !ep || *ep)
2236 h = TCPUDP6HASH(inode);
2237 for (tp6 = TcpUdp6[h]; tp6; tp6 = tp6->next) {
2238 if (tp6->inode == inode)
2244 * Create a new entry and link it to its hash bucket.
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));
2254 tp6->fport = (int)(fport & 0xffff);
2256 tp6->lport = (int)(lport & 0xffff);
2260 tp6->state = (int)state;
2261 tp6->next = TcpUdp6[h];
2266 #endif /* defined(HASIPv6) */
2270 * get_unix() - get UNIX net info
2275 char *p; /* /proc/net/unix path */
2277 char buf[MAXPATHLEN], *ep, **fp, *path, *pcb;
2282 struct uxsin *np, *up;
2284 static char *vbuf = (char *)NULL;
2285 static size_t vsz = (size_t)0;
2287 * Do second time cleanup or first time setup.
2290 for (h = 0; h < INOBUCKS; h++) {
2291 for (up = Uxsin[h]; up; up = np) {
2294 (void) free((FREE_P *)up->path);
2296 (void) free((FREE_P *)up->pcb);
2297 (void) free((FREE_P *)up);
2299 Uxsin[h] = (struct uxsin *)NULL;
2302 Uxsin = (struct uxsin **)calloc(INOBUCKS, sizeof(struct uxsin *));
2304 (void) fprintf(stderr,
2305 "%s: can't allocate %d bytes for Unix socket info\n",
2306 Pn, (int)(INOBUCKS * sizeof(struct uxsin *)));
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.
2313 if (!(us = open_proc_stream(p, "r", &vbuf, &vsz, 0)))
2315 while (fgets(buf, sizeof(buf) - 1, us)) {
2316 if ((nf = get_fields(buf, ":", &fp, (int *)NULL, 0)) < 7)
2321 * Check the first line for header words.
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")
2331 || !fp[7] || strcmp(fp[7], "Path"))
2334 (void) fprintf(stderr,
2335 "%s: WARNING: unsupported format: %s\n",
2344 * Assemble PCB address, inode number, and path name. If this
2345 * inode is already represented in Uxsin, skip it.
2348 if (!fp[6] || !*fp[6]
2349 || (inode = strtoull(fp[6], &ep, 0)) == ULONG_MAX || !ep || *ep)
2352 for (up = Uxsin[h]; up; up = up->next) {
2353 if (inode == up->inode)
2358 if (!fp[0] || !*fp[0])
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]);
2368 (void) snpf(pcb, len + 1, "0x%s", fp[0]);
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]);
2377 (void) snpf(path, len + 1, "%s", fp[7]);
2379 path = (char *)NULL;
2381 * Allocate and fill a Unix socket info structure; link it to its
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));
2393 if ((up->path = path) && (*path == '/')) {
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.
2404 sr = statsafely(path, &sb);
2406 sr = stat(path, &sb);
2407 if (sr && ((sb.st_mode & S_IFMT) == S_IFSOCK)) {
2409 up->sb_dev = sb.st_dev;
2410 up->sb_ino = (INODETYPE)sb.st_ino;
2411 up->sb_rdev = sb.st_rdev;
2414 up->next = Uxsin[h];
2421 #if defined(HASIPv6)
2423 * net6a2in6() - convert ASCII IPv6 address in /proc/net/{tcp,udp} form to
2429 char *as; /* address source */
2430 struct in6_addr *ad; /* address destination */
2436 * Assemble four uint32_t's from 4 X 8 hex digits into s6_addr32[].
2438 for (i = 0, len = strlen(as);
2439 (i < 4) && (len >= 8);
2440 as += 8, i++, len -= 8)
2442 (void) strncpy(buf, as, 8);
2445 if ((ad->s6_addr32[i] = (uint32_t)strtoul(buf, &ep, 16))
2446 == (uint32_t)UINT32_MAX || !ep || *ep)
2449 return((*as || (i != 4) || len) ? 1 : 0);
2451 #endif /* defined(HASIPv6) */
2455 * isainb(a,b) is string a in string b
2460 char *a; /*string a */
2461 char *b; /* string b */
2464 MALLOC_S la, lb, lt;
2468 if (!(la = strlen(a)) || !(lb = strlen(b)))
2470 if (!(cp = strchr(b, (int)','))) {
2473 return(strcmp(a, b));
2475 for (pp = b; pp && *pp; ) {
2476 lt = (MALLOC_S)(cp - pp);
2477 if ((la == lt) && !strncmp(a, pp, lt))
2481 if (!(cp = strchr(pp, (int)',')))
2491 * print_ax25info() - print AX25 socket info
2496 struct ax25sin *ap; /* AX25 socket info */
2498 char *cp, pbuf[1024];
2500 MALLOC_S pl = (MALLOC_S)0;
2505 ds = (ap->da && strcmp(ap->da, "*")) ? 1 : 0;
2506 (void) snpf(&pbuf[pl], sizeof(pbuf) - pl, "%s%s%s ", ap->sa,
2512 (void) snpf(&pbuf[pl], sizeof(pbuf) - pl, "(Sq=%lu ", ap->sq);
2518 (void) snpf(&pbuf[pl], sizeof(pbuf) - pl, "%sRq=%lu ", cp, ap->rq);
2522 (void) snpf(&pbuf[pl], sizeof(pbuf) - pl, "%sState=%d", cp, ap->state);
2524 if ((ap->state >= 0) && (ap->state < NAX25ST))
2525 cp = ax25st[ap->state];
2528 (void) snpf(&pbuf[pl], sizeof(pbuf) - pl, "%s%s)",
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);
2538 (void) snpf(cp, pl + 1, "%s", pbuf);
2544 * print_ipxinfo() - print IPX socket info
2549 struct ipxsin *ip; /* IPX socket info */
2551 char *cp, pbuf[256];
2556 (void) snpf(pbuf, sizeof(pbuf), "(Tx=%lx Rx=%lx State=%02x)",
2557 ip->txq, ip->rxq, ip->state);
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);
2565 (void) snpf(cp, pl + 1, "%s", pbuf);
2571 * print_tcptpi() - print TCP/TPI state
2576 int nl; /* 1 == '\n' required */
2579 char *cp = (char *)NULL;
2583 if ((Ftcptpi & TCPTPI_STATE) && Lf->lts.type == 0) {
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",
2594 (void) printf("%cST=%s%c", LSOF_FID_TCPTPI, cp, Terminator);
2597 (void) fputs(cp, stdout);
2603 # if defined(HASTCPTPIQ)
2604 if (Ftcptpi & TCPTPI_QUEUES) {
2607 putchar(LSOF_FID_TCPTPI);
2614 (void) printf("QR=%lu", Lf->lts.rq);
2616 putchar(Terminator);
2621 putchar(LSOF_FID_TCPTPI);
2628 (void) printf("QS=%lu", Lf->lts.sq);
2630 putchar(Terminator);
2634 # endif /* defined(HASTCPTPIQ) */
2636 # if defined(HASTCPTPIW)
2637 if (Ftcptpi & TCPTPI_WINDOWS) {
2640 putchar(LSOF_FID_TCPTPI);
2647 (void) printf("WR=%lu", Lf->lts.rw);
2649 putchar(Terminator);
2654 putchar(LSOF_FID_TCPTPI);
2661 (void) printf("WW=%lu", Lf->lts.ww);
2663 putchar(Terminator);
2667 # endif /* defined(HASTCPTPIW) */
2677 * process_proc_sock() - process /proc-based socket
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
2688 int lss; /* *l status -- i.e, SB_* values */
2691 char *cp, *path, tbuf[64];
2692 unsigned char *fa, *la;
2693 struct in_addr fs, ls;
2694 struct icmpin *icmpp;
2700 static char *prp = (char *)NULL;
2707 #if defined(HASIPv6)
2709 struct tcp_udp6 *tp6;
2710 #endif /* defined(HASIPv6) */
2713 * Enter offset, if possible.
2715 if (Foffset || !Fsize) {
2716 if (l && (lss & SB_SIZE) && OffType) {
2717 Lf->off = (SZOFFTYPE)l->st_size;
2722 * Check for socket's inode presence in the protocol info caches.
2725 (void) get_ax25(AX25path);
2726 (void) free((FREE_P *)AX25path);
2727 AX25path = (char *)NULL;
2730 && (ap = check_ax25((INODETYPE)s->st_ino))
2734 * The inode is connected to an AX25 /proc record.
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.
2740 (void) snpf(Lf->type, sizeof(Lf->type), "ax25");
2742 (void) enter_dev_ch(ap->dev_ch);
2743 Lf->inode = ap->inode;
2749 (void) get_ipx(Ipxpath);
2750 (void) free((FREE_P *)Ipxpath);
2751 Ipxpath = (char *)NULL;
2754 && (ip = check_ipx((INODETYPE)s->st_ino))
2758 * The inode is connected to an IPX /proc record.
2760 * Set the type to "ipx"; enter the inode and device numbers; store
2761 * the addresses, queue sizes, and state in the NAME column.
2763 (void) snpf(Lf->type, sizeof(Lf->type), "ipx");
2765 Lf->inode = (INODETYPE)s->st_ino;
2769 Lf->dev = s->st_dev;
2778 * Store the local IPX address.
2780 len = strlen(ip->la);
2783 (void) strncpy(cp, ip->la, len);
2791 * Store the remote IPX address, prefixed with "->".
2794 (void) snpf(cp, nl, "->");
2799 (void) snpf(cp, nl, "%s", ip->ra);
2804 (void) print_ipxinfo(ip);
2810 (void) get_raw(Rawpath);
2811 (void) free((FREE_P *)Rawpath);
2812 Rawpath = (char *)NULL;
2815 && (rp = check_raw((INODETYPE)s->st_ino))
2819 * The inode is connected to a raw /proc record.
2821 * Set the type to "raw"; enter the inode number; store the local
2822 * address, remote address, and state in the NAME column.
2824 (void) snpf(Lf->type, sizeof(Lf->type), "raw");
2826 Lf->inode = (INODETYPE)s->st_ino;
2832 if (rp->la && rp->lal) {
2835 * Store the local raw address.
2838 (void) snpf(cp, nl, "%s", rp->la);
2844 if (rp->ra && rp->ral) {
2847 * Store the remote raw address, prefixed with "->".
2849 if (nl > (rp->ral + 2)) {
2850 (void) snpf(cp, nl, "->%s", rp->ra);
2851 cp += (rp->ral + 2);
2853 nl -= (rp->ral + 2);
2856 if (rp->sp && rp->spl) {
2859 * Store the state, optionally prefixed by a space, in the
2863 if (nl > (len = ((cp == Namech) ? 0 : 1) + 3 + rp->spl)) {
2864 (void) snpf(cp, nl, "%sst=%s",
2865 (cp == Namech) ? "" : " ", rp->sp);
2876 (void) get_netlink(Nlkpath);
2877 (void) free((FREE_P *) Nlkpath);
2878 Nlkpath = (char *)NULL;
2881 && (np = check_netlink((INODETYPE)s->st_ino))
2884 * The inode is connected to a Netlink /proc record.
2886 * Set the type to "netlink" and store the protocol in the NAME
2887 * column. Save the inode number.
2890 (void) snpf(Lf->type, sizeof(Lf->type), "netlink");
2893 #if defined(NETLINK_ROUTE)
2897 #endif /* defined(NETLINK_ROUTE) */
2899 #if defined(NETLINK_UNUSED)
2900 case NETLINK_UNUSED:
2903 #endif /* defined(NETLINK_UNUSED) */
2905 #if defined(NETLINK_USERSOCK)
2906 case NETLINK_USERSOCK:
2909 #endif /* defined(NETLINK_USERSOCK) */
2911 #if defined(NETLINK_FIREWALL)
2912 case NETLINK_FIREWALL:
2915 #endif /* defined(NETLINK_FIREWALL) */
2917 #if defined(NETLINK_INET_DIAG)
2918 case NETLINK_INET_DIAG:
2921 #endif /* defined(NETLINK_INET_DIAG) */
2923 #if defined(NETLINK_NFLOG)
2927 #endif /* defined(NETLINK_NFLOG) */
2929 #if defined(NETLINK_XFRM)
2933 #endif /* defined(NETLINK_XFRM) */
2935 #if defined(NETLINK_SELINUX)
2936 case NETLINK_SELINUX:
2939 #endif /* defined(NETLINK_SELINUX) */
2941 #if defined(NETLINK_ISCSI)
2945 #endif /* defined(NETLINK_ISCSI) */
2947 #if defined(NETLINK_AUDIT)
2951 #endif /* defined(NETLINK_AUDIT) */
2953 #if defined(NETLINK_FIB_LOOKUP)
2954 case NETLINK_FIB_LOOKUP:
2957 #endif /* defined(NETLINK_FIB_LOOKUP) */
2959 #if defined(NETLINK_CONNECTOR)
2960 case NETLINK_CONNECTOR:
2963 #endif /* defined(NETLINK_CONNECTOR) */
2965 #if defined(NETLINK_NETFILTER)
2966 case NETLINK_NETFILTER:
2969 #endif /* defined(NETLINK_NETFILTER) */
2971 #if defined(NETLINK_IP6_FW)
2972 case NETLINK_IP6_FW:
2975 #endif /* defined(NETLINK_IP6_FW) */
2977 #if defined(NETLINK_DNRTMSG)
2978 case NETLINK_DNRTMSG:
2981 #endif /* defined(NETLINK_DNRTMSG) */
2983 #if defined(NETLINK_KOBJECT_UEVENT)
2984 case NETLINK_KOBJECT_UEVENT:
2985 cp = "KOBJECT_UEVENT";
2987 #endif /* defined(NETLINK_KOBJECT_UEVENT) */
2989 #if defined(NETLINK_GENERIC)
2990 case NETLINK_GENERIC:
2993 #endif /* defined(NETLINK_GENERIC) */
2995 #if defined(NETLINK_SCSITRANSPORT)
2996 case NETLINK_SCSITRANSPORT:
2997 cp = "SCSITRANSPORT";
2999 #endif /* defined(NETLINK_SCSITRANSPORT) */
3001 #if defined(NETLINK_ECRYPTFS)
3002 case NETLINK_ECRYPTFS:
3005 #endif /* defined(NETLINK_ECRYPTFS) */
3008 (void) snpf(Namech, Namechl, "unknown protocol: %d", np->pr);
3012 (void) snpf(Namech, Namechl, "%s", cp);
3013 Lf->inode = (INODETYPE)s->st_ino;
3020 (void) get_pack(Packpath);
3021 (void) free((FREE_P *)Packpath);
3022 Packpath = (char *)NULL;
3025 && (pp = check_pack((INODETYPE)s->st_ino))
3029 * The inode is connected to a packet /proc record.
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.
3035 (void) snpf(Lf->type, sizeof(Lf->type), "pack");
3038 #if defined(SOCK_STREAM)
3042 #endif /* defined(SOCK_STREAM) */
3044 #if defined(SOCK_DGRAM)
3048 #endif /* defined(SOCK_DGRAM) */
3050 #if defined(SOCK_RAW)
3054 #endif /* defined(SOCK_RAW) */
3056 #if defined(SOCK_RDM)
3060 #endif /* defined(SOCK_RDM) */
3062 #if defined(SOCK_SEQPACKET)
3063 case SOCK_SEQPACKET:
3066 #endif /* defined(SOCK_SEQPACKET) */
3068 #if defined(SOCK_PACKET)
3072 #endif /* defined(SOCK_PACKET) */
3075 (void) snpf(Namech, Namechl, "unknown type: %d", pp->ty);
3079 (void) snpf(Namech, Namechl, "type=SOCK_%s", cp);
3082 #if defined(ETH_P_LOOP)
3086 #endif /* defined(ETH_P_LOOP) */
3088 #if defined(ETH_P_PUP)
3092 #endif /* defined(ETH_P_PUP) */
3094 #if defined(ETH_P_PUPAT)
3098 #endif /* defined(ETH_P_PUPAT) */
3100 #if defined(ETH_P_IP)
3104 #endif /* defined(ETH_P_IP) */
3106 #if defined(ETH_P_X25)
3110 #endif /* defined(ETH_P_X25) */
3112 #if defined(ETH_P_ARP)
3116 #endif /* defined(ETH_P_ARP) */
3118 #if defined(ETH_P_BPQ)
3122 #endif /* defined(ETH_P_BPQ) */
3124 #if defined(ETH_P_IEEEPUP)
3128 #endif /* defined(ETH_P_IEEEPUP) */
3130 #if defined(ETH_P_IEEEPUPAT)
3131 case ETH_P_IEEEPUPAT:
3134 #endif /* defined(ETH_P_IEEEPUPAT) */
3136 #if defined(ETH_P_DEC)
3140 #endif /* defined(ETH_P_DEC) */
3142 #if defined(ETH_P_DNA_DL)
3146 #endif /* defined(ETH_P_DNA_DL) */
3148 #if defined(ETH_P_DNA_RC)
3152 #endif /* defined(ETH_P_DNA_RC) */
3154 #if defined(ETH_P_DNA_RT)
3158 #endif /* defined(ETH_P_DNA_RT) */
3160 #if defined(ETH_P_LAT)
3164 #endif /* defined(ETH_P_LAT) */
3166 #if defined(ETH_P_DIAG)
3170 #endif /* defined(ETH_P_DIAG) */
3172 #if defined(ETH_P_CUST)
3176 #endif /* defined(ETH_P_CUST) */
3178 #if defined(ETH_P_SCA)
3182 #endif /* defined(ETH_P_SCA) */
3184 #if defined(ETH_P_RARP)
3188 #endif /* defined(ETH_P_RARP) */
3190 #if defined(ETH_P_ATALK)
3194 #endif /* defined(ETH_P_ATALK) */
3196 #if defined(ETH_P_AARP)
3200 #endif /* defined(ETH_P_AARP) */
3202 #if defined(ETH_P_8021Q)
3206 #endif /* defined(ETH_P_8021Q) */
3208 #if defined(ETH_P_IPX)
3212 #endif /* defined(ETH_P_IPX) */
3214 #if defined(ETH_P_IPV6)
3218 #endif /* defined(ETH_P_IPV6) */
3220 #if defined(ETH_P_SLOW)
3224 #endif /* defined(ETH_P_SLOW) */
3226 #if defined(ETH_P_WCCP)
3230 #endif /* defined(ETH_P_WCCP) */
3232 #if defined(ETH_P_PPP_DISC)
3233 case ETH_P_PPP_DISC:
3236 #endif /* defined(ETH_P_PPP_DISC) */
3238 #if defined(ETH_P_PPP_SES)
3242 #endif /* defined(ETH_P_PPP_SES) */
3244 #if defined(ETH_P_MPLS_UC)
3248 #endif /* defined(ETH_P_MPLS_UC) */
3250 #if defined(ETH_P_ATMMPOA)
3254 #endif /* defined(ETH_P_ATMMPOA) */
3256 #if defined(ETH_P_MPLS_MC)
3260 #endif /* defined(ETH_P_MPLS_MC) */
3262 #if defined(ETH_P_ATMFATE)
3266 #endif /* defined(ETH_P_ATMFATE) */
3268 #if defined(ETH_P_AOE)
3272 #endif /* defined(ETH_P_AOE) */
3274 #if defined(ETH_P_TIPC)
3278 #endif /* defined(ETH_P_TIPC) */
3280 #if defined(ETH_P_802_3)
3284 #endif /* defined(ETH_P_802_3) */
3286 #if defined(ETH_P_AX25)
3290 #endif /* defined(ETH_P_AX25) */
3292 #if defined(ETH_P_ALL)
3296 #endif /* defined(ETH_P_ALL) */
3298 #if defined(ETH_P_802_2)
3302 #endif /* defined(ETH_P_802_2) */
3304 #if defined(ETH_P_SNAP)
3308 #endif /* defined(ETH_P_SNAP) */
3310 #if defined(ETH_P_DDCMP)
3314 #endif /* defined(ETH_P_DDCMP) */
3316 #if defined(ETH_P_WAN_PPP)
3320 #endif /* defined(ETH_P_WAN_PPP) */
3322 #if defined(ETH_P_PPP_MP)
3326 #endif /* defined(ETH_P_PPP_MP) */
3328 #if defined(ETH_P_LOCALTALK)
3329 case ETH_P_LOCALTALK:
3332 #endif /* defined(ETH_P_LOCALTALK) */
3334 #if defined(ETH_P_PPPTALK)
3338 #endif /* defined(ETH_P_PPPTALK) */
3340 #if defined(ETH_P_TR_802_2)
3341 case ETH_P_TR_802_2:
3344 #endif /* defined(ETH_P_TR_802_2) */
3346 #if defined(ETH_P_MOBITEX)
3350 #endif /* defined(ETH_P_MOBITEX) */
3352 #if defined(ETH_P_CONTROL)
3356 #endif /* defined(ETH_P_CONTROL) */
3358 #if defined(ETH_P_IRDA)
3362 #endif /* defined(ETH_P_IRDA) */
3364 #if defined(ETH_P_ECONET)
3368 #endif /* defined(ETH_P_ECONET) */
3370 #if defined(ETH_P_HDLC)
3374 #endif /* defined(ETH_P_HDLC) */
3376 #if defined(ETH_P_ARCNET)
3380 #endif /* defined(ETH_P_ARCNET) */
3383 (void) snpf(tbuf, sizeof(tbuf) - 1, "%d", pp->pr);
3384 tbuf[sizeof(tbuf) - 1] = '\0';
3387 (void) snpf(Lf->iproto, sizeof(Lf->iproto), "%.*s", IPROTOL-1, cp);
3390 (void) snpf(tbuf, sizeof(tbuf), InodeFmt_d,
3391 (INODETYPE)s->st_ino);
3392 tbuf[sizeof(tbuf) - 1] = '\0';
3400 (void) get_unix(UNIXpath);
3401 (void) free((FREE_P *)UNIXpath);
3402 UNIXpath = (char *)NULL;
3405 && (up = check_unix((INODETYPE)s->st_ino))
3409 * The inode is connected to a UNIX /proc record.
3411 * Set the type to "unix"; enter the PCB address in the DEVICE column;
3412 * enter the inode number; and save the optional path.
3416 (void) snpf(Lf->type, sizeof(Lf->type), "unix");
3418 enter_dev_ch(up->pcb);
3420 Lf->inode = (INODETYPE)s->st_ino;
3423 path = up->path ? up->path : p;
3424 (void) enter_nm(path);
3428 * See if this UNIX domain socket was specified as a search
3431 * Search first by device and node numbers, if that is possible;
3432 * then search by name.
3434 unsigned char f = 0; /* file-found flag */
3439 * If the UNIX socket information includes stat(2) results, do
3440 * a device and node number search.
3442 * Note: that requires the saving, temporary modification and
3443 * restoration of some *Lf values.
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 */
3452 sv_dev_def = Lf->dev_def;
3454 sv_inode = Lf->inode;
3455 sv_inp_ty = Lf->inp_ty;
3456 sv_rdev_def = Lf->rdev_def;
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)) {
3466 Lf->dev_def = sv_dev_def;
3468 Lf->inode = sv_inode;
3469 Lf->inp_ty = sv_inp_ty;
3470 Lf->rdev_def = sv_rdev_def;
3473 if (!f && (ss & SB_MODE)) {
3476 * If the file has not yet been found and the stat buffer has
3477 * st_mode, search for the file by full path.
3479 if (is_file_named(2, path, (struct mounts *)NULL,
3480 ((s->st_mode & S_IFMT) == S_IFCHR)) ? 1 : 0)
3489 #if defined(HASIPv6)
3492 (void) get_raw6(Raw6path);
3493 (void) free((FREE_P *)Raw6path);
3494 Raw6path = (char *)NULL;
3496 if (!Fxopt && (ss & SB_INO)
3497 && (rp = check_raw6((INODETYPE)s->st_ino))
3501 * The inode is connected to a raw IPv6 /proc record.
3503 * Set the type to "raw6"; enter the inode number; store the local
3504 * address, remote address, and state in the NAME column.
3506 (void) snpf(Lf->type, sizeof(Lf->type), "raw6");
3508 Lf->inode = (INODETYPE)s->st_ino;
3512 nl = MAXPATHLEN - 2;
3513 if (rp->la && rp->lal) {
3516 * Store the local raw IPv6 address.
3519 (void) snpf(cp, nl, "%s", rp->la);
3525 if (rp->ra && rp->ral) {
3528 * Store the remote raw address, prefixed with "->".
3530 if (nl > (rp->ral + 2)) {
3531 (void) snpf(cp, nl, "->%s", rp->ra);
3532 cp += (rp->ral + 2);
3533 nl -= (rp->ral + 2);
3536 if (rp->sp && rp->spl) {
3539 * Store the state, optionally prefixed by a space, in the
3543 if (nl > (len = ((cp == Namech) ? 0 : 1) + 3 + rp->spl)) {
3544 (void) snpf(cp, nl, "%sst=%s",
3545 (cp == Namech) ? "" : " ", rp->sp);
3557 (void) get_tcpudp6(TCP6path, 0, 1);
3558 (void) free((FREE_P *)TCP6path);
3559 TCP6path = (char *)NULL;
3563 (void) get_tcpudp6(UDP6path, 1, 0);
3564 (void) free((FREE_P *)UDP6path);
3565 UDP6path = (char *)NULL;
3569 (void) get_tcpudp6(UDPLITE6path, 2, 0);
3570 (void) free((FREE_P *)UDPLITE6path);
3571 UDPLITE6path = (char *)NULL;
3573 if (!Fxopt && (ss & SB_INO)
3574 && (tp6 = check_tcpudp6((INODETYPE)s->st_ino, &pr))
3578 * The inode is connected to an IPv6 TCP or UDP /proc record.
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.
3585 i = tp6->state + TcpStOff;
3589 * Check for state exclusion.
3591 if (i >= 0 && i < TcpNstates) {
3601 * Check for state inclusion.
3603 if (i >= 0 && i < TcpNstates) {
3612 if (Fnet && (FnetTy != 4))
3614 (void) snpf(Lf->type, sizeof(Lf->type), "IPv6");
3615 (void) snpf(Lf->iproto, sizeof(Lf->iproto), "%.*s", IPROTOL-1, pr);
3618 (void) snpf(tbuf, sizeof(tbuf), InodeFmt_d,
3619 (INODETYPE)s->st_ino);
3620 tbuf[sizeof(tbuf) - 1] = '\0';
3624 if (!IN6_IS_ADDR_UNSPECIFIED(&tp6->faddr) || tp6->fport)
3625 fa = (unsigned char *)&tp6->faddr;
3627 fa = (unsigned char *)NULL;
3628 if (!IN6_IS_ADDR_UNSPECIFIED(&tp6->laddr) || tp6->lport)
3629 la = (unsigned char *)&tp6->laddr;
3631 la = (unsigned char *)NULL;
3632 if ((fa && IN6_IS_ADDR_V4MAPPED(&tp6->faddr))
3633 || (la && IN6_IS_ADDR_V4MAPPED(&tp6->laddr))) {
3640 ent_inaddr(la, tp6->lport, fa, tp6->fport, af);
3641 Lf->lts.type = tp6->proto;
3642 Lf->lts.state.i = tp6->state;
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) */
3652 #endif /* defined(HASIPv6) */
3656 (void) get_tcpudp(TCPpath, 0, 1);
3657 (void) free((FREE_P *)TCPpath);
3658 TCPpath = (char *)NULL;
3662 (void) get_tcpudp(UDPpath, 1, 0);
3663 (void) free((FREE_P *)UDPpath);
3664 UDPpath = (char *)NULL;
3668 (void) get_tcpudp(UDPLITEpath, 2, 0);
3669 (void) free((FREE_P *)UDPLITEpath);
3670 UDPLITEpath = (char *)NULL;
3672 if (!Fxopt && (ss & SB_INO)
3673 && (tp = check_tcpudp((INODETYPE)s->st_ino, &pr))
3677 * The inode is connected to an IPv4 TCP or UDP /proc record.
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.
3684 i = tp->state + TcpStOff;
3688 * Check for state exclusion.
3690 if (i >= 0 && i < TcpNstates) {
3700 * Check for state inclusion.
3702 if (i >= 0 && i < TcpNstates) {
3711 if (Fnet && (FnetTy != 6))
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) */
3720 (void) snpf(Lf->iproto, sizeof(Lf->iproto), "%.*s", IPROTOL-1, pr);
3723 (void) snpf(tbuf, sizeof(tbuf), InodeFmt_d,
3724 (INODETYPE)s->st_ino);
3725 tbuf[sizeof(tbuf) - 1] = '\0';
3728 if (tp->faddr || tp->fport) {
3729 fs.s_addr = tp->faddr;
3730 fa = (unsigned char *)&fs;
3732 fa = (unsigned char *)NULL;
3733 if (tp->laddr || tp->lport) {
3734 ls.s_addr = tp->laddr;
3735 la = (unsigned char *)&ls;
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;
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) */
3752 for (i = 0; i < NSCTPPATHS; i++) {
3753 (void) free((FREE_P *)SCTPPath[i]);
3754 SCTPPath[i] = (char *)NULL;
3757 if ((ss & SB_INO) && (sp = check_sctp((INODETYPE)s->st_ino))
3761 * The inode is connected to an SCTP /proc record.
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.
3767 (void) snpf(Lf->type, sizeof(Lf->type), "sock");
3768 (void) snpf(Lf->iproto, sizeof(Lf->iproto), "%.*s", IPROTOL-1,
3771 (void) snpf(tbuf, sizeof(tbuf), InodeFmt_d, (INODETYPE)s->st_ino);
3772 tbuf[sizeof(tbuf) - 1] = '\0';
3775 if (sp->type == 1) {
3778 * This is an ENDPT SCTP file.
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 ? "]" : ""
3792 * This is an ASSOC, or ASSOC and ENDPT socket file.
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))
3806 sp->raddrs ? sp->raddrs : "",
3807 sp->rport ? "[" : "",
3808 sp->rport ? sp->rport : "",
3809 sp->rport ? "]" : ""
3817 (void) get_icmp(ICMPpath);
3818 (void) free((FREE_P *)ICMPpath);
3819 ICMPpath = (char *)NULL;
3822 && (icmpp = check_icmp((INODETYPE)s->st_ino))
3826 * The inode is connected to an ICMP /proc record.
3828 * Set the type to "icmp" and store the type in the NAME
3829 * column. Save the inode number.
3831 (void) snpf(Lf->type, sizeof(Lf->type), "icmp");
3832 Lf->inode = (INODETYPE)s->st_ino;
3837 if (icmpp->la && icmpp->lal) {
3840 * Store the local raw address.
3842 if (nl > icmpp->lal) {
3843 (void) snpf(cp, nl, "%s", icmpp->la);
3849 if (icmpp->ra && icmpp->ral) {
3852 * Store the remote raw address, prefixed with "->".
3854 if (nl > (icmpp->ral + 2)) {
3855 (void) snpf(cp, nl, "->%s", icmpp->ra);
3856 cp += (icmpp->ral + 2);
3858 nl -= (icmpp->ral + 2);
3866 * The socket's protocol can't be identified.
3868 (void) snpf(Lf->type, sizeof(Lf->type), "sock");
3870 Lf->inode = (INODETYPE)s->st_ino;
3874 Lf->dev = s->st_dev;
3878 enter_nm("can't identify protocol (-X specified)");
3880 (void) snpf(Namech, Namechl, "protocol: ");
3882 i = (int)strlen(Namech);
3884 sz = (ssize_t)(Namechl - i - 1);
3886 if ((getxattr(pbr, "system.sockprotoname", prp, sz)) < 0)
3887 enter_nm("can't identify protocol");
3895 * set_net_paths() - set /proc/net paths
3899 set_net_paths(p, pl)
3900 char *p; /* path to /proc/net/ */
3901 int pl; /* strlen(p) */
3907 (void) make_proc_path(p, pl, &AX25path, &pathl, "ax25");
3909 (void) make_proc_path(p, pl, &ICMPpath, &pathl, "icmp");
3911 (void) make_proc_path(p, pl, &Ipxpath, &pathl, "ipx");
3913 (void) make_proc_path(p, pl, &Nlkpath, &pathl, "netlink");
3915 (void) make_proc_path(p, pl, &Packpath, &pathl, "packet");
3917 (void) make_proc_path(p, pl, &Rawpath, &pathl, "raw");
3918 for (i = 0; i < NSCTPPATHS; i++) {
3920 (void) make_proc_path(p, pl, &SCTPPath[i], &pathl, SCTPSfx[i]);
3923 (void) make_proc_path(p, pl, &SockStatPath, &pathl, "sockstat");
3925 (void) make_proc_path(p, pl, &TCPpath, &pathl, "tcp");
3927 (void) make_proc_path(p, pl, &UDPpath, &pathl, "udp");
3929 (void) make_proc_path(p, pl, &UDPLITEpath, &pathl, "udplite");
3931 #if defined(HASIPv6)
3933 (void) make_proc_path(p, pl, &Raw6path, &pathl, "raw6");
3935 (void) make_proc_path(p, pl, &SockStatPath6, &pathl, "sockstat6");
3937 (void) make_proc_path(p, pl, &TCP6path, &pathl, "tcp6");
3939 (void) make_proc_path(p, pl, &UDP6path, &pathl, "udp6");
3941 (void) make_proc_path(p, pl, &UDPLITE6path, &pathl, "udplite6");
3942 #endif /* defined(HASIPv6) */
3945 (void) make_proc_path(p, pl, &UNIXpath, &pathl, "unix");