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.40 2014/10/13 22:25:58 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 */
157 uint32_t ty; /* socket type */
163 * Local static values
166 static char *AX25path = (char *)NULL; /* path to AX25 /proc information */
167 static struct ax25sin **AX25sin = (struct ax25sin **)NULL;
168 /* AX25 socket info, hashed by inode */
169 static char *ax25st[] = {
173 "ESTABLISHED", /* 3 */
176 #define NAX25ST (sizeof(ax25st) / sizeof(char *))
177 static char *ICMPpath = (char *)NULL; /* path to ICMP /proc information */
178 static struct icmpin **Icmpin = (struct icmpin **)NULL;
179 /* ICMP socket info, hashed by inode */
180 static char *Ipxpath = (char *)NULL; /* path to IPX /proc information */
181 static struct ipxsin **Ipxsin = (struct ipxsin **)NULL;
182 /* IPX socket info, hashed by inode */
183 static char *Nlkpath = (char *)NULL; /* path to Netlink /proc information */
184 static struct nlksin **Nlksin = (struct nlksin **)NULL;
185 /* Netlink socket info, hashed by
187 static struct packin **Packin = (struct packin **)NULL;
188 /* packet info, hashed by inode */
189 static char *Packpath = (char *)NULL; /* path to packet /proc information */
190 static char *Rawpath = (char *)NULL; /* path to raw socket /proc
192 static struct rawsin **Rawsin = (struct rawsin **)NULL;
193 /* raw socket info, hashed by inode */
194 static char *SCTPPath[] = { /* paths to /proc/net STCP info */
195 (char *)NULL, /* 0 = /proc/net/sctp/assocs */
196 (char *)NULL /* 1 = /proc/net/sctp/eps */
198 #define NSCTPPATHS sizeof(SCTPPath)/sizeof(char *)
199 static char *SCTPSfx[] = { /* /proc/net suffixes */
200 "sctp/assocs", /* 0 = /proc/net/sctp/assocs */
201 "sctp/eps" /* 1 = /proc/net/sctp/eps */
203 static struct sctpsin **SCTPsin = (struct sctpsin **)NULL;
204 /* SCTP info, hashed by inode */
205 static char *SockStatPath = (char *)NULL;
206 /* path to /proc/net socket status */
207 static char *TCPpath = (char *)NULL; /* path to TCP /proc information */
208 static struct tcp_udp **TcpUdp = (struct tcp_udp **)NULL;
209 /* IPv4 TCP & UDP info, hashed by
211 static int TcpUdp_bucks = 0; /* dynamically sized hash bucket
212 * count for TCP and UDP -- will
213 * be a power of two */
216 static char *Raw6path = (char *)NULL; /* path to raw IPv6 /proc information */
217 static struct rawsin **Rawsin6 = (struct rawsin **)NULL;
218 /* IPv6 raw socket info, hashed by
220 static char *SockStatPath6 = (char *)NULL;
221 /* path to /proc/net IPv6 socket
223 static char *TCP6path = (char *)NULL; /* path to IPv6 TCP /proc information */
224 static struct tcp_udp6 **TcpUdp6 = (struct tcp_udp6 **)NULL;
225 /* IPv6 TCP & UDP info, hashed by
227 static int TcpUdp6_bucks = 0; /* dynamically sized hash bucket
228 * count for IPv6 TCP and UDP -- will
229 * be a power of two */
230 static char *UDP6path = (char *)NULL; /* path to IPv6 UDP /proc information */
231 static char *UDPLITE6path = (char *)NULL;
232 /* path to IPv6 UDPLITE /proc
234 #endif /* defined(HASIPv6) */
236 static char *UDPpath = (char *)NULL; /* path to UDP /proc information */
237 static char *UDPLITEpath = (char *)NULL;
238 /* path to UDPLITE /proc information */
239 static char *UNIXpath = (char *)NULL; /* path to UNIX /proc information */
240 static struct uxsin **Uxsin = (struct uxsin **)NULL;
241 /* UNIX socket info, hashed by inode */
245 * Local function prototypes
248 _PROTOTYPE(static struct ax25sin *check_ax25,(INODETYPE i));
249 _PROTOTYPE(static struct icmpin *check_icmp,(INODETYPE i));
250 _PROTOTYPE(static struct ipxsin *check_ipx,(INODETYPE i));
251 _PROTOTYPE(static struct nlksin *check_netlink,(INODETYPE i));
252 _PROTOTYPE(static struct packin *check_pack,(INODETYPE i));
253 _PROTOTYPE(static struct rawsin *check_raw,(INODETYPE i));
254 _PROTOTYPE(static struct sctpsin *check_sctp,(INODETYPE i));
255 _PROTOTYPE(static struct tcp_udp *check_tcpudp,(INODETYPE i, char **p));
256 _PROTOTYPE(static struct uxsin *check_unix,(INODETYPE i));
257 _PROTOTYPE(static void get_ax25,(char *p));
258 _PROTOTYPE(static void get_icmp,(char *p));
259 _PROTOTYPE(static void get_ipx,(char *p));
260 _PROTOTYPE(static void get_netlink,(char *p));
261 _PROTOTYPE(static void get_pack,(char *p));
262 _PROTOTYPE(static void get_raw,(char *p));
263 _PROTOTYPE(static void get_sctp,(void));
264 _PROTOTYPE(static char *get_sctpaddrs,(char **fp, int i, int nf, int *x));
265 _PROTOTYPE(static void get_tcpudp,(char *p, int pr, int clr));
266 _PROTOTYPE(static void get_unix,(char *p));
267 _PROTOTYPE(static int isainb,(char *a, char *b));
268 _PROTOTYPE(static void print_ax25info,(struct ax25sin *ap));
269 _PROTOTYPE(static void print_ipxinfo,(struct ipxsin *ip));
270 _PROTOTYPE(static char *sockty2str,(uint32_t ty, int *rf));
273 _PROTOTYPE(static struct rawsin *check_raw6,(INODETYPE i));
274 _PROTOTYPE(static struct tcp_udp6 *check_tcpudp6,(INODETYPE i, char **p));
275 _PROTOTYPE(static void get_raw6,(char *p));
276 _PROTOTYPE(static void get_tcpudp6,(char *p, int pr, int clr));
277 _PROTOTYPE(static int net6a2in6,(char *as, struct in6_addr *ad));
278 #endif /* defined(HASIPv6) */
282 * build_IPstates() -- build the TCP and UDP state tables
289 (void) enter_IPstate("TCP", "ESTABLISHED", TCP_ESTABLISHED);
290 (void) enter_IPstate("TCP", "SYN_SENT", TCP_SYN_SENT);
291 (void) enter_IPstate("TCP", "SYN_RECV", TCP_SYN_RECV);
292 (void) enter_IPstate("TCP", "FIN_WAIT1", TCP_FIN_WAIT1);
293 (void) enter_IPstate("TCP", "FIN_WAIT2", TCP_FIN_WAIT2);
294 (void) enter_IPstate("TCP", "TIME_WAIT", TCP_TIME_WAIT);
295 (void) enter_IPstate("TCP", "CLOSE", TCP_CLOSE);
296 (void) enter_IPstate("TCP", "CLOSE_WAIT", TCP_CLOSE_WAIT);
297 (void) enter_IPstate("TCP", "LAST_ACK", TCP_LAST_ACK);
298 (void) enter_IPstate("TCP", "LISTEN", TCP_LISTEN);
299 (void) enter_IPstate("TCP", "CLOSING", TCP_CLOSING);
300 (void) enter_IPstate("TCP", "CLOSED", 0);
301 (void) enter_IPstate("TCP", (char *)NULL, 0);
307 * check_ax25() - check for AX25 socket file
310 static struct ax25sin *
312 INODETYPE i; /* socket file's inode number */
318 for (ap = AX25sin[h]; ap; ap = ap->next) {
322 return((struct ax25sin *)NULL);
328 * check_icmp() - check for ICMP socket
331 static struct icmpin *
333 INODETYPE i; /* socket file's inode number */
336 struct icmpin *icmpp;
339 for (icmpp = Icmpin[h]; icmpp; icmpp = icmpp->next) {
340 if (i == icmpp->inode)
343 return((struct icmpin *)NULL);
348 * check_ipx() - check for IPX socket file
351 static struct ipxsin *
353 INODETYPE i; /* socket file's inode number */
359 for (ip = Ipxsin[h]; ip; ip = ip->next) {
363 return((struct ipxsin *)NULL);
368 * check_netlink() - check for Netlink socket file
371 static struct nlksin *
373 INODETYPE i; /* socket file's inode number */
379 for (lp = Nlksin[h]; lp; lp = lp->next) {
383 return((struct nlksin *)NULL);
388 * check_pack() - check for packet file
391 static struct packin *
393 INODETYPE i; /* packet file's inode number */
399 for (pp = Packin[h]; pp; pp = pp->next) {
403 return((struct packin *)NULL);
408 * check_raw() - check for raw socket file
411 static struct rawsin *
413 INODETYPE i; /* socket file's inode number */
419 for (rp = Rawsin[h]; rp; rp = rp->next) {
423 return((struct rawsin *)NULL);
428 * check_sctp() - check for SCTP socket file
431 static struct sctpsin *
433 INODETYPE i; /* socket file's inode number */
439 for (sp = SCTPsin[h]; sp; sp = sp->next) {
443 return((struct sctpsin *)NULL);
448 * check_tcpudp() - check for IPv4 TCP or UDP socket file
451 static struct tcp_udp *
453 INODETYPE i; /* socket file's inode number */
454 char **p; /* protocol return */
460 for (tp = TcpUdp[h]; tp; tp = tp->next) {
461 if (i == tp->inode) {
478 return((struct tcp_udp *)NULL);
484 * check_raw6() - check for raw IPv6 socket file
487 static struct rawsin *
489 INODETYPE i; /* socket file's inode number */
495 for (rp = Rawsin6[h]; rp; rp = rp->next) {
499 return((struct rawsin *)NULL);
504 * check_tcpudp6() - check for IPv6 TCP or UDP socket file
507 static struct tcp_udp6 *
509 INODETYPE i; /* socket file's inode number */
510 char **p; /* protocol return */
513 struct tcp_udp6 *tp6;
516 for (tp6 = TcpUdp6[h]; tp6; tp6 = tp6->next) {
517 if (i == tp6->inode) {
518 switch (tp6->proto) {
534 return((struct tcp_udp6 *)NULL);
536 #endif /* defined(HASIPv6) */
540 * check_unix() - check for UNIX domain socket
543 static struct uxsin *
545 INODETYPE i; /* socket file's inode number */
551 for (up = Uxsin[h]; up; up = up->next) {
555 return((struct uxsin *)NULL);
560 * get_ax25() - get /proc/net/ax25 info
565 char *p; /* /proc/net/ipx path */
567 struct ax25sin *ap, *np;
569 char buf[MAXPATHLEN], *da, *dev_ch, *ep, **fp, *sa;
572 unsigned long rq, sq, state;
574 unsigned char rqs, sqs;
575 static char *vbuf = (char *)NULL;
576 static size_t vsz = (size_t)0;
578 * Do second time cleanup or first time setup.
581 for (h = 0; h < INOBUCKS; h++) {
582 for (ap = AX25sin[h]; ap; ap = np) {
585 (void) free((FREE_P *)ap->da);
587 (void) free((FREE_P *)ap->dev_ch);
589 (void) free((FREE_P *)ap->sa);
590 (void) free((FREE_P *)ap);
592 AX25sin[h] = (struct ax25sin *)NULL;
595 AX25sin = (struct ax25sin **)calloc(INOBUCKS,
596 sizeof(struct ax25sin *));
598 (void) fprintf(stderr,
599 "%s: can't allocate %d AX25 hash pointer bytes\n",
600 Pn, (int)(INOBUCKS * sizeof(struct ax25sin *)));
605 * Open the /proc/net/ax25 file, assign a page size buffer to the stream,
606 * and read it. Store AX25 socket info in the AX25sin[] hash buckets.
608 if (!(as = open_proc_stream(p, "r", &vbuf, &vsz, 0)))
610 while (fgets(buf, sizeof(buf) - 1, as)) {
611 if ((nf = get_fields(buf, (char *)NULL, &fp, (int *)NULL, 0)) < 24)
614 * /proc/net/ax25 has no title line, a very poor deficiency in its
617 * The ax25_get_info() function in kern module .../net/ax25/af_ax25.c
618 * says the format of the lines in the file is:
620 * magic dev src_addr dest_addr,digi1,digi2,.. st vs vr va t1 t1 \
621 * t2 t2 t3 t3 idle idle n2 n2 rtt window paclen Snd-Q Rcv-Q \
624 * The code in this function is forced to assume that format is in
629 * Assemble the inode number and see if it has already been recorded.
630 * If it has, skip this line.
633 if (!fp[23] || !*fp[23]
634 || (inode = strtoull(fp[23], &ep, 0)) == ULONG_MAX
637 h = INOHASH((INODETYPE)inode);
638 for (ap = AX25sin[h]; ap; ap = ap->next) {
639 if (inode == ap->inode)
645 * Assemble the send and receive queue values and the state.
647 rq = sq = (unsigned long)0;
648 rqs = sqs = (unsigned char)0;
650 if (!fp[21] || !*fp[21]
651 || (sq = strtoul(fp[21], &ep, 0)) == ULONG_MAX || !ep || *ep)
653 sqs = (unsigned char)1;
655 if (!fp[22] || !*fp[22]
656 || (rq = strtoul(fp[22], &ep, 0)) == ULONG_MAX || !ep || *ep)
658 rqs = (unsigned char)1;
660 if (!fp[4] || !*fp[4]
661 || (state = strtoul(fp[4], &ep, 0)) == ULONG_MAX || !ep || *ep)
664 * Allocate space for the destination address.
666 if (!fp[3] || !*fp[3])
668 else if ((len = strlen(fp[3]))) {
669 if (!(da = (char *)malloc(len + 1))) {
670 (void) fprintf(stderr,
671 "%s: can't allocate %d destination AX25 addr bytes: %s\n",
672 Pn, (int)(len + 1), fp[3]);
675 (void) snpf(da, len + 1, "%s", fp[3]);
679 * Allocate space for the source address.
681 if (!fp[2] || !*fp[2])
683 else if ((len = strlen(fp[2]))) {
684 if (!(sa = (char *)malloc(len + 1))) {
685 (void) fprintf(stderr,
686 "%s: can't allocate %d source AX25 address bytes: %s\n",
687 Pn, (int)(len + 1), fp[2]);
690 (void) snpf(sa, len + 1, "%s", fp[2]);
694 * Allocate space for the device characters.
696 if (!fp[1] || !*fp[1])
697 dev_ch = (char *)NULL;
698 else if ((len = strlen(fp[1]))) {
699 if (!(dev_ch = (char *)malloc(len + 1))) {
700 (void) fprintf(stderr,
701 "%s: can't allocate %d destination AX25 dev bytes: %s\n",
702 Pn, (int)(len + 1), fp[1]);
705 (void) snpf(dev_ch, len + 1, "%s", fp[1]);
707 dev_ch = (char *)NULL;
709 * Allocate space for an ax25sin entry, fill it, and link it to its
712 if (!(ap = (struct ax25sin *)malloc(sizeof(struct ax25sin)))) {
713 (void) fprintf(stderr,
714 "%s: can't allocate %d byte ax25sin structure\n",
715 Pn, (int)sizeof(struct ax25sin));
726 ap->state = (int)state;
727 ap->next = AX25sin[h];
735 * get_icmp() - get ICMP net info
740 char *p; /* /proc/net/icmp path */
742 char buf[MAXPATHLEN], *ep, **fp, *la, *ra;
746 struct icmpin *np, *icmpp;
748 MALLOC_S lal, ral, spl;
749 static char *vbuf = (char *)NULL;
750 static size_t vsz = (size_t)0;
753 * Do second time cleanup or first time setup.
756 for (h = 0; h < INOBUCKS; h++) {
757 for (icmpp = Icmpin[h]; icmpp; icmpp = np) {
759 (void) free((FREE_P *)icmpp);
761 Icmpin[h] = (struct icmpin *)NULL;
764 Icmpin = (struct icmpin **)calloc(INOBUCKS,
765 sizeof(struct icmpin *));
767 (void) fprintf(stderr,
768 "%s: can't allocate %d icmp hash pointer bytes\n",
769 Pn, (int)(INOBUCKS * sizeof(struct icmpin *)));
774 * Open the /proc/net/icmp file, assign a page size buffer to its stream,
775 * and read the file. Store icmp info in the Icmpin[] hash buckets.
777 if (!(xs = open_proc_stream(p, "r", &vbuf, &vsz, 0)))
779 while (fgets(buf, sizeof(buf) - 1, xs)) {
780 if (get_fields(buf, (char *)NULL, &fp, (int *)NULL, 0) < 11)
785 * Check the column labels in the first line.
788 * In column header, "inode" is at the 11th column.
789 * However, in data rows, inode appears at the 9th column.
791 * In column header, "tx_queue" and "rx_queue" are separated
792 * by a space. It is the same for "tr" and "tm->when"; in
793 * data rows they are connected with ":".
795 if (!fp[1] || strcmp(fp[1], "local_address")
796 || !fp[2] || strcmp(fp[2], "rem_address")
797 || !fp[11] || strcmp(fp[11], "inode"))
800 (void) fprintf(stderr,
801 "%s: WARNING: unsupported format: %s\n",
810 * Assemble the inode number and see if the inode is already
814 if (!fp[9] || !*fp[9]
815 || (inode = strtoull(fp[9], &ep, 0)) == ULONG_MAX
819 for (icmpp = Icmpin[h]; icmpp; icmpp = icmpp->next) {
820 if (inode == icmpp->inode)
826 * Save the local address, and remote address.
828 if (!fp[1] || !*fp[1] || (lal = strlen(fp[1])) < 1) {
832 if (!(la = (char *)malloc(lal + 1))) {
833 (void) fprintf(stderr,
834 "%s: can't allocate %d local icmp address bytes: %s\n",
835 Pn, (int)(lal + 1), fp[1]);
838 (void) snpf(la, lal + 1, "%s", fp[1]);
840 if (!fp[2] || !*fp[2] || (ral = strlen(fp[2])) < 1) {
844 if (!(ra = (char *)malloc(ral + 1))) {
845 (void) fprintf(stderr,
846 "%s: can't allocate %d remote icmp address bytes: %s\n",
847 Pn, (int)(ral + 1), fp[2]);
850 (void) snpf(ra, ral + 1, "%s", fp[2]);
853 * Allocate space for a icmpin entry, fill it, and link it to its
856 if (!(icmpp = (struct icmpin *)malloc(sizeof(struct icmpin)))) {
857 (void) fprintf(stderr,
858 "%s: can't allocate %d byte icmp structure\n",
859 Pn, (int)sizeof(struct icmpin));
862 icmpp->inode = inode;
867 icmpp->next = Icmpin[h];
876 * get_ipx() - get /proc/net/ipx info
881 char *p; /* /proc/net/ipx path */
883 char buf[MAXPATHLEN], *ep, **fp, *la, *ra;
887 unsigned long rxq, state, txq;
888 struct ipxsin *ip, *np;
890 static char *vbuf = (char *)NULL;
891 static size_t vsz = (size_t)0;
894 * Do second time cleanup or first time setup.
897 for (h = 0; h < INOBUCKS; h++) {
898 for (ip = Ipxsin[h]; ip; ip = np) {
901 (void) free((FREE_P *)ip->la);
903 (void) free((FREE_P *)ip->ra);
904 (void) free((FREE_P *)ip);
906 Ipxsin[h] = (struct ipxsin *)NULL;
909 Ipxsin = (struct ipxsin **)calloc(INOBUCKS,
910 sizeof(struct ipxsin *));
912 (void) fprintf(stderr,
913 "%s: can't allocate %d IPX hash pointer bytes\n",
914 Pn, (int)(INOBUCKS * sizeof(struct ipxsin *)));
919 * Open the /proc/net/ipx file, assign a page size buffer to the stream,
920 * and read it. Store IPX socket info in the Ipxsin[] hash buckets.
922 if (!(xs = open_proc_stream(p, "r", &vbuf, &vsz, 0)))
924 while (fgets(buf, sizeof(buf) - 1, xs)) {
925 if (get_fields(buf, (char *)NULL, &fp, (int *)NULL, 0) < 7)
930 * Check the column labels in the first line.
932 if (!fp[0] || strcmp(fp[0], "Local_Address")
933 || !fp[1] || strcmp(fp[1], "Remote_Address")
934 || !fp[2] || strcmp(fp[2], "Tx_Queue")
935 || !fp[3] || strcmp(fp[3], "Rx_Queue")
936 || !fp[4] || strcmp(fp[4], "State")
937 || !fp[5] || strcmp(fp[5], "Uid")
938 || !fp[6] || strcmp(fp[6], "Inode"))
941 (void) fprintf(stderr,
942 "%s: WARNING: unsupported format: %s\n",
951 * Assemble the inode number and see if the inode is already
955 if (!fp[6] || !*fp[6]
956 || (inode = strtoull(fp[6], &ep, 0)) == ULONG_MAX
960 for (ip = Ipxsin[h]; ip; ip = ip->next) {
961 if (inode == ip->inode)
967 * Assemble the transmit and receive queue values and the state.
970 if (!fp[2] || !*fp[2]
971 || (txq = strtoul(fp[2], &ep, 16)) == ULONG_MAX || !ep || *ep)
974 if (!fp[3] || !*fp[3]
975 || (rxq = strtoul(fp[3], &ep, 16)) == ULONG_MAX || !ep || *ep)
978 if (!fp[4] || !*fp[4]
979 || (state = strtoul(fp[4], &ep, 16)) == ULONG_MAX || !ep || *ep)
982 * Allocate space for the local address, unless it is "Not_Connected".
984 if (!fp[0] || !*fp[0] || strcmp(fp[0], "Not_Connected") == 0)
986 else if ((len = strlen(fp[0]))) {
987 if (!(la = (char *)malloc(len + 1))) {
988 (void) fprintf(stderr,
989 "%s: can't allocate %d local IPX address bytes: %s\n",
990 Pn, (int)(len + 1), fp[0]);
993 (void) snpf(la, len + 1, "%s", fp[0]);
997 * Allocate space for the remote address, unless it is "Not_Connected".
999 if (!fp[1] || !*fp[1] || strcmp(fp[1], "Not_Connected") == 0)
1001 else if ((len = strlen(fp[1]))) {
1002 if (!(ra = (char *)malloc(len + 1))) {
1003 (void) fprintf(stderr,
1004 "%s: can't allocate %d remote IPX address bytes: %s\n",
1005 Pn, (int)(len + 1), fp[1]);
1008 (void) snpf(ra, len + 1, "%s", fp[1]);
1012 * Allocate space for an ipxsin entry, fill it, and link it to its
1015 if (!(ip = (struct ipxsin *)malloc(sizeof(struct ipxsin)))) {
1016 (void) fprintf(stderr,
1017 "%s: can't allocate %d byte ipxsin structure\n",
1018 Pn, (int)sizeof(struct ipxsin));
1026 ip->state = (int)state;
1027 ip->next = Ipxsin[h];
1035 * get_netlink() - get /proc/net/netlink info
1040 char *p; /* /proc/net/netlink path */
1042 char buf[MAXPATHLEN], *ep, **fp;
1046 struct nlksin *np, *lp;
1047 static char *vbuf = (char *)NULL;
1048 static size_t vsz = (size_t)0;
1051 * Do second time cleanup or first time setup.
1054 for (h = 0; h < INOBUCKS; h++) {
1055 for (lp = Nlksin[h]; lp; lp = np) {
1057 (void) free((FREE_P *)lp);
1059 Nlksin[h] = (struct nlksin *)NULL;
1062 Nlksin = (struct nlksin **)calloc(INOBUCKS,sizeof(struct nlksin *));
1064 (void) fprintf(stderr,
1065 "%s: can't allocate %d netlink hash pointer bytes\n",
1066 Pn, (int)(INOBUCKS * sizeof(struct nlksin *)));
1071 * Open the /proc/net/netlink file, assign a page size buffer to its stream,
1072 * and read the file. Store Netlink info in the Nlksin[] hash buckets.
1074 if (!(xs = open_proc_stream(p, "r", &vbuf, &vsz, 0)))
1076 while (fgets(buf, sizeof(buf) - 1, xs)) {
1077 if (get_fields(buf, (char *)NULL, &fp, (int *)NULL, 0) < 10)
1082 * Check the column labels in the first line.
1084 if (!fp[1] || strcmp(fp[1], "Eth")
1085 || !fp[9] || strcmp(fp[9], "Inode"))
1088 (void) fprintf(stderr,
1089 "%s: WARNING: unsupported format: %s\n",
1098 * Assemble the inode number and see if the inode is already
1102 if (!fp[9] || !*fp[9]
1103 || (inode = strtoull(fp[9], &ep, 0)) == ULONG_MAX
1107 for (lp = Nlksin[h]; lp; lp = lp->next) {
1108 if (inode == lp->inode)
1114 * Save the protocol from the Eth column.
1116 if (!fp[1] || !*fp[1] || (strlen(fp[1])) < 1)
1120 * Allocate space for a nlksin entry, fill it, and link it to its
1123 if (!(lp = (struct nlksin *)malloc(sizeof(struct nlksin)))) {
1124 (void) fprintf(stderr,
1125 "%s: can't allocate %d byte Netlink structure\n",
1126 Pn, (int)sizeof(struct nlksin));
1131 lp->next = Nlksin[h];
1139 * get_pack() - get /proc/net/packet info
1144 char *p; /* /proc/net/raw path */
1146 char buf[MAXPATHLEN], *ep, **fp;
1150 struct packin *np, *pp;
1152 static char *vbuf = (char *)NULL;
1153 static size_t vsz = (size_t)0;
1156 * Do second time cleanup or first time setup.
1159 for (h = 0; h < INOBUCKS; h++) {
1160 for (pp = Packin[h]; pp; pp = np) {
1162 (void) free((FREE_P *)pp);
1164 Packin[h] = (struct packin *)NULL;
1167 Packin = (struct packin **)calloc(INOBUCKS,
1168 sizeof(struct packin *));
1170 (void) fprintf(stderr,
1171 "%s: can't allocate %d packet hash pointer bytes\n",
1172 Pn, (int)(INOBUCKS * sizeof(struct packin *)));
1177 * Open the /proc/net/packet file, assign a page size buffer to its stream,
1178 * and read the file. Store packet info in the Packin[] hash buckets.
1180 if (!(xs = open_proc_stream(p, "r", &vbuf, &vsz, 0)))
1182 while (fgets(buf, sizeof(buf) - 1, xs)) {
1183 if (get_fields(buf, (char *)NULL, &fp, (int *)NULL, 0) < 9)
1188 * Check the column labels in the first line.
1190 if (!fp[2] || strcmp(fp[2], "Type")
1191 || !fp[3] || strcmp(fp[3], "Proto")
1192 || !fp[8] || strcmp(fp[8], "Inode"))
1195 (void) fprintf(stderr,
1196 "%s: WARNING: unsupported format: %s\n",
1205 * Assemble the inode number and see if the inode is already
1209 if (!fp[8] || !*fp[8]
1210 || (inode = strtoull(fp[8], &ep, 0)) == ULONG_MAX
1214 for (pp = Packin[h]; pp; pp = pp->next) {
1215 if (inode == pp->inode)
1221 * Save the socket type and protocol.
1223 if (!fp[2] || !*fp[2] || (strlen(fp[2])) < 1)
1227 if (!fp[3] || !*fp[3] || (strlen(fp[3]) < 1)
1228 || ((pr = strtoul(fp[3], &ep, 16)) == ULONG_MAX) || !ep || *ep)
1231 * Allocate space for a packin entry, fill it, and link it to its
1234 if (!(pp = (struct packin *)malloc(sizeof(struct packin)))) {
1235 (void) fprintf(stderr,
1236 "%s: can't allocate %d byte packet structure\n",
1237 Pn, (int)sizeof(struct packin));
1243 pp->next = Packin[h];
1251 * get_raw() - get /proc/net/raw info
1256 char *p; /* /proc/net/raw path */
1258 char buf[MAXPATHLEN], *ep, **fp, *la, *ra, *sp;
1262 struct rawsin *np, *rp;
1263 MALLOC_S lal, ral, spl;
1264 static char *vbuf = (char *)NULL;
1265 static size_t vsz = (size_t)0;
1268 * Do second time cleanup or first time setup.
1271 for (h = 0; h < INOBUCKS; h++) {
1272 for (rp = Rawsin[h]; rp; rp = np) {
1275 (void) free((FREE_P *)rp->la);
1277 (void) free((FREE_P *)rp->ra);
1278 (void) free((FREE_P *)rp);
1280 Rawsin[h] = (struct rawsin *)NULL;
1283 Rawsin = (struct rawsin **)calloc(INOBUCKS,
1284 sizeof(struct rawsin *));
1286 (void) fprintf(stderr,
1287 "%s: can't allocate %d raw hash pointer bytes\n",
1288 Pn, (int)(INOBUCKS * sizeof(struct rawsin *)));
1293 * Open the /proc/net/raw file, assign a page size buffer to its stream,
1294 * and read the file. Store raw socket info in the Rawsin[] hash buckets.
1296 if (!(xs = open_proc_stream(p, "r", &vbuf, &vsz, 0)))
1298 while (fgets(buf, sizeof(buf) - 1, xs)) {
1299 if (get_fields(buf, (char *)NULL, &fp, (int *)NULL, 0) < nf)
1304 * Check the column labels in the first line.
1306 if (!fp[1] || strcmp(fp[1], "local_address")
1307 || !fp[2] || strcmp(fp[2], "rem_address")
1308 || !fp[3] || strcmp(fp[3], "st")
1309 || !fp[11] || strcmp(fp[11], "inode"))
1312 (void) fprintf(stderr,
1313 "%s: WARNING: unsupported format: %s\n",
1322 * Assemble the inode number and see if the inode is already
1326 if (!fp[9] || !*fp[9]
1327 || (inode = strtoull(fp[9], &ep, 0)) == ULONG_MAX
1331 for (rp = Rawsin[h]; rp; rp = rp->next) {
1332 if (inode == rp->inode)
1338 * Save the local address, remote address, and state.
1340 if (!fp[1] || !*fp[1] || (lal = strlen(fp[1])) < 1) {
1344 if (!(la = (char *)malloc(lal + 1))) {
1345 (void) fprintf(stderr,
1346 "%s: can't allocate %d local raw address bytes: %s\n",
1347 Pn, (int)(lal + 1), fp[1]);
1350 (void) snpf(la, lal + 1, "%s", fp[1]);
1352 if (!fp[2] || !*fp[2] || (ral = strlen(fp[2])) < 1) {
1356 if (!(ra = (char *)malloc(ral + 1))) {
1357 (void) fprintf(stderr,
1358 "%s: can't allocate %d remote raw address bytes: %s\n",
1359 Pn, (int)(ral + 1), fp[2]);
1362 (void) snpf(ra, ral + 1, "%s", fp[2]);
1364 if (!fp[3] || !*fp[3] || (spl = strlen(fp[3])) < 1) {
1368 if (!(sp = (char *)malloc(spl + 1))) {
1369 (void) fprintf(stderr,
1370 "%s: can't allocate %d remote raw state bytes: %s\n",
1371 Pn, (int)(spl + 1), fp[2]);
1374 (void) snpf(sp, spl + 1, "%s", fp[3]);
1377 * Allocate space for an rawsin entry, fill it, and link it to its
1380 if (!(rp = (struct rawsin *)malloc(sizeof(struct rawsin)))) {
1381 (void) fprintf(stderr,
1382 "%s: can't allocate %d byte rawsin structure\n",
1383 Pn, (int)sizeof(struct rawsin));
1393 rp->next = Rawsin[h];
1401 * get_sctp() - get /proc/net/sctp/assocs info
1407 char buf[MAXPATHLEN], *a, *ep, **fp, *id, *la, *lp, *ra, *rp, *ta;
1408 int d, err, fl, h, i, j, nf, ty, x;
1411 struct sctpsin *sp, *np;
1413 static char *vbuf = (char *)NULL;
1414 static size_t vsz = (size_t)0;
1416 * Do second time cleanup or first time setup.
1419 for (h = 0; h < INOBUCKS; h++) {
1420 for (sp = SCTPsin[h]; sp; sp = np) {
1423 (void) free((FREE_P *)sp->addr);
1425 (void) free((FREE_P *)sp->assocID);
1427 (void) free((FREE_P *)sp->lport);
1429 (void) free((FREE_P *)sp->rport);
1431 (void) free((FREE_P *)sp->laddrs);
1433 (void) free((FREE_P *)sp->raddrs);
1434 (void) free((FREE_P *)sp);
1436 SCTPsin[h] = (struct sctpsin *)NULL;
1439 SCTPsin = (struct sctpsin **)calloc(INOBUCKS,
1440 sizeof(struct sctpsin *));
1442 (void) fprintf(stderr,
1443 "%s: can't allocate %d SCTP hash pointer bytes\n",
1444 Pn, (int)(INOBUCKS * sizeof(struct sctpsin *)));
1449 * Open the /proc/net/sctp files, assign a page size buffer to the streams,
1450 * and read them. Store SCTP socket info in the SCTPsin[] hash buckets.
1452 for (i = 0; i < NSCTPPATHS; i++ ) {
1453 if (!(ss = open_proc_stream(SCTPPath[i], "r", &vbuf, &vsz, 0)))
1456 while (fgets(buf, sizeof(buf) - 1, ss)) {
1457 if ((nf = get_fields(buf, (char *)NULL, &fp, (int *)NULL, 0))
1465 * Check the column labels in the first line.
1470 if (!fp[0] || strcmp(fp[0], "ASSOC")
1471 || !fp[6] || strcmp(fp[6], "ASSOC-ID")
1472 || !fp[10] || strcmp(fp[10], "INODE")
1473 || !fp[11] || strcmp(fp[11], "LPORT")
1474 || !fp[12] || strcmp(fp[12], "RPORT")
1475 || !fp[13] || strcmp(fp[13], "LADDRS")
1476 || !fp[14] || strcmp(fp[14], "<->")
1477 || !fp[15] || strcmp(fp[15], "RADDRS")
1483 if (!fp[0] || strcmp(fp[0], "ENDPT")
1484 || !fp[5] || strcmp(fp[5], "LPORT")
1485 || !fp[7] || strcmp(fp[7], "INODE")
1486 || !fp[8] || strcmp(fp[8], "LADDRS")
1493 (void) fprintf(stderr,
1494 "%s: WARNING: unsupported format: %s\n",
1502 * Assemble the inode number and see if it has already been
1507 if (!fp[j] || !*fp[j]
1508 || (inode = strtoull(fp[j], &ep, 0)) == ULONG_MAX
1511 h = INOHASH((INODETYPE)inode);
1512 for (sp = SCTPsin[h]; sp; sp = sp->next) {
1513 if (inode == sp->inode)
1517 * Set the entry type.
1520 ty = (sp->type == i) ? i : 3;
1524 * Allocate space for this line's sctpsin members.
1526 * The association or endpoint address is in the first field.
1528 a = sp ? sp->addr : (char *)NULL;
1529 if (fp[0] && *fp[0] && (len = strlen(fp[0]))) {
1531 if (isainb(fp[0], a)) {
1533 a = (char *)realloc((MALLOC_P *)a, plen + len + 2);
1539 a = (char *)malloc(len + 1);
1543 (void) fprintf(stderr,
1544 "%s: can't allocate %d SCTP ASSOC bytes: %s\n",
1545 Pn, (int)(len + 1), fp[0]);
1550 (void) snpf((a + plen), len + 2, ",%s", fp[0]);
1552 (void) snpf(a, len + 1, "%s", fp[0]);
1556 * The association ID is in the seventh field.
1558 id = sp ? sp->assocID : (char *)NULL;
1559 if (!i && fp[6] && *fp[6] && (len = strlen(fp[6]))) {
1561 if (isainb(fp[6], id)) {
1563 id = (char *)realloc((MALLOC_P *)id,plen+len+2);
1569 id = (char *)malloc(len + 1);
1573 (void) fprintf(stderr,
1574 "%s: can't allocate %d SCTP ASSOC-ID bytes: %s\n",
1575 Pn, (int)(len + 1), fp[6]);
1580 (void) snpf((id + plen), len + 2, ",%s", fp[6]);
1582 (void) snpf(id, len + 1, "%s", fp[6]);
1586 * The field number for the local port depends on the entry type.
1589 lp = sp ? sp->lport : (char *)NULL;
1590 if (fp[j] && *fp[j] && (len = strlen(fp[j]))) {
1592 if (isainb(fp[j], lp)) {
1594 lp = (char *)realloc((MALLOC_P *)lp,plen+len+2);
1600 lp = (char *)malloc(len + 1);
1604 (void) fprintf(stderr,
1605 "%s: can't allocate %d SCTP LPORT bytes: %s\n",
1606 Pn, (int)(len + 1), fp[j]);
1611 (void) snpf((lp + plen), len + 2, ",%s", fp[j]);
1613 (void) snpf(lp, len + 1, "%s", fp[j]);
1617 * The field number for the remote port depends on the entry type.
1619 rp = sp ? sp->rport : (char *)NULL;
1620 if (!i && fp[12] && *fp[12] && (len = strlen(fp[12]))) {
1622 if (isainb(fp[12], rp)) {
1624 rp = (char *)realloc((MALLOC_P *)rp,plen+len+2);
1630 rp = (char *)malloc(len + 1);
1634 (void) fprintf(stderr,
1635 "%s: can't allocate %d SCTP RPORT bytes: %s\n",
1636 Pn, (int)(len + 1), fp[12]);
1641 (void) snpf((rp + plen), len + 2, ",%s", fp[12]);
1643 (void) snpf(rp, len + 1, "%s", fp[12]);
1647 * The local addresses begin in a field whose number depends on
1651 la = sp ? sp->laddrs : (char *)NULL;
1652 if (fp[j] && *fp[j] && (len = strlen(fp[j]))) {
1653 if (!(ta = get_sctpaddrs(fp, j, nf, &x))) {
1654 (void) fprintf(stderr,
1655 "%s: can't allocate %d SCTP LADDRS bytes\n",
1660 if (isainb(ta, la)) {
1663 if (!(la=(char *)realloc((MALLOC_P *)la,plen+len+2))
1665 (void) fprintf(stderr,
1666 "%s: can't reallocate %d SCTP LADDRS bytes\n",
1670 (void) snpf(la + plen, len + 2, ",%s", ta);
1671 (void) free((FREE_P *)ta);
1677 * The remote addresses begin after the local addresses, but only
1678 * for the ASSOC type.
1680 ra = sp ? sp->raddrs : (char *)NULL;
1681 if (!i && x && fp[x+1] && *fp[x+1] && (len = strlen(fp[x+1]))) {
1682 if (!(ta = get_sctpaddrs(fp, x + 1, nf, &x))) {
1683 (void) fprintf(stderr,
1684 "%s: can't allocate %d SCTP RADDRS bytes\n",
1689 if (isainb(ta, ra)) {
1692 if (!(ra=(char *)realloc((MALLOC_P *)ra,plen+len+2))
1694 (void) fprintf(stderr,
1695 "%s: can't reallocate %d SCTP RADDRS bytes\n",
1699 (void) snpf(ra + plen, len + 2, ",%s", ta);
1700 (void) free((FREE_P *)ta);
1706 * If no matching sctpsin entry was found for this inode, allocate
1707 * space for a new sctpsin entry, fill it, and link it to its hash
1708 * bucket. Update a matching entry.
1711 if (!(sp = (struct sctpsin *)malloc(sizeof(struct sctpsin))) ) {
1712 (void) fprintf(stderr,
1713 "%s: can't allocate %d byte sctpsin structure\n",
1714 Pn, (int)sizeof(struct sctpsin));
1718 sp->next = SCTPsin[h];
1735 get_sctpaddrs(fp, i, nf, x)
1736 char **fp; /* field pointers */
1737 int i; /* first address field index in fp */
1738 int nf; /* number of fields */
1739 int *x; /* index of first "<->" field entry */
1741 MALLOC_S al = (MALLOC_S)0;
1742 char *cp = (char *)NULL;
1747 if ((i >= nf) || !fp[i] || !*fp[i] || !(tl = strlen(fp[i])))
1749 if (!strcmp(fp[i], "<->")) {
1753 if (!strchr(fp[i], (int)'.') && !strchr(fp[i], (int)':'))
1756 cp = (char *)realloc((MALLOC_P *)cp, al + tl + 1);
1758 cp = (char *)malloc(al + tl + 1);
1762 *(cp + al - 1) = ',';
1763 (void) strncpy(al ? (cp + al) : cp, fp[i], tl);
1765 *(cp + al - 1) = '\0';
1772 * get_tcpudp() - get IPv4 TCP, UDP or UDPLITE net info
1776 get_tcpudp(p, pr, clr)
1777 char *p; /* /proc/net/{tcp,udp} path */
1778 int pr; /* protocol: 0 = TCP, 1 = UDP,
1780 int clr; /* 1 == clear the table */
1782 char buf[MAXPATHLEN], *ep, **fp;
1783 unsigned long faddr, fport, laddr, lport, rxq, state, txq;
1787 struct tcp_udp *np, *tp;
1788 static char *vbuf = (char *)NULL;
1789 static size_t vsz = (size_t)0;
1791 * Delete previous table contents.
1795 for (h = 0; h < TcpUdp_bucks; h++) {
1796 for (tp = TcpUdp[h]; tp; tp = np) {
1798 (void) free((FREE_P *)tp);
1800 TcpUdp[h] = (struct tcp_udp *)NULL;
1804 * If no hash buckets have been allocated, do so now.
1809 * Open the /proc/net/sockstat file and establish the hash bucket
1810 * count from its "sockets: used" line.
1812 TcpUdp_bucks = INOBUCKS;
1813 if ((fs = fopen(SockStatPath, "r"))) {
1814 while(fgets(buf, sizeof(buf) - 1, fs)) {
1815 if (get_fields(buf, (char *)NULL, &fp, (int *)NULL, 0) != 3)
1817 if (!fp[0] || strcmp(fp[0], "sockets:")
1818 || !fp[1] || strcmp(fp[1], "used")
1819 || !fp[2] || !*fp[2])
1821 if ((h = atoi(fp[2])) < 1)
1823 while (TcpUdp_bucks < h)
1829 if (!(TcpUdp = (struct tcp_udp **)calloc(TcpUdp_bucks,
1830 sizeof(struct tcp_udp *))))
1832 (void) fprintf(stderr,
1833 "%s: can't allocate %d bytes for TCP&UDP hash buckets\n",
1834 Pn, (int)(TcpUdp_bucks * sizeof(struct tcp_udp *)));
1839 * Open the /proc/net file, assign a page size buffer to the stream, and
1842 if (!(fs = open_proc_stream(p, "r", &vbuf, &vsz, 0)))
1845 while(fgets(buf, sizeof(buf) - 1, fs)) {
1847 (nf == 12) ? (char *)NULL : ":",
1848 &fp, (int *)NULL, 0)
1852 if (!fp[1] || strcmp(fp[1], "local_address")
1853 || !fp[2] || strcmp(fp[2], "rem_address")
1854 || !fp[3] || strcmp(fp[3], "st")
1855 || !fp[4] || strcmp(fp[4], "tx_queue")
1856 || !fp[5] || strcmp(fp[5], "rx_queue")
1857 || !fp[11] || strcmp(fp[11], "inode"))
1860 (void) fprintf(stderr,
1861 "%s: WARNING: unsupported format: %s\n",
1870 * Get the local and remote addresses.
1873 if (!fp[1] || !*fp[1]
1874 || (laddr = strtoul(fp[1], &ep, 16)) == ULONG_MAX || !ep || *ep)
1877 if (!fp[2] || !*fp[2]
1878 || (lport = strtoul(fp[2], &ep, 16)) == ULONG_MAX || !ep || *ep)
1881 if (!fp[3] || !*fp[3]
1882 || (faddr = strtoul(fp[3], &ep, 16)) == ULONG_MAX || !ep || *ep)
1885 if (!fp[4] || !*fp[4]
1886 || (fport = strtoul(fp[4], &ep, 16)) == ULONG_MAX || !ep || *ep)
1889 * Get the state and queue sizes.
1892 if (!fp[5] || !*fp[5]
1893 || (state = strtoul(fp[5], &ep, 16)) == ULONG_MAX || !ep || *ep)
1896 if (!fp[6] || !*fp[6]
1897 || (txq = strtoul(fp[6], &ep, 16)) == ULONG_MAX || !ep || *ep)
1900 if (!fp[7] || !*fp[7]
1901 || (rxq = strtoul(fp[7], &ep, 16)) == ULONG_MAX || !ep || *ep)
1904 * Get the inode and use it for hashing and searching.
1907 if (!fp[13] || !*fp[13]
1908 || (inode = strtoull(fp[13], &ep, 0)) == ULONG_MAX || !ep || *ep)
1910 h = TCPUDPHASH(inode);
1911 for (tp = TcpUdp[h]; tp; tp = tp->next) {
1912 if (tp->inode == inode)
1918 * Create a new entry and link it to its hash bucket.
1920 if (!(tp = (struct tcp_udp *)malloc(sizeof(struct tcp_udp)))) {
1921 (void) fprintf(stderr,
1922 "%s: can't allocate %d bytes for tcp_udp struct\n",
1923 Pn, (int)sizeof(struct tcp_udp));
1928 tp->fport = (int)(fport & 0xffff);
1930 tp->lport = (int)(lport & 0xffff);
1934 tp->state = (int)state;
1935 tp->next = TcpUdp[h];
1942 #if defined(HASIPv6)
1944 * get_raw6() - get /proc/net/raw6 info
1949 char *p; /* /proc/net/raw path */
1951 char buf[MAXPATHLEN], *ep, **fp, *la, *ra, *sp;
1955 struct rawsin *np, *rp;
1956 MALLOC_S lal, ral, spl;
1957 static char *vbuf = (char *)NULL;
1958 static size_t vsz = (size_t)0;
1961 * Do second time cleanup or first time setup.
1964 for (h = 0; h < INOBUCKS; h++) {
1965 for (rp = Rawsin6[h]; rp; rp = np) {
1968 (void) free((FREE_P *)rp->la);
1970 (void) free((FREE_P *)rp->ra);
1971 (void) free((FREE_P *)rp);
1973 Rawsin6[h] = (struct rawsin *)NULL;
1976 Rawsin6 = (struct rawsin **)calloc(INOBUCKS,
1977 sizeof(struct rawsin *));
1979 (void) fprintf(stderr,
1980 "%s: can't allocate %d raw6 hash pointer bytes\n",
1981 Pn, (int)(INOBUCKS * sizeof(struct rawsin *)));
1986 * Open the /proc/net/raw6 file, assign a page size buffer to the stream,
1987 * and read it. Store raw6 socket info in the Rawsin6[] hash buckets.
1989 if (!(xs = open_proc_stream(p, "r", &vbuf, &vsz, 0)))
1991 while (fgets(buf, sizeof(buf) - 1, xs)) {
1992 if (get_fields(buf, (char *)NULL, &fp, (int *)NULL, 0) < nf)
1997 * Check the column labels in the first line.
1999 if (!fp[1] || strcmp(fp[1], "local_address")
2000 || !fp[2] || strcmp(fp[2], "remote_address")
2001 || !fp[3] || strcmp(fp[3], "st")
2002 || !fp[11] || strcmp(fp[11], "inode"))
2005 (void) fprintf(stderr,
2006 "%s: WARNING: unsupported format: %s\n",
2015 * Assemble the inode number and see if the inode is already
2019 if (!fp[9] || !*fp[9]
2020 || (inode = strtoull(fp[9], &ep, 0)) == ULONG_MAX
2024 for (rp = Rawsin6[h]; rp; rp = rp->next) {
2025 if (inode == rp->inode)
2031 * Save the local address, remote address, and state.
2033 if (!fp[1] || !*fp[1] || (lal = strlen(fp[1])) < 1) {
2037 if (!(la = (char *)malloc(lal + 1))) {
2038 (void) fprintf(stderr,
2039 "%s: can't allocate %d local raw6 address bytes: %s\n",
2040 Pn, (int)(lal + 1), fp[1]);
2043 (void) snpf(la, lal + 1, "%s", fp[1]);
2045 if (!fp[2] || !*fp[2] || (ral = strlen(fp[2])) < 1) {
2049 if (!(ra = (char *)malloc(ral + 1))) {
2050 (void) fprintf(stderr,
2051 "%s: can't allocate %d remote raw6 address bytes: %s\n",
2052 Pn, (int)(ral + 1), fp[2]);
2055 (void) snpf(ra, ral + 1, "%s", fp[2]);
2057 if (!fp[3] || !*fp[3] || (spl = strlen(fp[3])) < 1) {
2061 if (!(sp = (char *)malloc(spl + 1))) {
2062 (void) fprintf(stderr,
2063 "%s: can't allocate %d remote raw6 state bytes: %s\n",
2064 Pn, (int)(spl + 1), fp[2]);
2067 (void) snpf(sp, spl + 1, "%s", fp[3]);
2070 * Allocate space for an rawsin entry, fill it, and link it to its
2073 if (!(rp = (struct rawsin *)malloc(sizeof(struct rawsin)))) {
2074 (void) fprintf(stderr,
2075 "%s: can't allocate %d byte rawsin structure for IPv6\n",
2076 Pn, (int)sizeof(struct rawsin));
2086 rp->next = Rawsin6[h];
2094 * get_tcpudp6() - get IPv6 TCP, UDP or UDPLITE net info
2098 get_tcpudp6(p, pr, clr)
2099 char *p; /* /proc/net/{tcp,udp} path */
2100 int pr; /* protocol: 0 = TCP, 1 = UDP */
2101 int clr; /* 1 == clear the table */
2103 char buf[MAXPATHLEN], *ep, **fp;
2104 struct in6_addr faddr, laddr;
2105 unsigned long fport, lport, rxq, state, txq;
2109 struct tcp_udp6 *np6, *tp6;
2110 static char *vbuf = (char *)NULL;
2111 static size_t vsz = (size_t)0;
2113 * Delete previous table contents. Allocate a table for the first time.
2117 for (h = 0; h < TcpUdp6_bucks; h++) {
2118 for (tp6 = TcpUdp6[h]; tp6; tp6 = np6) {
2120 (void) free((FREE_P *)tp6);
2122 TcpUdp6[h] = (struct tcp_udp6 *)NULL;
2128 * Open the /proc/net/sockstat6 file and establish the hash bucket
2129 * count from its "TCP6: inuse" and "UDP6: inuse" lines.
2131 TcpUdp6_bucks = INOBUCKS;
2133 if ((fs = fopen(SockStatPath6, "r"))) {
2134 while(fgets(buf, sizeof(buf) - 1, fs)) {
2135 if (get_fields(buf, (char *)NULL, &fp, (int *)NULL, 0) != 3)
2138 || !fp[1] || strcmp(fp[1], "inuse")
2139 || !fp[2] || !*fp[2])
2141 if (!strcmp(fp[0], "TCP6:")) {
2143 if ((h = atoi(fp[2])) < 1)
2146 } else if (!strcmp(fp[0], "UDP6:")) {
2148 if ((h = atoi(fp[2])) < 1)
2154 while (TcpUdp6_bucks < i)
2161 if (!(TcpUdp6 = (struct tcp_udp6 **)calloc(TcpUdp6_bucks,
2162 sizeof(struct tcp_udp6 *))))
2164 (void) fprintf(stderr,
2165 "%s: can't allocate %d bytes for TCP6&UDP6 hash buckets\n",
2166 Pn, (int)(TcpUdp6_bucks * sizeof(struct tcp_udp6 *)));
2171 * Open the /proc/net file, assign a page size buffer to the stream,
2174 if (!(fs = open_proc_stream(p, "r", &vbuf, &vsz, 0)))
2177 while(fgets(buf, sizeof(buf) - 1, fs)) {
2179 (nf == 12) ? (char *)NULL : ":",
2180 &fp, (int *)NULL, 0)
2184 if (!fp[1] || strcmp(fp[1], "local_address")
2185 || !fp[2] || strcmp(fp[2], "remote_address")
2186 || !fp[3] || strcmp(fp[3], "st")
2187 || !fp[4] || strcmp(fp[4], "tx_queue")
2188 || !fp[5] || strcmp(fp[5], "rx_queue")
2189 || !fp[11] || strcmp(fp[11], "inode"))
2192 (void) fprintf(stderr,
2193 "%s: WARNING: unsupported format: %s\n",
2202 * Get the local and remote addresses.
2204 if (!fp[1] || !*fp[1] || net6a2in6(fp[1], &laddr))
2207 if (!fp[2] || !*fp[2]
2208 || (lport = strtoul(fp[2], &ep, 16)) == ULONG_MAX || !ep || *ep)
2210 if (!fp[3] || !*fp[3] || net6a2in6(fp[3], &faddr))
2213 if (!fp[4] || !*fp[4]
2214 || (fport = strtoul(fp[4], &ep, 16)) == ULONG_MAX || !ep || *ep)
2217 * Get the state and queue sizes.
2220 if (!fp[5] || !*fp[5]
2221 || (state = strtoul(fp[5], &ep, 16)) == ULONG_MAX || !ep || *ep)
2224 if (!fp[6] || !*fp[6]
2225 || (txq = strtoul(fp[6], &ep, 16)) == ULONG_MAX || !ep || *ep)
2228 if (!fp[7] || !*fp[7]
2229 || (rxq = strtoul(fp[7], &ep, 16)) == ULONG_MAX || !ep || *ep)
2232 * Get the inode and use it for hashing and searching.
2235 if (!fp[13] || !*fp[13]
2236 || (inode = strtoull(fp[13], &ep, 0)) == ULONG_MAX || !ep || *ep)
2238 h = TCPUDP6HASH(inode);
2239 for (tp6 = TcpUdp6[h]; tp6; tp6 = tp6->next) {
2240 if (tp6->inode == inode)
2246 * Create a new entry and link it to its hash bucket.
2248 if (!(tp6 = (struct tcp_udp6 *)malloc(sizeof(struct tcp_udp6)))) {
2249 (void) fprintf(stderr,
2250 "%s: can't allocate %d bytes for tcp_udp6 struct\n",
2251 Pn, (int)sizeof(struct tcp_udp6));
2256 tp6->fport = (int)(fport & 0xffff);
2258 tp6->lport = (int)(lport & 0xffff);
2262 tp6->state = (int)state;
2263 tp6->next = TcpUdp6[h];
2268 #endif /* defined(HASIPv6) */
2272 * get_unix() - get UNIX net info
2277 char *p; /* /proc/net/unix path */
2279 char buf[MAXPATHLEN], *ep, **fp, *path, *pcb;
2284 struct uxsin *np, *up;
2287 static char *vbuf = (char *)NULL;
2288 static size_t vsz = (size_t)0;
2290 * Do second time cleanup or first time setup.
2293 for (h = 0; h < INOBUCKS; h++) {
2294 for (up = Uxsin[h]; up; up = np) {
2297 (void) free((FREE_P *)up->path);
2299 (void) free((FREE_P *)up->pcb);
2300 (void) free((FREE_P *)up);
2302 Uxsin[h] = (struct uxsin *)NULL;
2305 Uxsin = (struct uxsin **)calloc(INOBUCKS, sizeof(struct uxsin *));
2307 (void) fprintf(stderr,
2308 "%s: can't allocate %d bytes for Unix socket info\n",
2309 Pn, (int)(INOBUCKS * sizeof(struct uxsin *)));
2313 * Open the /proc/net/unix file, assign a page size buffer to the stream,
2314 * read the file's contents, and add them to the Uxsin hash buckets.
2316 if (!(us = open_proc_stream(p, "r", &vbuf, &vsz, 0)))
2318 while (fgets(buf, sizeof(buf) - 1, us)) {
2319 if ((nf = get_fields(buf, ":", &fp, (int *)NULL, 0)) < 7)
2324 * Check the first line for header words.
2326 if (!fp[0] || strcmp(fp[0], "Num")
2327 || !fp[1] || strcmp(fp[1], "RefCount")
2328 || !fp[2] || strcmp(fp[2], "Protocol")
2329 || !fp[3] || strcmp(fp[3], "Flags")
2330 || !fp[4] || strcmp(fp[4], "Type")
2331 || !fp[5] || strcmp(fp[5], "St")
2332 || !fp[6] || strcmp(fp[6], "Inode")
2334 || !fp[7] || strcmp(fp[7], "Path"))
2337 (void) fprintf(stderr,
2338 "%s: WARNING: unsupported format: %s\n",
2347 * Assemble PCB address, inode number, and path name. If this
2348 * inode is already represented in Uxsin, skip it.
2351 if (!fp[6] || !*fp[6]
2352 || (inode = strtoull(fp[6], &ep, 0)) == ULONG_MAX || !ep || *ep)
2355 for (up = Uxsin[h]; up; up = up->next) {
2356 if (inode == up->inode)
2361 if (!fp[0] || !*fp[0])
2364 len = strlen(fp[0]) + 2;
2365 if (!(pcb = (char *)malloc(len + 1))) {
2366 (void) fprintf(stderr,
2367 "%s: can't allocate %d bytes for UNIX PCB: %s\n",
2368 Pn, (int)(len + 1), fp[0]);
2371 (void) snpf(pcb, len + 1, "0x%s", fp[0]);
2373 if (nf >= 8 && fp[7] && *fp[7] && (len = strlen(fp[7]))) {
2374 if (!(path = (char *)malloc(len + 1))) {
2375 (void) fprintf(stderr,
2376 "%s: can't allocate %d bytes for UNIX path \"%s\"\n",
2377 Pn, (int)(len + 1), fp[7]);
2380 (void) snpf(path, len + 1, "%s", fp[7]);
2382 path = (char *)NULL;
2384 * Assemble socket type.
2387 if (!fp[4] || !*fp[4]
2388 || (ty = (uint32_t)strtoul(fp[4], &ep, 16)) == (uint32_t)UINT32_MAX
2391 ty = (uint32_t)UINT_MAX;
2394 * Allocate and fill a Unix socket info structure; link it to its
2397 if (!(up = (struct uxsin *)malloc(sizeof(struct uxsin)))) {
2398 (void) fprintf(stderr,
2399 "%s: can't allocate %d bytes for uxsin struct\n",
2400 Pn, (int)sizeof(struct uxsin));
2407 if ((up->path = path) && (*path == '/')) {
2410 * If an absolute path (i.e., one that begins with a '/') exists
2411 * for the line, attempt to stat(2) it and save the device and
2412 * node numbers reported in the stat buffer.
2418 sr = statsafely(path, &sb);
2420 sr = stat(path, &sb);
2421 if (sr && ((sb.st_mode & S_IFMT) == S_IFSOCK)) {
2423 up->sb_dev = sb.st_dev;
2424 up->sb_ino = (INODETYPE)sb.st_ino;
2425 up->sb_rdev = sb.st_rdev;
2428 up->next = Uxsin[h];
2435 #if defined(HASIPv6)
2437 * net6a2in6() - convert ASCII IPv6 address in /proc/net/{tcp,udp} form to
2443 char *as; /* address source */
2444 struct in6_addr *ad; /* address destination */
2450 * Assemble four uint32_t's from 4 X 8 hex digits into s6_addr32[].
2452 for (i = 0, len = strlen(as);
2453 (i < 4) && (len >= 8);
2454 as += 8, i++, len -= 8)
2456 (void) strncpy(buf, as, 8);
2459 if ((ad->s6_addr32[i] = (uint32_t)strtoul(buf, &ep, 16))
2460 == (uint32_t)UINT32_MAX || !ep || *ep)
2463 return((*as || (i != 4) || len) ? 1 : 0);
2465 #endif /* defined(HASIPv6) */
2469 * isainb(a,b) is string a in string b
2474 char *a; /*string a */
2475 char *b; /* string b */
2478 MALLOC_S la, lb, lt;
2482 if (!(la = strlen(a)) || !(lb = strlen(b)))
2484 if (!(cp = strchr(b, (int)','))) {
2487 return(strcmp(a, b));
2489 for (pp = b; pp && *pp; ) {
2490 lt = (MALLOC_S)(cp - pp);
2491 if ((la == lt) && !strncmp(a, pp, lt))
2495 if (!(cp = strchr(pp, (int)',')))
2505 * print_ax25info() - print AX25 socket info
2510 struct ax25sin *ap; /* AX25 socket info */
2512 char *cp, pbuf[1024];
2514 MALLOC_S pl = (MALLOC_S)0;
2519 ds = (ap->da && strcmp(ap->da, "*")) ? 1 : 0;
2520 (void) snpf(&pbuf[pl], sizeof(pbuf) - pl, "%s%s%s ", ap->sa,
2526 (void) snpf(&pbuf[pl], sizeof(pbuf) - pl, "(Sq=%lu ", ap->sq);
2532 (void) snpf(&pbuf[pl], sizeof(pbuf) - pl, "%sRq=%lu ", cp, ap->rq);
2536 (void) snpf(&pbuf[pl], sizeof(pbuf) - pl, "%sState=%d", cp, ap->state);
2538 if ((ap->state >= 0) && (ap->state < NAX25ST))
2539 cp = ax25st[ap->state];
2542 (void) snpf(&pbuf[pl], sizeof(pbuf) - pl, "%s%s)",
2546 if (!(cp = (char *)malloc(pl + 1))) {
2547 (void) fprintf(stderr,
2548 "%s: can't allocate %d bytes for AX25 sock state, PID: %d\n",
2549 Pn, (int)(pl + 1), Lp->pid);
2552 (void) snpf(cp, pl + 1, "%s", pbuf);
2558 * print_ipxinfo() - print IPX socket info
2563 struct ipxsin *ip; /* IPX socket info */
2565 char *cp, pbuf[256];
2570 (void) snpf(pbuf, sizeof(pbuf), "(Tx=%lx Rx=%lx State=%02x)",
2571 ip->txq, ip->rxq, ip->state);
2573 if (!(cp = (char *)malloc(pl + 1))) {
2574 (void) fprintf(stderr,
2575 "%s: can't allocate %d bytes for IPX sock state, PID: %d\n",
2576 Pn, (int)(pl + 1), Lp->pid);
2579 (void) snpf(cp, pl + 1, "%s", pbuf);
2585 * print_tcptpi() - print TCP/TPI state
2590 int nl; /* 1 == '\n' required */
2593 char *cp = (char *)NULL;
2597 if ((Ftcptpi & TCPTPI_STATE) && Lf->lts.type == 0) {
2599 (void) build_IPstates();
2600 if ((s = Lf->lts.state.i + TcpStOff) < 0 || s >= TcpNstates) {
2601 (void) snpf(buf, sizeof(buf), "UNKNOWN_TCP_STATE_%d",
2608 (void) printf("%cST=%s%c", LSOF_FID_TCPTPI, cp, Terminator);
2611 (void) fputs(cp, stdout);
2617 # if defined(HASTCPTPIQ)
2618 if (Ftcptpi & TCPTPI_QUEUES) {
2621 putchar(LSOF_FID_TCPTPI);
2628 (void) printf("QR=%lu", Lf->lts.rq);
2630 putchar(Terminator);
2635 putchar(LSOF_FID_TCPTPI);
2642 (void) printf("QS=%lu", Lf->lts.sq);
2644 putchar(Terminator);
2648 # endif /* defined(HASTCPTPIQ) */
2650 # if defined(HASTCPTPIW)
2651 if (Ftcptpi & TCPTPI_WINDOWS) {
2654 putchar(LSOF_FID_TCPTPI);
2661 (void) printf("WR=%lu", Lf->lts.rw);
2663 putchar(Terminator);
2668 putchar(LSOF_FID_TCPTPI);
2675 (void) printf("WW=%lu", Lf->lts.ww);
2677 putchar(Terminator);
2681 # endif /* defined(HASTCPTPIW) */
2691 * process_proc_sock() - process /proc-based socket
2695 process_proc_sock(p, pbr, s, ss, l, lss)
2696 char *p; /* node's readlink() path */
2697 char *pbr; /* node's path before readlink() */
2698 struct stat *s; /* stat() result for path */
2699 int ss; /* *s status -- i.e, SB_* values */
2700 struct stat *l; /* lstat() result for FD (NULL for
2702 int lss; /* *l status -- i.e, SB_* values */
2705 char *cp, *path, tbuf[64];
2706 unsigned char *fa, *la;
2707 struct in_addr fs, ls;
2708 struct icmpin *icmpp;
2714 static char *prp = (char *)NULL;
2721 #if defined(HASIPv6)
2723 struct tcp_udp6 *tp6;
2724 #endif /* defined(HASIPv6) */
2727 * Enter offset, if possible.
2729 if (Foffset || !Fsize) {
2730 if (l && (lss & SB_SIZE) && OffType) {
2731 Lf->off = (SZOFFTYPE)l->st_size;
2736 * Check for socket's inode presence in the protocol info caches.
2739 (void) get_ax25(AX25path);
2740 (void) free((FREE_P *)AX25path);
2741 AX25path = (char *)NULL;
2744 && (ap = check_ax25((INODETYPE)s->st_ino))
2748 * The inode is connected to an AX25 /proc record.
2750 * Set the type to "ax25"; save the device name; save the inode number;
2751 * save the destination and source addresses; save the send and receive
2752 * queue sizes; and save the connection state.
2754 (void) snpf(Lf->type, sizeof(Lf->type), "ax25");
2756 (void) enter_dev_ch(ap->dev_ch);
2757 Lf->inode = ap->inode;
2763 (void) get_ipx(Ipxpath);
2764 (void) free((FREE_P *)Ipxpath);
2765 Ipxpath = (char *)NULL;
2768 && (ip = check_ipx((INODETYPE)s->st_ino))
2772 * The inode is connected to an IPX /proc record.
2774 * Set the type to "ipx"; enter the inode and device numbers; store
2775 * the addresses, queue sizes, and state in the NAME column.
2777 (void) snpf(Lf->type, sizeof(Lf->type), "ipx");
2779 Lf->inode = (INODETYPE)s->st_ino;
2783 Lf->dev = s->st_dev;
2792 * Store the local IPX address.
2794 len = strlen(ip->la);
2797 (void) strncpy(cp, ip->la, len);
2805 * Store the remote IPX address, prefixed with "->".
2808 (void) snpf(cp, nl, "->");
2813 (void) snpf(cp, nl, "%s", ip->ra);
2818 (void) print_ipxinfo(ip);
2824 (void) get_raw(Rawpath);
2825 (void) free((FREE_P *)Rawpath);
2826 Rawpath = (char *)NULL;
2829 && (rp = check_raw((INODETYPE)s->st_ino))
2833 * The inode is connected to a raw /proc record.
2835 * Set the type to "raw"; enter the inode number; store the local
2836 * address, remote address, and state in the NAME column.
2838 (void) snpf(Lf->type, sizeof(Lf->type), "raw");
2840 Lf->inode = (INODETYPE)s->st_ino;
2846 if (rp->la && rp->lal) {
2849 * Store the local raw address.
2852 (void) snpf(cp, nl, "%s", rp->la);
2858 if (rp->ra && rp->ral) {
2861 * Store the remote raw address, prefixed with "->".
2863 if (nl > (rp->ral + 2)) {
2864 (void) snpf(cp, nl, "->%s", rp->ra);
2865 cp += (rp->ral + 2);
2867 nl -= (rp->ral + 2);
2870 if (rp->sp && rp->spl) {
2873 * Store the state, optionally prefixed by a space, in the
2877 if (nl > (len = ((cp == Namech) ? 0 : 1) + 3 + rp->spl)) {
2878 (void) snpf(cp, nl, "%sst=%s",
2879 (cp == Namech) ? "" : " ", rp->sp);
2890 (void) get_netlink(Nlkpath);
2891 (void) free((FREE_P *) Nlkpath);
2892 Nlkpath = (char *)NULL;
2895 && (np = check_netlink((INODETYPE)s->st_ino))
2898 * The inode is connected to a Netlink /proc record.
2900 * Set the type to "netlink" and store the protocol in the NAME
2901 * column. Save the inode number.
2904 (void) snpf(Lf->type, sizeof(Lf->type), "netlink");
2907 #if defined(NETLINK_ROUTE)
2911 #endif /* defined(NETLINK_ROUTE) */
2913 #if defined(NETLINK_UNUSED)
2914 case NETLINK_UNUSED:
2917 #endif /* defined(NETLINK_UNUSED) */
2919 #if defined(NETLINK_USERSOCK)
2920 case NETLINK_USERSOCK:
2923 #endif /* defined(NETLINK_USERSOCK) */
2925 #if defined(NETLINK_FIREWALL)
2926 case NETLINK_FIREWALL:
2929 #endif /* defined(NETLINK_FIREWALL) */
2931 #if defined(NETLINK_INET_DIAG)
2932 case NETLINK_INET_DIAG:
2935 #endif /* defined(NETLINK_INET_DIAG) */
2937 #if defined(NETLINK_NFLOG)
2941 #endif /* defined(NETLINK_NFLOG) */
2943 #if defined(NETLINK_XFRM)
2947 #endif /* defined(NETLINK_XFRM) */
2949 #if defined(NETLINK_SELINUX)
2950 case NETLINK_SELINUX:
2953 #endif /* defined(NETLINK_SELINUX) */
2955 #if defined(NETLINK_ISCSI)
2959 #endif /* defined(NETLINK_ISCSI) */
2961 #if defined(NETLINK_AUDIT)
2965 #endif /* defined(NETLINK_AUDIT) */
2967 #if defined(NETLINK_FIB_LOOKUP)
2968 case NETLINK_FIB_LOOKUP:
2971 #endif /* defined(NETLINK_FIB_LOOKUP) */
2973 #if defined(NETLINK_CONNECTOR)
2974 case NETLINK_CONNECTOR:
2977 #endif /* defined(NETLINK_CONNECTOR) */
2979 #if defined(NETLINK_NETFILTER)
2980 case NETLINK_NETFILTER:
2983 #endif /* defined(NETLINK_NETFILTER) */
2985 #if defined(NETLINK_IP6_FW)
2986 case NETLINK_IP6_FW:
2989 #endif /* defined(NETLINK_IP6_FW) */
2991 #if defined(NETLINK_DNRTMSG)
2992 case NETLINK_DNRTMSG:
2995 #endif /* defined(NETLINK_DNRTMSG) */
2997 #if defined(NETLINK_KOBJECT_UEVENT)
2998 case NETLINK_KOBJECT_UEVENT:
2999 cp = "KOBJECT_UEVENT";
3001 #endif /* defined(NETLINK_KOBJECT_UEVENT) */
3003 #if defined(NETLINK_GENERIC)
3004 case NETLINK_GENERIC:
3007 #endif /* defined(NETLINK_GENERIC) */
3009 #if defined(NETLINK_SCSITRANSPORT)
3010 case NETLINK_SCSITRANSPORT:
3011 cp = "SCSITRANSPORT";
3013 #endif /* defined(NETLINK_SCSITRANSPORT) */
3015 #if defined(NETLINK_ECRYPTFS)
3016 case NETLINK_ECRYPTFS:
3019 #endif /* defined(NETLINK_ECRYPTFS) */
3022 (void) snpf(Namech, Namechl, "unknown protocol: %d", np->pr);
3026 (void) snpf(Namech, Namechl, "%s", cp);
3027 Lf->inode = (INODETYPE)s->st_ino;
3034 (void) get_pack(Packpath);
3035 (void) free((FREE_P *)Packpath);
3036 Packpath = (char *)NULL;
3039 && (pp = check_pack((INODETYPE)s->st_ino))
3043 * The inode is connected to a packet /proc record.
3045 * Set the type to "pack" and store the socket type in the NAME
3046 * column. Put the protocol name in the NODE column and the inode
3047 * number in the DEVICE column.
3049 (void) snpf(Lf->type, sizeof(Lf->type), "pack");
3050 cp = sockty2str(pp->ty, &rf);
3051 (void) snpf(Namech, Namechl, "type=%s%s", rf ? "" : "SOCK_", cp);
3054 #if defined(ETH_P_LOOP)
3058 #endif /* defined(ETH_P_LOOP) */
3060 #if defined(ETH_P_PUP)
3064 #endif /* defined(ETH_P_PUP) */
3066 #if defined(ETH_P_PUPAT)
3070 #endif /* defined(ETH_P_PUPAT) */
3072 #if defined(ETH_P_IP)
3076 #endif /* defined(ETH_P_IP) */
3078 #if defined(ETH_P_X25)
3082 #endif /* defined(ETH_P_X25) */
3084 #if defined(ETH_P_ARP)
3088 #endif /* defined(ETH_P_ARP) */
3090 #if defined(ETH_P_BPQ)
3094 #endif /* defined(ETH_P_BPQ) */
3096 #if defined(ETH_P_IEEEPUP)
3100 #endif /* defined(ETH_P_IEEEPUP) */
3102 #if defined(ETH_P_IEEEPUPAT)
3103 case ETH_P_IEEEPUPAT:
3106 #endif /* defined(ETH_P_IEEEPUPAT) */
3108 #if defined(ETH_P_DEC)
3112 #endif /* defined(ETH_P_DEC) */
3114 #if defined(ETH_P_DNA_DL)
3118 #endif /* defined(ETH_P_DNA_DL) */
3120 #if defined(ETH_P_DNA_RC)
3124 #endif /* defined(ETH_P_DNA_RC) */
3126 #if defined(ETH_P_DNA_RT)
3130 #endif /* defined(ETH_P_DNA_RT) */
3132 #if defined(ETH_P_LAT)
3136 #endif /* defined(ETH_P_LAT) */
3138 #if defined(ETH_P_DIAG)
3142 #endif /* defined(ETH_P_DIAG) */
3144 #if defined(ETH_P_CUST)
3148 #endif /* defined(ETH_P_CUST) */
3150 #if defined(ETH_P_SCA)
3154 #endif /* defined(ETH_P_SCA) */
3156 #if defined(ETH_P_RARP)
3160 #endif /* defined(ETH_P_RARP) */
3162 #if defined(ETH_P_ATALK)
3166 #endif /* defined(ETH_P_ATALK) */
3168 #if defined(ETH_P_AARP)
3172 #endif /* defined(ETH_P_AARP) */
3174 #if defined(ETH_P_8021Q)
3178 #endif /* defined(ETH_P_8021Q) */
3180 #if defined(ETH_P_IPX)
3184 #endif /* defined(ETH_P_IPX) */
3186 #if defined(ETH_P_IPV6)
3190 #endif /* defined(ETH_P_IPV6) */
3192 #if defined(ETH_P_SLOW)
3196 #endif /* defined(ETH_P_SLOW) */
3198 #if defined(ETH_P_WCCP)
3202 #endif /* defined(ETH_P_WCCP) */
3204 #if defined(ETH_P_PPP_DISC)
3205 case ETH_P_PPP_DISC:
3208 #endif /* defined(ETH_P_PPP_DISC) */
3210 #if defined(ETH_P_PPP_SES)
3214 #endif /* defined(ETH_P_PPP_SES) */
3216 #if defined(ETH_P_MPLS_UC)
3220 #endif /* defined(ETH_P_MPLS_UC) */
3222 #if defined(ETH_P_ATMMPOA)
3226 #endif /* defined(ETH_P_ATMMPOA) */
3228 #if defined(ETH_P_MPLS_MC)
3232 #endif /* defined(ETH_P_MPLS_MC) */
3234 #if defined(ETH_P_ATMFATE)
3238 #endif /* defined(ETH_P_ATMFATE) */
3240 #if defined(ETH_P_AOE)
3244 #endif /* defined(ETH_P_AOE) */
3246 #if defined(ETH_P_TIPC)
3250 #endif /* defined(ETH_P_TIPC) */
3252 #if defined(ETH_P_802_3)
3256 #endif /* defined(ETH_P_802_3) */
3258 #if defined(ETH_P_AX25)
3262 #endif /* defined(ETH_P_AX25) */
3264 #if defined(ETH_P_ALL)
3268 #endif /* defined(ETH_P_ALL) */
3270 #if defined(ETH_P_802_2)
3274 #endif /* defined(ETH_P_802_2) */
3276 #if defined(ETH_P_SNAP)
3280 #endif /* defined(ETH_P_SNAP) */
3282 #if defined(ETH_P_DDCMP)
3286 #endif /* defined(ETH_P_DDCMP) */
3288 #if defined(ETH_P_WAN_PPP)
3292 #endif /* defined(ETH_P_WAN_PPP) */
3294 #if defined(ETH_P_PPP_MP)
3298 #endif /* defined(ETH_P_PPP_MP) */
3300 #if defined(ETH_P_LOCALTALK)
3301 case ETH_P_LOCALTALK:
3304 #endif /* defined(ETH_P_LOCALTALK) */
3306 #if defined(ETH_P_PPPTALK)
3310 #endif /* defined(ETH_P_PPPTALK) */
3312 #if defined(ETH_P_TR_802_2)
3313 case ETH_P_TR_802_2:
3316 #endif /* defined(ETH_P_TR_802_2) */
3318 #if defined(ETH_P_MOBITEX)
3322 #endif /* defined(ETH_P_MOBITEX) */
3324 #if defined(ETH_P_CONTROL)
3328 #endif /* defined(ETH_P_CONTROL) */
3330 #if defined(ETH_P_IRDA)
3334 #endif /* defined(ETH_P_IRDA) */
3336 #if defined(ETH_P_ECONET)
3340 #endif /* defined(ETH_P_ECONET) */
3342 #if defined(ETH_P_HDLC)
3346 #endif /* defined(ETH_P_HDLC) */
3348 #if defined(ETH_P_ARCNET)
3352 #endif /* defined(ETH_P_ARCNET) */
3355 (void) snpf(tbuf, sizeof(tbuf) - 1, "%d", pp->pr);
3356 tbuf[sizeof(tbuf) - 1] = '\0';
3359 (void) snpf(Lf->iproto, sizeof(Lf->iproto), "%.*s", IPROTOL-1, cp);
3362 (void) snpf(tbuf, sizeof(tbuf), InodeFmt_d,
3363 (INODETYPE)s->st_ino);
3364 tbuf[sizeof(tbuf) - 1] = '\0';
3372 (void) get_unix(UNIXpath);
3373 (void) free((FREE_P *)UNIXpath);
3374 UNIXpath = (char *)NULL;
3377 && (up = check_unix((INODETYPE)s->st_ino))
3381 * The inode is connected to a UNIX /proc record.
3383 * Set the type to "unix"; enter the PCB address in the DEVICE column;
3384 * enter the inode number; and save the optional path.
3388 (void) snpf(Lf->type, sizeof(Lf->type), "unix");
3390 enter_dev_ch(up->pcb);
3392 Lf->inode = (INODETYPE)s->st_ino;
3395 cp = sockty2str(up->ty, &rf);
3396 (void) snpf(Namech, Namechl - 1, "%s%stype=%s",
3397 up->path ? up->path : "",
3398 up->path ? " " : "",
3400 Namech[Namechl - 1] = '\0';
3401 (void) enter_nm(Namech);
3405 * See if this UNIX domain socket was specified as a search
3408 * Search first by device and node numbers, if that is possible;
3409 * then search by name.
3411 unsigned char f = 0; /* file-found flag */
3416 * If the UNIX socket information includes stat(2) results, do
3417 * a device and node number search.
3419 * Note: that requires the saving, temporary modification and
3420 * restoration of some *Lf values.
3422 unsigned char sv_dev_def; /* saved dev_def */
3423 unsigned char sv_inp_ty; /* saved inp_ty */
3424 unsigned char sv_rdev_def; /* saved rdev_def */
3425 dev_t sv_dev; /* saved dev */
3426 INODETYPE sv_inode; /* saved inode */
3427 dev_t sv_rdev; /* saved rdev */
3429 sv_dev_def = Lf->dev_def;
3431 sv_inode = Lf->inode;
3432 sv_inp_ty = Lf->inp_ty;
3433 sv_rdev_def = Lf->rdev_def;
3435 Lf->dev_def = Lf->inp_ty = Lf->rdev_def = 1;
3436 Lf->dev = up->sb_dev;
3437 Lf->inode = up->sb_ino;
3438 Lf->rdev = up->sb_rdev;
3439 if (is_file_named(0, path, (struct mounts *)NULL, 0)) {
3443 Lf->dev_def = sv_dev_def;
3445 Lf->inode = sv_inode;
3446 Lf->inp_ty = sv_inp_ty;
3447 Lf->rdev_def = sv_rdev_def;
3450 if (!f && (ss & SB_MODE)) {
3453 * If the file has not yet been found and the stat buffer has
3454 * st_mode, search for the file by full path.
3456 if (is_file_named(2, path, (struct mounts *)NULL,
3457 ((s->st_mode & S_IFMT) == S_IFCHR)) ? 1 : 0)
3466 #if defined(HASIPv6)
3469 (void) get_raw6(Raw6path);
3470 (void) free((FREE_P *)Raw6path);
3471 Raw6path = (char *)NULL;
3473 if (!Fxopt && (ss & SB_INO)
3474 && (rp = check_raw6((INODETYPE)s->st_ino))
3478 * The inode is connected to a raw IPv6 /proc record.
3480 * Set the type to "raw6"; enter the inode number; store the local
3481 * address, remote address, and state in the NAME column.
3483 (void) snpf(Lf->type, sizeof(Lf->type), "raw6");
3485 Lf->inode = (INODETYPE)s->st_ino;
3489 nl = MAXPATHLEN - 2;
3490 if (rp->la && rp->lal) {
3493 * Store the local raw IPv6 address.
3496 (void) snpf(cp, nl, "%s", rp->la);
3502 if (rp->ra && rp->ral) {
3505 * Store the remote raw address, prefixed with "->".
3507 if (nl > (rp->ral + 2)) {
3508 (void) snpf(cp, nl, "->%s", rp->ra);
3509 cp += (rp->ral + 2);
3510 nl -= (rp->ral + 2);
3513 if (rp->sp && rp->spl) {
3516 * Store the state, optionally prefixed by a space, in the
3520 if (nl > (len = ((cp == Namech) ? 0 : 1) + 3 + rp->spl)) {
3521 (void) snpf(cp, nl, "%sst=%s",
3522 (cp == Namech) ? "" : " ", rp->sp);
3534 (void) get_tcpudp6(TCP6path, 0, 1);
3535 (void) free((FREE_P *)TCP6path);
3536 TCP6path = (char *)NULL;
3540 (void) get_tcpudp6(UDP6path, 1, 0);
3541 (void) free((FREE_P *)UDP6path);
3542 UDP6path = (char *)NULL;
3546 (void) get_tcpudp6(UDPLITE6path, 2, 0);
3547 (void) free((FREE_P *)UDPLITE6path);
3548 UDPLITE6path = (char *)NULL;
3550 if (!Fxopt && (ss & SB_INO)
3551 && (tp6 = check_tcpudp6((INODETYPE)s->st_ino, &pr))
3555 * The inode is connected to an IPv6 TCP or UDP /proc record.
3557 * Set the type to "IPv6"; enter the protocol; put the inode number
3558 * in the DEVICE column in lieu of the PCB address; save the local
3559 * and foreign IPv6 addresses; save the type and protocol; and
3560 * (optionally) save the queue sizes.
3562 i = tp6->state + TcpStOff;
3566 * Check for state exclusion.
3568 if (i >= 0 && i < TcpNstates) {
3578 * Check for state inclusion.
3580 if (i >= 0 && i < TcpNstates) {
3589 if (Fnet && (FnetTy != 4))
3591 (void) snpf(Lf->type, sizeof(Lf->type), "IPv6");
3592 (void) snpf(Lf->iproto, sizeof(Lf->iproto), "%.*s", IPROTOL-1, pr);
3595 (void) snpf(tbuf, sizeof(tbuf), InodeFmt_d,
3596 (INODETYPE)s->st_ino);
3597 tbuf[sizeof(tbuf) - 1] = '\0';
3601 if (!IN6_IS_ADDR_UNSPECIFIED(&tp6->faddr) || tp6->fport)
3602 fa = (unsigned char *)&tp6->faddr;
3604 fa = (unsigned char *)NULL;
3605 if (!IN6_IS_ADDR_UNSPECIFIED(&tp6->laddr) || tp6->lport)
3606 la = (unsigned char *)&tp6->laddr;
3608 la = (unsigned char *)NULL;
3609 if ((fa && IN6_IS_ADDR_V4MAPPED(&tp6->faddr))
3610 || (la && IN6_IS_ADDR_V4MAPPED(&tp6->laddr))) {
3617 ent_inaddr(la, tp6->lport, fa, tp6->fport, af);
3618 Lf->lts.type = tp6->proto;
3619 Lf->lts.state.i = tp6->state;
3621 #if defined(HASTCPTPIQ)
3622 Lf->lts.rq = tp6->rxq;
3623 Lf->lts.sq = tp6->txq;
3624 Lf->lts.rqs = Lf->lts.sqs = 1;
3625 #endif /* defined(HASTCPTPIQ) */
3629 #endif /* defined(HASIPv6) */
3633 (void) get_tcpudp(TCPpath, 0, 1);
3634 (void) free((FREE_P *)TCPpath);
3635 TCPpath = (char *)NULL;
3639 (void) get_tcpudp(UDPpath, 1, 0);
3640 (void) free((FREE_P *)UDPpath);
3641 UDPpath = (char *)NULL;
3645 (void) get_tcpudp(UDPLITEpath, 2, 0);
3646 (void) free((FREE_P *)UDPLITEpath);
3647 UDPLITEpath = (char *)NULL;
3649 if (!Fxopt && (ss & SB_INO)
3650 && (tp = check_tcpudp((INODETYPE)s->st_ino, &pr))
3654 * The inode is connected to an IPv4 TCP or UDP /proc record.
3656 * Set the type to "inet" or "IPv4"; enter the protocol; put the
3657 * inode number in the DEVICE column in lieu of the PCB address;
3658 * save the local and foreign IPv4 addresses; save the type and
3659 * protocol; and (optionally) save the queue sizes.
3661 i = tp->state + TcpStOff;
3665 * Check for state exclusion.
3667 if (i >= 0 && i < TcpNstates) {
3677 * Check for state inclusion.
3679 if (i >= 0 && i < TcpNstates) {
3688 if (Fnet && (FnetTy != 6))
3691 #if defined(HASIPv6)
3692 (void) snpf(Lf->type, sizeof(Lf->type), "IPv4");
3693 #else /* !defined(HASIPv6) */
3694 (void) snpf(Lf->type, sizeof(Lf->type), "inet");
3695 #endif /* defined(HASIPv6) */
3697 (void) snpf(Lf->iproto, sizeof(Lf->iproto), "%.*s", IPROTOL-1, pr);
3700 (void) snpf(tbuf, sizeof(tbuf), InodeFmt_d,
3701 (INODETYPE)s->st_ino);
3702 tbuf[sizeof(tbuf) - 1] = '\0';
3705 if (tp->faddr || tp->fport) {
3706 fs.s_addr = tp->faddr;
3707 fa = (unsigned char *)&fs;
3709 fa = (unsigned char *)NULL;
3710 if (tp->laddr || tp->lport) {
3711 ls.s_addr = tp->laddr;
3712 la = (unsigned char *)&ls;
3714 la = (unsigned char *)NULL;
3715 ent_inaddr(la, tp->lport, fa, tp->fport, AF_INET);
3716 Lf->lts.type = tp->proto;
3717 Lf->lts.state.i = tp->state;
3719 #if defined(HASTCPTPIQ)
3720 Lf->lts.rq = tp->rxq;
3721 Lf->lts.sq = tp->txq;
3722 Lf->lts.rqs = Lf->lts.sqs = 1;
3723 #endif /* defined(HASTCPTPIQ) */
3729 for (i = 0; i < NSCTPPATHS; i++) {
3730 (void) free((FREE_P *)SCTPPath[i]);
3731 SCTPPath[i] = (char *)NULL;
3734 if ((ss & SB_INO) && (sp = check_sctp((INODETYPE)s->st_ino))
3738 * The inode is connected to an SCTP /proc record.
3740 * Set the type to "sock"; enter the inode number in the DEVICE
3741 * column; set the protocol to SCTP; and fill in the NAME column
3742 * with ASSOC, ASSOC-ID, ENDPT, LADDRS, LPORT, RADDRS and RPORT.
3744 (void) snpf(Lf->type, sizeof(Lf->type), "sock");
3745 (void) snpf(Lf->iproto, sizeof(Lf->iproto), "%.*s", IPROTOL-1,
3748 (void) snpf(tbuf, sizeof(tbuf), InodeFmt_d, (INODETYPE)s->st_ino);
3749 tbuf[sizeof(tbuf) - 1] = '\0';
3752 if (sp->type == 1) {
3755 * This is an ENDPT SCTP file.
3757 (void) snpf(Namech, Namechl,
3758 "ENDPT: %s%s%s%s%s%s",
3759 sp->addr ? sp->addr : "",
3760 (sp->laddrs || sp->lport) ? " " : "",
3761 sp->laddrs ? sp->laddrs : "",
3762 sp->lport ? "[" : "",
3763 sp->lport ? sp->lport : "",
3764 sp->lport ? "]" : ""
3769 * This is an ASSOC, or ASSOC and ENDPT socket file.
3771 (void) snpf(Namech, Namechl,
3772 "%s: %s%s%s %s%s%s%s%s%s%s%s%s",
3773 sp->type ? "ASSOC+ENDPT" : "ASSOC",
3774 sp->addr ? sp->addr : "",
3775 (sp->addr && sp->assocID) ? "," : "",
3776 sp->assocID ? sp->assocID : "",
3777 sp->laddrs ? sp->laddrs : "",
3778 sp->lport ? "[" : "",
3779 sp->lport ? sp->lport : "",
3780 sp->lport ? "]" : "",
3781 ((sp->laddrs || sp->lport) && (sp->raddrs || sp->rport))
3783 sp->raddrs ? sp->raddrs : "",
3784 sp->rport ? "[" : "",
3785 sp->rport ? sp->rport : "",
3786 sp->rport ? "]" : ""
3794 (void) get_icmp(ICMPpath);
3795 (void) free((FREE_P *)ICMPpath);
3796 ICMPpath = (char *)NULL;
3799 && (icmpp = check_icmp((INODETYPE)s->st_ino))
3803 * The inode is connected to an ICMP /proc record.
3805 * Set the type to "icmp" and store the type in the NAME
3806 * column. Save the inode number.
3808 (void) snpf(Lf->type, sizeof(Lf->type), "icmp");
3809 Lf->inode = (INODETYPE)s->st_ino;
3814 if (icmpp->la && icmpp->lal) {
3817 * Store the local raw address.
3819 if (nl > icmpp->lal) {
3820 (void) snpf(cp, nl, "%s", icmpp->la);
3826 if (icmpp->ra && icmpp->ral) {
3829 * Store the remote raw address, prefixed with "->".
3831 if (nl > (icmpp->ral + 2)) {
3832 (void) snpf(cp, nl, "->%s", icmpp->ra);
3833 cp += (icmpp->ral + 2);
3835 nl -= (icmpp->ral + 2);
3843 * The socket's protocol can't be identified.
3845 (void) snpf(Lf->type, sizeof(Lf->type), "sock");
3847 Lf->inode = (INODETYPE)s->st_ino;
3851 Lf->dev = s->st_dev;
3855 enter_nm("can't identify protocol (-X specified)");
3857 (void) snpf(Namech, Namechl, "protocol: ");
3859 i = (int)strlen(Namech);
3861 sz = (ssize_t)(Namechl - i - 1);
3863 if ((getxattr(pbr, "system.sockprotoname", prp, sz)) < 0)
3864 enter_nm("can't identify protocol");
3872 * set_net_paths() - set /proc/net paths
3876 set_net_paths(p, pl)
3877 char *p; /* path to /proc/net/ */
3878 int pl; /* strlen(p) */
3884 (void) make_proc_path(p, pl, &AX25path, &pathl, "ax25");
3886 (void) make_proc_path(p, pl, &ICMPpath, &pathl, "icmp");
3888 (void) make_proc_path(p, pl, &Ipxpath, &pathl, "ipx");
3890 (void) make_proc_path(p, pl, &Nlkpath, &pathl, "netlink");
3892 (void) make_proc_path(p, pl, &Packpath, &pathl, "packet");
3894 (void) make_proc_path(p, pl, &Rawpath, &pathl, "raw");
3895 for (i = 0; i < NSCTPPATHS; i++) {
3897 (void) make_proc_path(p, pl, &SCTPPath[i], &pathl, SCTPSfx[i]);
3900 (void) make_proc_path(p, pl, &SockStatPath, &pathl, "sockstat");
3902 (void) make_proc_path(p, pl, &TCPpath, &pathl, "tcp");
3904 (void) make_proc_path(p, pl, &UDPpath, &pathl, "udp");
3906 (void) make_proc_path(p, pl, &UDPLITEpath, &pathl, "udplite");
3908 #if defined(HASIPv6)
3910 (void) make_proc_path(p, pl, &Raw6path, &pathl, "raw6");
3912 (void) make_proc_path(p, pl, &SockStatPath6, &pathl, "sockstat6");
3914 (void) make_proc_path(p, pl, &TCP6path, &pathl, "tcp6");
3916 (void) make_proc_path(p, pl, &UDP6path, &pathl, "udp6");
3918 (void) make_proc_path(p, pl, &UDPLITE6path, &pathl, "udplite6");
3919 #endif /* defined(HASIPv6) */
3922 (void) make_proc_path(p, pl, &UNIXpath, &pathl, "unix");
3927 * Sockty2str() -- convert socket type number to a string
3932 uint32_t ty; /* socket type number */
3933 int *rf; /* result flag: 0 == known
3936 int f = 0; /* result flag */
3937 char *sr; /*string result */
3941 #if defined(SOCK_STREAM)
3945 #endif /* defined(SOCK_STREAM) */
3947 #if defined(SOCK_DGRAM)
3951 #endif /* defined(SOCK_DGRAM) */
3953 #if defined(SOCK_RAW)
3957 #endif /* defined(SOCK_RAW) */
3959 #if defined(SOCK_RDM)
3963 #endif /* defined(SOCK_RDM) */
3965 #if defined(SOCK_SEQPACKET)
3966 case SOCK_SEQPACKET:
3969 #endif /* defined(SOCK_SEQPACKET) */
3971 #if defined(SOCK_PACKET)
3975 #endif /* defined(SOCK_PACKET) */