• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * ss.c		"sockstat", socket statistics
3  *
4  *		This program is free software; you can redistribute it and/or
5  *		modify it under the terms of the GNU General Public License
6  *		as published by the Free Software Foundation; either version
7  *		2 of the License, or (at your option) any later version.
8  *
9  * Authors:	Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
10  */
11 
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <unistd.h>
15 #include <syslog.h>
16 #include <fcntl.h>
17 #include <sys/ioctl.h>
18 #include <sys/socket.h>
19 #include <sys/uio.h>
20 #include <netinet/in.h>
21 #include <string.h>
22 #include <errno.h>
23 #include <netdb.h>
24 #include <arpa/inet.h>
25 #include <resolv.h>
26 #include <dirent.h>
27 #include <fnmatch.h>
28 #include <getopt.h>
29 
30 #include "utils.h"
31 #include "rt_names.h"
32 #include "ll_map.h"
33 #include "libnetlink.h"
34 #include "SNAPSHOT.h"
35 
36 #include <netinet/tcp.h>
37 #include <linux/inet_diag.h>
38 
39 int resolve_hosts = 0;
40 int resolve_services = 1;
41 int preferred_family = AF_UNSPEC;
42 int show_options = 0;
43 int show_details = 0;
44 int show_users = 0;
45 int show_mem = 0;
46 int show_tcpinfo = 0;
47 
48 int netid_width;
49 int state_width;
50 int addrp_width;
51 int addr_width;
52 int serv_width;
53 int screen_width;
54 
55 static const char *TCP_PROTO = "tcp";
56 static const char *UDP_PROTO = "udp";
57 static const char *RAW_PROTO = "raw";
58 static const char *dg_proto = NULL;
59 
60 enum
61 {
62 	TCP_DB,
63 	DCCP_DB,
64 	UDP_DB,
65 	RAW_DB,
66 	UNIX_DG_DB,
67 	UNIX_ST_DB,
68 	PACKET_DG_DB,
69 	PACKET_R_DB,
70 	NETLINK_DB,
71 	MAX_DB
72 };
73 
74 #define PACKET_DBM ((1<<PACKET_DG_DB)|(1<<PACKET_R_DB))
75 #define UNIX_DBM ((1<<UNIX_DG_DB)|(1<<UNIX_ST_DB))
76 #define ALL_DB ((1<<MAX_DB)-1)
77 
78 enum {
79 	SS_UNKNOWN,
80 	SS_ESTABLISHED,
81 	SS_SYN_SENT,
82 	SS_SYN_RECV,
83 	SS_FIN_WAIT1,
84 	SS_FIN_WAIT2,
85 	SS_TIME_WAIT,
86 	SS_CLOSE,
87 	SS_CLOSE_WAIT,
88 	SS_LAST_ACK,
89 	SS_LISTEN,
90 	SS_CLOSING,
91 	SS_MAX
92 };
93 
94 #define SS_ALL ((1<<SS_MAX)-1)
95 
96 #include "ssfilter.h"
97 
98 struct filter
99 {
100 	int dbs;
101 	int states;
102 	int families;
103 	struct ssfilter *f;
104 };
105 
106 struct filter default_filter = {
107 	.dbs	=  (1<<TCP_DB),
108 	.states = SS_ALL & ~((1<<SS_LISTEN)|(1<<SS_CLOSE)|(1<<SS_TIME_WAIT)|(1<<SS_SYN_RECV)),
109 	.families= (1<<AF_INET)|(1<<AF_INET6),
110 };
111 
112 struct filter current_filter;
113 
generic_proc_open(const char * env,const char * name)114 static FILE *generic_proc_open(const char *env, const char *name)
115 {
116 	const char *p = getenv(env);
117 	char store[128];
118 
119 	if (!p) {
120 		p = getenv("PROC_ROOT") ? : "/proc";
121 		snprintf(store, sizeof(store)-1, "%s/%s", p, name);
122 		p = store;
123 	}
124 
125 	return fopen(p, "r");
126 }
127 
net_tcp_open(void)128 static FILE *net_tcp_open(void)
129 {
130 	return generic_proc_open("PROC_NET_TCP", "net/tcp");
131 }
132 
net_tcp6_open(void)133 static FILE *net_tcp6_open(void)
134 {
135 	return generic_proc_open("PROC_NET_TCP6", "net/tcp6");
136 }
137 
net_udp_open(void)138 static FILE *net_udp_open(void)
139 {
140 	return generic_proc_open("PROC_NET_UDP", "net/udp");
141 }
142 
net_udp6_open(void)143 static FILE *net_udp6_open(void)
144 {
145 	return generic_proc_open("PROC_NET_UDP6", "net/udp6");
146 }
147 
net_raw_open(void)148 static FILE *net_raw_open(void)
149 {
150 	return generic_proc_open("PROC_NET_RAW", "net/raw");
151 }
152 
net_raw6_open(void)153 static FILE *net_raw6_open(void)
154 {
155 	return generic_proc_open("PROC_NET_RAW6", "net/raw6");
156 }
157 
net_unix_open(void)158 static FILE *net_unix_open(void)
159 {
160 	return generic_proc_open("PROC_NET_UNIX", "net/unix");
161 }
162 
net_packet_open(void)163 static FILE *net_packet_open(void)
164 {
165 	return generic_proc_open("PROC_NET_PACKET", "net/packet");
166 }
167 
net_netlink_open(void)168 static FILE *net_netlink_open(void)
169 {
170 	return generic_proc_open("PROC_NET_NETLINK", "net/netlink");
171 }
172 
slabinfo_open(void)173 static FILE *slabinfo_open(void)
174 {
175 	return generic_proc_open("PROC_SLABINFO", "slabinfo");
176 }
177 
net_sockstat_open(void)178 static FILE *net_sockstat_open(void)
179 {
180 	return generic_proc_open("PROC_NET_SOCKSTAT", "net/sockstat");
181 }
182 
net_sockstat6_open(void)183 static FILE *net_sockstat6_open(void)
184 {
185 	return generic_proc_open("PROC_NET_SOCKSTAT6", "net/sockstat6");
186 }
187 
net_snmp_open(void)188 static FILE *net_snmp_open(void)
189 {
190 	return generic_proc_open("PROC_NET_SNMP", "net/snmp");
191 }
192 
ephemeral_ports_open(void)193 static FILE *ephemeral_ports_open(void)
194 {
195 	return generic_proc_open("PROC_IP_LOCAL_PORT_RANGE", "sys/net/ipv4/ip_local_port_range");
196 }
197 
198 struct user_ent {
199 	struct user_ent	*next;
200 	unsigned int	ino;
201 	int		pid;
202 	int		fd;
203 	char		process[0];
204 };
205 
206 #define USER_ENT_HASH_SIZE	256
207 struct user_ent *user_ent_hash[USER_ENT_HASH_SIZE];
208 
user_ent_hashfn(unsigned int ino)209 static int user_ent_hashfn(unsigned int ino)
210 {
211 	int val = (ino >> 24) ^ (ino >> 16) ^ (ino >> 8) ^ ino;
212 
213 	return val & (USER_ENT_HASH_SIZE - 1);
214 }
215 
user_ent_add(unsigned int ino,const char * process,int pid,int fd)216 static void user_ent_add(unsigned int ino, const char *process, int pid, int fd)
217 {
218 	struct user_ent *p, **pp;
219 	int str_len;
220 
221 	str_len = strlen(process) + 1;
222 	p = malloc(sizeof(struct user_ent) + str_len);
223 	if (!p)
224 		abort();
225 	p->next = NULL;
226 	p->ino = ino;
227 	p->pid = pid;
228 	p->fd = fd;
229 	strcpy(p->process, process);
230 
231 	pp = &user_ent_hash[user_ent_hashfn(ino)];
232 	p->next = *pp;
233 	*pp = p;
234 }
235 
user_ent_hash_build(void)236 static void user_ent_hash_build(void)
237 {
238 	const char *root = getenv("PROC_ROOT") ? : "/proc/";
239 	struct dirent *d;
240 	char name[1024];
241 	int nameoff;
242 	DIR *dir;
243 
244 	strcpy(name, root);
245 	if (strlen(name) == 0 || name[strlen(name)-1] != '/')
246 		strcat(name, "/");
247 
248 	nameoff = strlen(name);
249 
250 	dir = opendir(name);
251 	if (!dir)
252 		return;
253 
254 	while ((d = readdir(dir)) != NULL) {
255 		struct dirent *d1;
256 		char process[16];
257 		int pid, pos;
258 		DIR *dir1;
259 		char crap;
260 
261 		if (sscanf(d->d_name, "%d%c", &pid, &crap) != 1)
262 			continue;
263 
264 		sprintf(name + nameoff, "%d/fd/", pid);
265 		pos = strlen(name);
266 		if ((dir1 = opendir(name)) == NULL)
267 			continue;
268 
269 		process[0] = '\0';
270 
271 		while ((d1 = readdir(dir1)) != NULL) {
272 			const char *pattern = "socket:[";
273 			unsigned int ino;
274 			char lnk[64];
275 			int fd, n;
276 
277 			if (sscanf(d1->d_name, "%d%c", &fd, &crap) != 1)
278 				continue;
279 
280 			sprintf(name+pos, "%d", fd);
281 			n = readlink(name, lnk, sizeof(lnk)-1);
282 			if (strncmp(lnk, pattern, strlen(pattern)))
283 				continue;
284 
285 			sscanf(lnk, "socket:[%u]", &ino);
286 
287 			if (process[0] == '\0') {
288 				char tmp[1024];
289 				FILE *fp;
290 
291 				snprintf(tmp, sizeof(tmp), "%s/%d/stat", root, pid);
292 				if ((fp = fopen(tmp, "r")) != NULL) {
293 					fscanf(fp, "%*d (%[^)])", process);
294 					fclose(fp);
295 				}
296 			}
297 
298 			user_ent_add(ino, process, pid, fd);
299 		}
300 		closedir(dir1);
301 	}
302 	closedir(dir);
303 }
304 
find_users(unsigned ino,char * buf,int buflen)305 int find_users(unsigned ino, char *buf, int buflen)
306 {
307 	struct user_ent *p;
308 	int cnt = 0;
309 	char *ptr;
310 
311 	if (!ino)
312 		return 0;
313 
314 	p = user_ent_hash[user_ent_hashfn(ino)];
315 	ptr = buf;
316 	while (p) {
317 		if (p->ino != ino)
318 			goto next;
319 
320 		if (ptr - buf >= buflen - 1)
321 			break;
322 
323 		snprintf(ptr, buflen - (ptr - buf),
324 			 "(\"%s\",%d,%d),",
325 			 p->process, p->pid, p->fd);
326 		ptr += strlen(ptr);
327 		cnt++;
328 
329 	next:
330 		p = p->next;
331 	}
332 
333 	if (ptr != buf)
334 		ptr[-1] = '\0';
335 
336 	return cnt;
337 }
338 
339 /* Get stats from slab */
340 
341 struct slabstat
342 {
343 	int socks;
344 	int tcp_ports;
345 	int tcp_tws;
346 	int tcp_syns;
347 	int skbs;
348 };
349 
350 struct slabstat slabstat;
351 
352 static const char *slabstat_ids[] =
353 {
354 	"sock",
355 	"tcp_bind_bucket",
356 	"tcp_tw_bucket",
357 	"tcp_open_request",
358 	"skbuff_head_cache",
359 };
360 
get_slabstat(struct slabstat * s)361 int get_slabstat(struct slabstat *s)
362 {
363 	char buf[256];
364 	FILE *fp;
365 	int cnt;
366 
367 	memset(s, 0, sizeof(*s));
368 
369 	fp = slabinfo_open();
370 	if (!fp)
371 		return -1;
372 
373 	cnt = sizeof(*s)/sizeof(int);
374 
375 	fgets(buf, sizeof(buf), fp);
376 	while(fgets(buf, sizeof(buf), fp) != NULL) {
377 		int i;
378 		for (i=0; i<sizeof(slabstat_ids)/sizeof(slabstat_ids[0]); i++) {
379 			if (memcmp(buf, slabstat_ids[i], strlen(slabstat_ids[i])) == 0) {
380 				sscanf(buf, "%*s%d", ((int *)s) + i);
381 				cnt--;
382 				break;
383 			}
384 		}
385 		if (cnt <= 0)
386 			break;
387 	}
388 
389 	fclose(fp);
390 	return 0;
391 }
392 
393 static const char *sstate_name[] = {
394 	"UNKNOWN",
395 	[TCP_ESTABLISHED] = "ESTAB",
396 	[TCP_SYN_SENT] = "SYN-SENT",
397 	[TCP_SYN_RECV] = "SYN-RECV",
398 	[TCP_FIN_WAIT1] = "FIN-WAIT-1",
399 	[TCP_FIN_WAIT2] = "FIN-WAIT-2",
400 	[TCP_TIME_WAIT] = "TIME-WAIT",
401 	[TCP_CLOSE] = "UNCONN",
402 	[TCP_CLOSE_WAIT] = "CLOSE-WAIT",
403 	[TCP_LAST_ACK] = "LAST-ACK",
404 	[TCP_LISTEN] = 	"LISTEN",
405 	[TCP_CLOSING] = "CLOSING",
406 };
407 
408 static const char *sstate_namel[] = {
409 	"UNKNOWN",
410 	[TCP_ESTABLISHED] = "established",
411 	[TCP_SYN_SENT] = "syn-sent",
412 	[TCP_SYN_RECV] = "syn-recv",
413 	[TCP_FIN_WAIT1] = "fin-wait-1",
414 	[TCP_FIN_WAIT2] = "fin-wait-2",
415 	[TCP_TIME_WAIT] = "time-wait",
416 	[TCP_CLOSE] = "unconnected",
417 	[TCP_CLOSE_WAIT] = "close-wait",
418 	[TCP_LAST_ACK] = "last-ack",
419 	[TCP_LISTEN] = 	"listening",
420 	[TCP_CLOSING] = "closing",
421 };
422 
423 struct tcpstat
424 {
425 	inet_prefix	local;
426 	inet_prefix	remote;
427 	int		lport;
428 	int		rport;
429 	int		state;
430 	int		rq, wq;
431 	int		timer;
432 	int		timeout;
433 	int		retrs;
434 	unsigned	ino;
435 	int		probes;
436 	unsigned	uid;
437 	int		refcnt;
438 	unsigned long long sk;
439 	int		rto, ato, qack, cwnd, ssthresh;
440 };
441 
442 static const char *tmr_name[] = {
443 	"off",
444 	"on",
445 	"keepalive",
446 	"timewait",
447 	"persist",
448 	"unknown"
449 };
450 
print_ms_timer(int timeout)451 const char *print_ms_timer(int timeout)
452 {
453 	static char buf[64];
454 	int secs, msecs, minutes;
455 	if (timeout < 0)
456 		timeout = 0;
457 	secs = timeout/1000;
458 	minutes = secs/60;
459 	secs = secs%60;
460 	msecs = timeout%1000;
461 	buf[0] = 0;
462 	if (minutes) {
463 		msecs = 0;
464 		snprintf(buf, sizeof(buf)-16, "%dmin", minutes);
465 		if (minutes > 9)
466 			secs = 0;
467 	}
468 	if (secs) {
469 		if (secs > 9)
470 			msecs = 0;
471 		sprintf(buf+strlen(buf), "%d%s", secs, msecs ? "." : "sec");
472 	}
473 	if (msecs)
474 		sprintf(buf+strlen(buf), "%03dms", msecs);
475 	return buf;
476 }
477 
print_hz_timer(int timeout)478 const char *print_hz_timer(int timeout)
479 {
480 	int hz = get_user_hz();
481 	return print_ms_timer(((timeout*1000) + hz-1)/hz);
482 }
483 
484 struct scache
485 {
486 	struct scache *next;
487 	int port;
488 	char *name;
489 	const char *proto;
490 };
491 
492 struct scache *rlist;
493 
init_service_resolver(void)494 void init_service_resolver(void)
495 {
496 	char buf[128];
497 	FILE *fp = popen("/usr/sbin/rpcinfo -p 2>/dev/null", "r");
498 	if (fp) {
499 		fgets(buf, sizeof(buf), fp);
500 		while (fgets(buf, sizeof(buf), fp) != NULL) {
501 			unsigned int progn, port;
502 			char proto[128], prog[128];
503 			if (sscanf(buf, "%u %*d %s %u %s", &progn, proto,
504 				   &port, prog+4) == 4) {
505 				struct scache *c = malloc(sizeof(*c));
506 				if (c) {
507 					c->port = port;
508 					memcpy(prog, "rpc.", 4);
509 					c->name = strdup(prog);
510 					if (strcmp(proto, TCP_PROTO) == 0)
511 						c->proto = TCP_PROTO;
512 					else if (strcmp(proto, UDP_PROTO) == 0)
513 						c->proto = UDP_PROTO;
514 					else
515 						c->proto = NULL;
516 					c->next = rlist;
517 					rlist = c;
518 				}
519 			}
520 		}
521 	}
522 }
523 
524 static int ip_local_port_min, ip_local_port_max;
525 
526 /* Even do not try default linux ephemeral port ranges:
527  * default /etc/services contains so much of useless crap
528  * wouldbe "allocated" to this area that resolution
529  * is really harmful. I shrug each time when seeing
530  * "socks" or "cfinger" in dumps.
531  */
is_ephemeral(int port)532 static int is_ephemeral(int port)
533 {
534 	if (!ip_local_port_min) {
535 		FILE *f = ephemeral_ports_open();
536 		if (f) {
537 			fscanf(f, "%d %d",
538 			       &ip_local_port_min, &ip_local_port_max);
539 			fclose(f);
540 		} else {
541 			ip_local_port_min = 1024;
542 			ip_local_port_max = 4999;
543 		}
544 	}
545 
546 	return (port >= ip_local_port_min && port<= ip_local_port_max);
547 }
548 
549 
__resolve_service(int port)550 const char *__resolve_service(int port)
551 {
552 	struct scache *c;
553 
554 	for (c = rlist; c; c = c->next) {
555 		if (c->port == port && c->proto == dg_proto)
556 			return c->name;
557 	}
558 
559 	if (!is_ephemeral(port)) {
560 		static int notfirst;
561 		struct servent *se;
562 		if (!notfirst) {
563 			setservent(1);
564 			notfirst = 1;
565 		}
566 		se = getservbyport(htons(port), dg_proto);
567 		if (se)
568 			return se->s_name;
569 	}
570 
571 	return NULL;
572 }
573 
574 
resolve_service(int port)575 const char *resolve_service(int port)
576 {
577 	static char buf[128];
578 	static struct scache cache[256];
579 
580 	if (port == 0) {
581 		buf[0] = '*';
582 		buf[1] = 0;
583 		return buf;
584 	}
585 
586 	if (resolve_services) {
587 		if (dg_proto == RAW_PROTO) {
588 			return inet_proto_n2a(port, buf, sizeof(buf));
589 		} else {
590 			struct scache *c;
591 			const char *res;
592 			int hash = (port^(((unsigned long)dg_proto)>>2))&255;
593 
594 			for (c = &cache[hash]; c; c = c->next) {
595 				if (c->port == port &&
596 				    c->proto == dg_proto) {
597 					if (c->name)
598 						return c->name;
599 					goto do_numeric;
600 				}
601 			}
602 
603 			if ((res = __resolve_service(port)) != NULL) {
604 				if ((c = malloc(sizeof(*c))) == NULL)
605 					goto do_numeric;
606 			} else {
607 				c = &cache[hash];
608 				if (c->name)
609 					free(c->name);
610 			}
611 			c->port = port;
612 			c->name = NULL;
613 			c->proto = dg_proto;
614 			if (res) {
615 				c->name = strdup(res);
616 				c->next = cache[hash].next;
617 				cache[hash].next = c;
618 			}
619 			if (c->name)
620 				return c->name;
621 		}
622 	}
623 
624 	do_numeric:
625 	sprintf(buf, "%u", port);
626 	return buf;
627 }
628 
formatted_print(const inet_prefix * a,int port)629 void formatted_print(const inet_prefix *a, int port)
630 {
631 	char buf[1024];
632 	const char *ap = buf;
633 	int est_len;
634 
635 	est_len = addr_width;
636 
637 	if (a->family == AF_INET) {
638 		if (a->data[0] == 0) {
639 			buf[0] = '*';
640 			buf[1] = 0;
641 		} else {
642 			ap = format_host(AF_INET, 4, a->data, buf, sizeof(buf));
643 		}
644 	} else {
645 		ap = format_host(a->family, 16, a->data, buf, sizeof(buf));
646 		est_len = strlen(ap);
647 		if (est_len <= addr_width)
648 			est_len = addr_width;
649 		else
650 			est_len = addr_width + ((est_len-addr_width+3)/4)*4;
651 	}
652 	printf("%*s:%-*s ", est_len, ap, serv_width, resolve_service(port));
653 }
654 
655 struct aafilter
656 {
657 	inet_prefix	addr;
658 	int		port;
659 	struct aafilter *next;
660 };
661 
inet2_addr_match(const inet_prefix * a,const inet_prefix * p,int plen)662 int inet2_addr_match(const inet_prefix *a, const inet_prefix *p, int plen)
663 {
664 	if (!inet_addr_match(a, p, plen))
665 		return 0;
666 
667 	/* Cursed "v4 mapped" addresses: v4 mapped socket matches
668 	 * pure IPv4 rule, but v4-mapped rule selects only v4-mapped
669 	 * sockets. Fair? */
670 	if (p->family == AF_INET && a->family == AF_INET6) {
671 		if (a->data[0] == 0 && a->data[1] == 0 &&
672 		    a->data[2] == htonl(0xffff)) {
673 			inet_prefix tmp = *a;
674 			tmp.data[0] = a->data[3];
675 			return inet_addr_match(&tmp, p, plen);
676 		}
677 	}
678 	return 1;
679 }
680 
unix_match(const inet_prefix * a,const inet_prefix * p)681 int unix_match(const inet_prefix *a, const inet_prefix *p)
682 {
683 	char *addr, *pattern;
684 	memcpy(&addr, a->data, sizeof(addr));
685 	memcpy(&pattern, p->data, sizeof(pattern));
686 	if (pattern == NULL)
687 		return 1;
688 	if (addr == NULL)
689 		addr = "";
690 	return !fnmatch(pattern, addr, 0);
691 }
692 
run_ssfilter(struct ssfilter * f,struct tcpstat * s)693 int run_ssfilter(struct ssfilter *f, struct tcpstat *s)
694 {
695 	switch (f->type) {
696 		case SSF_S_AUTO:
697 	{
698                 static int low, high=65535;
699 
700 		if (s->local.family == AF_UNIX) {
701 			char *p;
702 			memcpy(&p, s->local.data, sizeof(p));
703 			return p == NULL || (p[0] == '@' && strlen(p) == 6 &&
704 					     strspn(p+1, "0123456789abcdef") == 5);
705 		}
706 		if (s->local.family == AF_PACKET)
707 			return s->lport == 0 && s->local.data == 0;
708 		if (s->local.family == AF_NETLINK)
709 			return s->lport < 0;
710 
711                 if (!low) {
712 			FILE *fp = ephemeral_ports_open();
713 			if (fp) {
714 				fscanf(fp, "%d%d", &low, &high);
715 				fclose(fp);
716 			}
717 		}
718 		return s->lport >= low && s->lport <= high;
719 	}
720 		case SSF_DCOND:
721 	{
722 		struct aafilter *a = (void*)f->pred;
723 		if (a->addr.family == AF_UNIX)
724 			return unix_match(&s->remote, &a->addr);
725 		if (a->port != -1 && a->port != s->rport)
726 			return 0;
727 		if (a->addr.bitlen) {
728 			do {
729 				if (!inet2_addr_match(&s->remote, &a->addr, a->addr.bitlen))
730 					return 1;
731 			} while ((a = a->next) != NULL);
732 			return 0;
733 		}
734 		return 1;
735 	}
736 		case SSF_SCOND:
737 	{
738 		struct aafilter *a = (void*)f->pred;
739 		if (a->addr.family == AF_UNIX)
740 			return unix_match(&s->local, &a->addr);
741 		if (a->port != -1 && a->port != s->lport)
742 			return 0;
743 		if (a->addr.bitlen) {
744 			do {
745 				if (!inet2_addr_match(&s->local, &a->addr, a->addr.bitlen))
746 					return 1;
747 			} while ((a = a->next) != NULL);
748 			return 0;
749 		}
750 		return 1;
751 	}
752 		case SSF_D_GE:
753 	{
754 		struct aafilter *a = (void*)f->pred;
755 		return s->rport >= a->port;
756 	}
757 		case SSF_D_LE:
758 	{
759 		struct aafilter *a = (void*)f->pred;
760 		return s->rport <= a->port;
761 	}
762 		case SSF_S_GE:
763 	{
764 		struct aafilter *a = (void*)f->pred;
765 		return s->lport >= a->port;
766 	}
767 		case SSF_S_LE:
768 	{
769 		struct aafilter *a = (void*)f->pred;
770 		return s->lport <= a->port;
771 	}
772 
773 		/* Yup. It is recursion. Sorry. */
774 		case SSF_AND:
775 		return run_ssfilter(f->pred, s) && run_ssfilter(f->post, s);
776 		case SSF_OR:
777 		return run_ssfilter(f->pred, s) || run_ssfilter(f->post, s);
778 		case SSF_NOT:
779 		return !run_ssfilter(f->pred, s);
780 		default:
781 		abort();
782 	}
783 }
784 
785 /* Relocate external jumps by reloc. */
ssfilter_patch(char * a,int len,int reloc)786 static void ssfilter_patch(char *a, int len, int reloc)
787 {
788 	while (len > 0) {
789 		struct inet_diag_bc_op *op = (struct inet_diag_bc_op*)a;
790 		if (op->no == len+4)
791 			op->no += reloc;
792 		len -= op->yes;
793 		a += op->yes;
794 	}
795 	if (len < 0)
796 		abort();
797 }
798 
ssfilter_bytecompile(struct ssfilter * f,char ** bytecode)799 static int ssfilter_bytecompile(struct ssfilter *f, char **bytecode)
800 {
801 	switch (f->type) {
802 		case SSF_S_AUTO:
803 	{
804 		if (!(*bytecode=malloc(4))) abort();
805 		((struct inet_diag_bc_op*)*bytecode)[0] = (struct inet_diag_bc_op){ INET_DIAG_BC_AUTO, 4, 8 };
806 		return 8;
807 	}
808 		case SSF_DCOND:
809 		case SSF_SCOND:
810 	{
811 		struct aafilter *a = (void*)f->pred;
812 		struct aafilter *b;
813 		char *ptr;
814 		int  code = (f->type == SSF_DCOND ? INET_DIAG_BC_D_COND : INET_DIAG_BC_S_COND);
815 		int len = 0;
816 
817 		for (b=a; b; b=b->next) {
818 			len += 4 + sizeof(struct inet_diag_hostcond);
819 			if (a->addr.family == AF_INET6)
820 				len += 16;
821 			else
822 				len += 4;
823 			if (b->next)
824 				len += 4;
825 		}
826 		if (!(ptr = malloc(len))) abort();
827 		*bytecode = ptr;
828 		for (b=a; b; b=b->next) {
829 			struct inet_diag_bc_op *op = (struct inet_diag_bc_op *)ptr;
830 			int alen = (a->addr.family == AF_INET6 ? 16 : 4);
831 			int oplen = alen + 4 + sizeof(struct inet_diag_hostcond);
832 			struct inet_diag_hostcond *cond = (struct inet_diag_hostcond*)(ptr+4);
833 
834 			*op = (struct inet_diag_bc_op){ code, oplen, oplen+4 };
835 			cond->family = a->addr.family;
836 			cond->port = a->port;
837 			cond->prefix_len = a->addr.bitlen;
838 			memcpy(cond->addr, a->addr.data, alen);
839 			ptr += oplen;
840 			if (b->next) {
841 				op = (struct inet_diag_bc_op *)ptr;
842 				*op = (struct inet_diag_bc_op){ INET_DIAG_BC_JMP, 4, len - (ptr-*bytecode)};
843 				ptr += 4;
844 			}
845 		}
846 		return ptr - *bytecode;
847 	}
848 		case SSF_D_GE:
849 	{
850 		struct aafilter *x = (void*)f->pred;
851 		if (!(*bytecode=malloc(8))) abort();
852 		((struct inet_diag_bc_op*)*bytecode)[0] = (struct inet_diag_bc_op){ INET_DIAG_BC_D_GE, 8, 12 };
853 		((struct inet_diag_bc_op*)*bytecode)[1] = (struct inet_diag_bc_op){ 0, 0, x->port };
854 		return 8;
855 	}
856 		case SSF_D_LE:
857 	{
858 		struct aafilter *x = (void*)f->pred;
859 		if (!(*bytecode=malloc(8))) abort();
860 		((struct inet_diag_bc_op*)*bytecode)[0] = (struct inet_diag_bc_op){ INET_DIAG_BC_D_LE, 8, 12 };
861 		((struct inet_diag_bc_op*)*bytecode)[1] = (struct inet_diag_bc_op){ 0, 0, x->port };
862 		return 8;
863 	}
864 		case SSF_S_GE:
865 	{
866 		struct aafilter *x = (void*)f->pred;
867 		if (!(*bytecode=malloc(8))) abort();
868 		((struct inet_diag_bc_op*)*bytecode)[0] = (struct inet_diag_bc_op){ INET_DIAG_BC_S_GE, 8, 12 };
869 		((struct inet_diag_bc_op*)*bytecode)[1] = (struct inet_diag_bc_op){ 0, 0, x->port };
870 		return 8;
871 	}
872 		case SSF_S_LE:
873 	{
874 		struct aafilter *x = (void*)f->pred;
875 		if (!(*bytecode=malloc(8))) abort();
876 		((struct inet_diag_bc_op*)*bytecode)[0] = (struct inet_diag_bc_op){ INET_DIAG_BC_S_LE, 8, 12 };
877 		((struct inet_diag_bc_op*)*bytecode)[1] = (struct inet_diag_bc_op){ 0, 0, x->port };
878 		return 8;
879 	}
880 
881 		case SSF_AND:
882 	{
883 		char *a1, *a2, *a, l1, l2;
884 		l1 = ssfilter_bytecompile(f->pred, &a1);
885 		l2 = ssfilter_bytecompile(f->post, &a2);
886 		if (!(a = malloc(l1+l2))) abort();
887 		memcpy(a, a1, l1);
888 		memcpy(a+l1, a2, l2);
889 		free(a1); free(a2);
890 		ssfilter_patch(a, l1, l2);
891 		*bytecode = a;
892 		return l1+l2;
893 	}
894 		case SSF_OR:
895 	{
896 		char *a1, *a2, *a, l1, l2;
897 		l1 = ssfilter_bytecompile(f->pred, &a1);
898 		l2 = ssfilter_bytecompile(f->post, &a2);
899 		if (!(a = malloc(l1+l2+4))) abort();
900 		memcpy(a, a1, l1);
901 		memcpy(a+l1+4, a2, l2);
902 		free(a1); free(a2);
903 		*(struct inet_diag_bc_op*)(a+l1) = (struct inet_diag_bc_op){ INET_DIAG_BC_JMP, 4, l2+4 };
904 		*bytecode = a;
905 		return l1+l2+4;
906 	}
907 		case SSF_NOT:
908 	{
909 		char *a1, *a, l1;
910 		l1 = ssfilter_bytecompile(f->pred, &a1);
911 		if (!(a = malloc(l1+4))) abort();
912 		memcpy(a, a1, l1);
913 		free(a1);
914 		*(struct inet_diag_bc_op*)(a+l1) = (struct inet_diag_bc_op){ INET_DIAG_BC_JMP, 4, 8 };
915 		*bytecode = a;
916 		return l1+4;
917 	}
918 		default:
919 		abort();
920 	}
921 }
922 
remember_he(struct aafilter * a,struct hostent * he)923 static int remember_he(struct aafilter *a, struct hostent *he)
924 {
925 	char **ptr = he->h_addr_list;
926 	int cnt = 0;
927 	int len;
928 
929 	if (he->h_addrtype == AF_INET)
930 		len = 4;
931 	else if (he->h_addrtype == AF_INET6)
932 		len = 16;
933 	else
934 		return 0;
935 
936 	while (*ptr) {
937 		struct aafilter *b = a;
938 		if (a->addr.bitlen) {
939 			if ((b = malloc(sizeof(*b))) == NULL)
940 				return cnt;
941 			*b = *a;
942 			b->next = a->next;
943 			a->next = b;
944 		}
945 		memcpy(b->addr.data, *ptr, len);
946 		b->addr.bytelen = len;
947 		b->addr.bitlen = len*8;
948 		b->addr.family = he->h_addrtype;
949 		ptr++;
950 		cnt++;
951 	}
952 	return cnt;
953 }
954 
get_dns_host(struct aafilter * a,const char * addr,int fam)955 static int get_dns_host(struct aafilter *a, const char *addr, int fam)
956 {
957 	static int notfirst;
958 	int cnt = 0;
959 	struct hostent *he;
960 
961 	a->addr.bitlen = 0;
962 	if (!notfirst) {
963 		sethostent(1);
964 		notfirst = 1;
965 	}
966 	he = gethostbyname2(addr, fam == AF_UNSPEC ? AF_INET : fam);
967 	if (he)
968 		cnt = remember_he(a, he);
969 	if (fam == AF_UNSPEC) {
970 		he = gethostbyname2(addr, AF_INET6);
971 		if (he)
972 			cnt += remember_he(a, he);
973 	}
974 	return !cnt;
975 }
976 
977 static int xll_initted = 0;
978 
xll_init(void)979 static void xll_init(void)
980 {
981 	struct rtnl_handle rth;
982 	rtnl_open(&rth, 0);
983 	ll_init_map(&rth);
984 	rtnl_close(&rth);
985 	xll_initted = 1;
986 }
987 
xll_index_to_name(int index)988 static const char *xll_index_to_name(int index)
989 {
990 	if (!xll_initted)
991 		xll_init();
992 	return ll_index_to_name(index);
993 }
994 
xll_name_to_index(const char * dev)995 static int xll_name_to_index(const char *dev)
996 {
997 	if (!xll_initted)
998 		xll_init();
999 	return ll_name_to_index(dev);
1000 }
1001 
parse_hostcond(char * addr)1002 void *parse_hostcond(char *addr)
1003 {
1004 	char *port = NULL;
1005 	struct aafilter a;
1006 	struct aafilter *res;
1007 	int fam = preferred_family;
1008 
1009 	memset(&a, 0, sizeof(a));
1010 	a.port = -1;
1011 
1012 	if (fam == AF_UNIX || strncmp(addr, "unix:", 5) == 0) {
1013 		char *p;
1014 		a.addr.family = AF_UNIX;
1015 		if (strncmp(addr, "unix:", 5) == 0)
1016 			addr+=5;
1017 		p = strdup(addr);
1018 		a.addr.bitlen = 8*strlen(p);
1019 		memcpy(a.addr.data, &p, sizeof(p));
1020 		goto out;
1021 	}
1022 
1023 	if (fam == AF_PACKET || strncmp(addr, "link:", 5) == 0) {
1024 		a.addr.family = AF_PACKET;
1025 		a.addr.bitlen = 0;
1026 		if (strncmp(addr, "link:", 5) == 0)
1027 			addr+=5;
1028 		port = strchr(addr, ':');
1029 		if (port) {
1030 			*port = 0;
1031 			if (port[1] && strcmp(port+1, "*")) {
1032 				if (get_integer(&a.port, port+1, 0)) {
1033 					if ((a.port = xll_name_to_index(port+1)) <= 0)
1034 						return NULL;
1035 				}
1036 			}
1037 		}
1038 		if (addr[0] && strcmp(addr, "*")) {
1039 			unsigned short tmp;
1040 			a.addr.bitlen = 32;
1041 			if (ll_proto_a2n(&tmp, addr))
1042 				return NULL;
1043 			a.addr.data[0] = ntohs(tmp);
1044 		}
1045 		goto out;
1046 	}
1047 
1048 	if (fam == AF_NETLINK || strncmp(addr, "netlink:", 8) == 0) {
1049 		a.addr.family = AF_NETLINK;
1050 		a.addr.bitlen = 0;
1051 		if (strncmp(addr, "netlink:", 8) == 0)
1052 			addr+=8;
1053 		port = strchr(addr, ':');
1054 		if (port) {
1055 			*port = 0;
1056 			if (port[1] && strcmp(port+1, "*")) {
1057 				if (get_integer(&a.port, port+1, 0)) {
1058 					if (strcmp(port+1, "kernel") == 0)
1059 						a.port = 0;
1060 					else
1061 						return NULL;
1062 				}
1063 			}
1064 		}
1065 		if (addr[0] && strcmp(addr, "*")) {
1066 			a.addr.bitlen = 32;
1067 			if (get_u32(a.addr.data, addr, 0)) {
1068 				if (strcmp(addr, "rtnl") == 0)
1069 					a.addr.data[0] = 0;
1070 				else if (strcmp(addr, "fw") == 0)
1071 					a.addr.data[0] = 3;
1072 				else if (strcmp(addr, "tcpdiag") == 0)
1073 					a.addr.data[0] = 4;
1074 				else
1075 					return NULL;
1076 			}
1077 		}
1078 		goto out;
1079 	}
1080 
1081 	if (strncmp(addr, "inet:", 5) == 0) {
1082 		addr += 5;
1083 		fam = AF_INET;
1084 	} else if (strncmp(addr, "inet6:", 6) == 0) {
1085 		addr += 6;
1086 		fam = AF_INET6;
1087 	}
1088 
1089 	/* URL-like literal [] */
1090 	if (addr[0] == '[') {
1091 		addr++;
1092 		if ((port = strchr(addr, ']')) == NULL)
1093 			return NULL;
1094 		*port++ = 0;
1095 	} else if (addr[0] == '*') {
1096 		port = addr+1;
1097 	} else {
1098 		port = strrchr(strchr(addr, '/') ? : addr, ':');
1099 	}
1100 	if (port && *port) {
1101 		if (*port != ':')
1102 			return NULL;
1103 		*port++ = 0;
1104 		if (*port && *port != '*') {
1105 			if (get_integer(&a.port, port, 0)) {
1106 				struct servent *se1 = NULL;
1107 				struct servent *se2 = NULL;
1108 				if (current_filter.dbs&(1<<UDP_DB))
1109 					se1 = getservbyname(port, UDP_PROTO);
1110 				if (current_filter.dbs&(1<<TCP_DB))
1111 					se2 = getservbyname(port, TCP_PROTO);
1112 				if (se1 && se2 && se1->s_port != se2->s_port) {
1113 					fprintf(stderr, "Error: ambiguous port \"%s\".\n", port);
1114 					return NULL;
1115 				}
1116 				if (!se1)
1117 					se1 = se2;
1118 				if (se1) {
1119 					a.port = ntohs(se1->s_port);
1120 				} else {
1121 					struct scache *s;
1122 					for (s = rlist; s; s = s->next) {
1123 						if ((s->proto == UDP_PROTO &&
1124 						     (current_filter.dbs&(1<<UDP_DB))) ||
1125 						    (s->proto == TCP_PROTO &&
1126 						     (current_filter.dbs&(1<<TCP_DB)))) {
1127 							if (s->name && strcmp(s->name, port) == 0) {
1128 								if (a.port > 0 && a.port != s->port) {
1129 									fprintf(stderr, "Error: ambiguous port \"%s\".\n", port);
1130 									return NULL;
1131 								}
1132 								a.port = s->port;
1133 							}
1134 						}
1135 					}
1136 					if (a.port <= 0) {
1137 						fprintf(stderr, "Error: \"%s\" does not look like a port.\n", port);
1138 						return NULL;
1139 					}
1140 				}
1141 			}
1142 		}
1143 	}
1144 	if (addr && *addr && *addr != '*') {
1145 		if (get_prefix_1(&a.addr, addr, fam)) {
1146 			if (get_dns_host(&a, addr, fam)) {
1147 				fprintf(stderr, "Error: an inet prefix is expected rather than \"%s\".\n", addr);
1148 				return NULL;
1149 			}
1150 		}
1151 	}
1152 
1153 	out:
1154 	res = malloc(sizeof(*res));
1155 	if (res)
1156 		memcpy(res, &a, sizeof(a));
1157 	return res;
1158 }
1159 
tcp_show_line(char * line,const struct filter * f,int family)1160 static int tcp_show_line(char *line, const struct filter *f, int family)
1161 {
1162 	struct tcpstat s;
1163 	char *loc, *rem, *data;
1164 	char opt[256];
1165 	int n;
1166 	char *p;
1167 
1168 	if ((p = strchr(line, ':')) == NULL)
1169 		return -1;
1170 	loc = p+2;
1171 
1172 	if ((p = strchr(loc, ':')) == NULL)
1173 		return -1;
1174 	p[5] = 0;
1175 	rem = p+6;
1176 
1177 	if ((p = strchr(rem, ':')) == NULL)
1178 		return -1;
1179 	p[5] = 0;
1180 	data = p+6;
1181 
1182 	do {
1183 		int state = (data[1] >= 'A') ? (data[1] - 'A' + 10) : (data[1] - '0');
1184 
1185 		if (!(f->states & (1<<state)))
1186 			return 0;
1187 	} while (0);
1188 
1189 	s.local.family = s.remote.family = family;
1190 	if (family == AF_INET) {
1191 		sscanf(loc, "%x:%x", s.local.data, (unsigned*)&s.lport);
1192 		sscanf(rem, "%x:%x", s.remote.data, (unsigned*)&s.rport);
1193 		s.local.bytelen = s.remote.bytelen = 4;
1194 	} else {
1195 		sscanf(loc, "%08x%08x%08x%08x:%x",
1196 		       s.local.data,
1197 		       s.local.data+1,
1198 		       s.local.data+2,
1199 		       s.local.data+3,
1200 		       &s.lport);
1201 		sscanf(rem, "%08x%08x%08x%08x:%x",
1202 		       s.remote.data,
1203 		       s.remote.data+1,
1204 		       s.remote.data+2,
1205 		       s.remote.data+3,
1206 		       &s.rport);
1207 		s.local.bytelen = s.remote.bytelen = 16;
1208 	}
1209 
1210 	if (f->f && run_ssfilter(f->f, &s) == 0)
1211 		return 0;
1212 
1213 	opt[0] = 0;
1214 	n = sscanf(data, "%x %x:%x %x:%x %x %d %d %u %d %llx %d %d %d %d %d %[^\n]\n",
1215 		   &s.state, &s.wq, &s.rq,
1216 		   &s.timer, &s.timeout, &s.retrs, &s.uid, &s.probes, &s.ino,
1217 		   &s.refcnt, &s.sk, &s.rto, &s.ato, &s.qack,
1218 		   &s.cwnd, &s.ssthresh, opt);
1219 
1220 	if (n < 17)
1221 		opt[0] = 0;
1222 
1223 	if (n < 12) {
1224 		s.rto = 0;
1225 		s.cwnd = 2;
1226 		s.ssthresh = -1;
1227 		s.ato = s.qack = 0;
1228 	}
1229 
1230 	if (netid_width)
1231 		printf("%-*s ", netid_width, "tcp");
1232 	if (state_width)
1233 		printf("%-*s ", state_width, sstate_name[s.state]);
1234 
1235 	printf("%-6d %-6d ", s.rq, s.wq);
1236 
1237 	formatted_print(&s.local, s.lport);
1238 	formatted_print(&s.remote, s.rport);
1239 
1240 	if (show_options) {
1241 		if (s.timer) {
1242 			if (s.timer > 4)
1243 				s.timer = 5;
1244 			printf(" timer:(%s,%s,%d)",
1245 			       tmr_name[s.timer],
1246 			       print_hz_timer(s.timeout),
1247 			       s.timer != 1 ? s.probes : s.retrs);
1248 		}
1249 	}
1250 	if (show_tcpinfo) {
1251 		int hz = get_user_hz();
1252 		if (s.rto && s.rto != 3*hz)
1253 			printf(" rto:%g", (double)s.rto/hz);
1254 		if (s.ato)
1255 			printf(" ato:%g", (double)s.ato/hz);
1256 		if (s.cwnd != 2)
1257 			printf(" cwnd:%d", s.cwnd);
1258 		if (s.ssthresh != -1)
1259 			printf(" ssthresh:%d", s.ssthresh);
1260 		if (s.qack/2)
1261 			printf(" qack:%d", s.qack/2);
1262 		if (s.qack&1)
1263 			printf(" bidir");
1264 	}
1265 	if (show_users) {
1266 		char ubuf[4096];
1267 		if (find_users(s.ino, ubuf, sizeof(ubuf)) > 0)
1268 			printf(" users:(%s)", ubuf);
1269 	}
1270 	if (show_details) {
1271 		if (s.uid)
1272 			printf(" uid:%u", (unsigned)s.uid);
1273 		printf(" ino:%u", s.ino);
1274 		printf(" sk:%llx", s.sk);
1275 		if (opt[0])
1276 			printf(" opt:\"%s\"", opt);
1277 	}
1278 	printf("\n");
1279 
1280 	return 0;
1281 }
1282 
generic_record_read(FILE * fp,int (* worker)(char *,const struct filter *,int),const struct filter * f,int fam)1283 static int generic_record_read(FILE *fp,
1284 			       int (*worker)(char*, const struct filter *, int),
1285 			       const struct filter *f, int fam)
1286 {
1287 	char line[256];
1288 
1289 	/* skip header */
1290 	if (fgets(line, sizeof(line), fp) == NULL)
1291 		goto outerr;
1292 
1293 	while (fgets(line, sizeof(line), fp) != NULL) {
1294 		int n = strlen(line);
1295 		if (n == 0 || line[n-1] != '\n') {
1296 			errno = -EINVAL;
1297 			return -1;
1298 		}
1299 		line[n-1] = 0;
1300 
1301 		if (worker(line, f, fam) < 0)
1302 			return 0;
1303 	}
1304 outerr:
1305 
1306 	return ferror(fp) ? -1 : 0;
1307 }
1308 
sprint_bw(char * buf,double bw)1309 static char *sprint_bw(char *buf, double bw)
1310 {
1311 	if (bw > 1000000.)
1312 		sprintf(buf,"%.1fM", bw / 1000000.);
1313 	else if (bw > 1000.)
1314 		sprintf(buf,"%.1fK", bw / 1000.);
1315 	else
1316 		sprintf(buf, "%g", bw);
1317 
1318 	return buf;
1319 }
1320 
tcp_show_info(const struct nlmsghdr * nlh,struct inet_diag_msg * r)1321 static void tcp_show_info(const struct nlmsghdr *nlh, struct inet_diag_msg *r)
1322 {
1323 	struct rtattr * tb[INET_DIAG_MAX+1];
1324 	char b1[64];
1325 	double rtt = 0;
1326 
1327 	parse_rtattr(tb, INET_DIAG_MAX, (struct rtattr*)(r+1),
1328 		     nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*r)));
1329 
1330 	if (tb[INET_DIAG_MEMINFO]) {
1331 		const struct inet_diag_meminfo *minfo
1332 			= RTA_DATA(tb[INET_DIAG_MEMINFO]);
1333 		printf(" mem:(r%u,w%u,f%u,t%u)",
1334 		       minfo->idiag_rmem,
1335 		       minfo->idiag_wmem,
1336 		       minfo->idiag_fmem,
1337 		       minfo->idiag_tmem);
1338 	}
1339 
1340 	if (tb[INET_DIAG_INFO]) {
1341 		struct tcp_info *info;
1342 		int len = RTA_PAYLOAD(tb[INET_DIAG_INFO]);
1343 
1344 		/* workaround for older kernels with less fields */
1345 		if (len < sizeof(*info)) {
1346 			info = alloca(sizeof(*info));
1347 			memset(info, 0, sizeof(*info));
1348 			memcpy(info, RTA_DATA(tb[INET_DIAG_INFO]), len);
1349 		} else
1350 			info = RTA_DATA(tb[INET_DIAG_INFO]);
1351 
1352 		if (show_options) {
1353 			if (info->tcpi_options & TCPI_OPT_TIMESTAMPS)
1354 				printf(" ts");
1355 			if (info->tcpi_options & TCPI_OPT_SACK)
1356 				printf(" sack");
1357 			if (info->tcpi_options & TCPI_OPT_ECN)
1358 				printf(" ecn");
1359 		}
1360 
1361 		if (tb[INET_DIAG_CONG])
1362 			printf(" %s", (char *) RTA_DATA(tb[INET_DIAG_CONG]));
1363 
1364 		if (info->tcpi_options & TCPI_OPT_WSCALE)
1365 			printf(" wscale:%d,%d", info->tcpi_snd_wscale,
1366 			       info->tcpi_rcv_wscale);
1367 		if (info->tcpi_rto && info->tcpi_rto != 3000000)
1368 			printf(" rto:%g", (double)info->tcpi_rto/1000);
1369 		if (info->tcpi_rtt)
1370 			printf(" rtt:%g/%g", (double)info->tcpi_rtt/1000,
1371 			       (double)info->tcpi_rttvar/1000);
1372 		if (info->tcpi_ato)
1373 			printf(" ato:%g", (double)info->tcpi_ato/1000);
1374 		if (info->tcpi_snd_cwnd != 2)
1375 			printf(" cwnd:%d", info->tcpi_snd_cwnd);
1376 		if (info->tcpi_snd_ssthresh < 0xFFFF)
1377 			printf(" ssthresh:%d", info->tcpi_snd_ssthresh);
1378 
1379 		rtt = (double) info->tcpi_rtt;
1380 		if (tb[INET_DIAG_VEGASINFO]) {
1381 			const struct tcpvegas_info *vinfo
1382 				= RTA_DATA(tb[INET_DIAG_VEGASINFO]);
1383 
1384 			if (vinfo->tcpv_enabled &&
1385 			    vinfo->tcpv_rtt && vinfo->tcpv_rtt != 0x7fffffff)
1386 				rtt =  vinfo->tcpv_rtt;
1387 		}
1388 
1389 		if (rtt > 0 && info->tcpi_snd_mss && info->tcpi_snd_cwnd) {
1390 			printf(" send %sbps",
1391 			       sprint_bw(b1, (double) info->tcpi_snd_cwnd *
1392 					 (double) info->tcpi_snd_mss * 8000000.
1393 					 / rtt));
1394 		}
1395 
1396 		if (info->tcpi_rcv_rtt)
1397 			printf(" rcv_rtt:%g", (double) info->tcpi_rcv_rtt/1000);
1398 		if (info->tcpi_rcv_space)
1399 			printf(" rcv_space:%d", info->tcpi_rcv_space);
1400 
1401 	}
1402 }
1403 
tcp_show_sock(struct nlmsghdr * nlh,struct filter * f)1404 static int tcp_show_sock(struct nlmsghdr *nlh, struct filter *f)
1405 {
1406 	struct inet_diag_msg *r = NLMSG_DATA(nlh);
1407 	struct tcpstat s;
1408 
1409 	s.state = r->idiag_state;
1410 	s.local.family = s.remote.family = r->idiag_family;
1411 	s.lport = ntohs(r->id.idiag_sport);
1412 	s.rport = ntohs(r->id.idiag_dport);
1413 	if (s.local.family == AF_INET) {
1414 		s.local.bytelen = s.remote.bytelen = 4;
1415 	} else {
1416 		s.local.bytelen = s.remote.bytelen = 16;
1417 	}
1418 	memcpy(s.local.data, r->id.idiag_src, s.local.bytelen);
1419 	memcpy(s.remote.data, r->id.idiag_dst, s.local.bytelen);
1420 
1421 	if (f && f->f && run_ssfilter(f->f, &s) == 0)
1422 		return 0;
1423 
1424 	if (netid_width)
1425 		printf("%-*s ", netid_width, "tcp");
1426 	if (state_width)
1427 		printf("%-*s ", state_width, sstate_name[s.state]);
1428 
1429 	printf("%-6d %-6d ", r->idiag_rqueue, r->idiag_wqueue);
1430 
1431 	formatted_print(&s.local, s.lport);
1432 	formatted_print(&s.remote, s.rport);
1433 
1434 	if (show_options) {
1435 		if (r->idiag_timer) {
1436 			if (r->idiag_timer > 4)
1437 				r->idiag_timer = 5;
1438 			printf(" timer:(%s,%s,%d)",
1439 			       tmr_name[r->idiag_timer],
1440 			       print_ms_timer(r->idiag_expires),
1441 			       r->idiag_retrans);
1442 		}
1443 	}
1444 	if (show_users) {
1445 		char ubuf[4096];
1446 		if (find_users(r->idiag_inode, ubuf, sizeof(ubuf)) > 0)
1447 			printf(" users:(%s)", ubuf);
1448 	}
1449 	if (show_details) {
1450 		if (r->idiag_uid)
1451 			printf(" uid:%u", (unsigned)r->idiag_uid);
1452 		printf(" ino:%u", r->idiag_inode);
1453 		printf(" sk:");
1454 		if (r->id.idiag_cookie[1] != 0)
1455 			printf("%08x", r->id.idiag_cookie[1]);
1456  		printf("%08x", r->id.idiag_cookie[0]);
1457 	}
1458 	if (show_mem || show_tcpinfo) {
1459 		printf("\n\t");
1460 		tcp_show_info(nlh, r);
1461 	}
1462 
1463 	printf("\n");
1464 
1465 	return 0;
1466 }
1467 
tcp_show_netlink(struct filter * f,FILE * dump_fp,int socktype)1468 static int tcp_show_netlink(struct filter *f, FILE *dump_fp, int socktype)
1469 {
1470 	int fd;
1471 	struct sockaddr_nl nladdr;
1472 	struct {
1473 		struct nlmsghdr nlh;
1474 		struct inet_diag_req r;
1475 	} req;
1476 	char    *bc = NULL;
1477 	int	bclen;
1478 	struct msghdr msg;
1479 	struct rtattr rta;
1480 	char	buf[8192];
1481 	struct iovec iov[3];
1482 
1483 	if ((fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_INET_DIAG)) < 0)
1484 		return -1;
1485 
1486 	memset(&nladdr, 0, sizeof(nladdr));
1487 	nladdr.nl_family = AF_NETLINK;
1488 
1489 	req.nlh.nlmsg_len = sizeof(req);
1490 	req.nlh.nlmsg_type = socktype;
1491 	req.nlh.nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST;
1492 	req.nlh.nlmsg_pid = 0;
1493 	req.nlh.nlmsg_seq = 123456;
1494 	memset(&req.r, 0, sizeof(req.r));
1495 	req.r.idiag_family = AF_INET;
1496 	req.r.idiag_states = f->states;
1497 	if (show_mem)
1498 		req.r.idiag_ext |= (1<<(INET_DIAG_MEMINFO-1));
1499 
1500 	if (show_tcpinfo) {
1501 		req.r.idiag_ext |= (1<<(INET_DIAG_INFO-1));
1502 		req.r.idiag_ext |= (1<<(INET_DIAG_VEGASINFO-1));
1503 		req.r.idiag_ext |= (1<<(INET_DIAG_CONG-1));
1504 	}
1505 
1506 	iov[0] = (struct iovec){
1507 		.iov_base = &req,
1508 		.iov_len = sizeof(req)
1509 	};
1510 	if (f->f) {
1511 		bclen = ssfilter_bytecompile(f->f, &bc);
1512 		rta.rta_type = INET_DIAG_REQ_BYTECODE;
1513 		rta.rta_len = RTA_LENGTH(bclen);
1514 		iov[1] = (struct iovec){ &rta, sizeof(rta) };
1515 		iov[2] = (struct iovec){ bc, bclen };
1516 		req.nlh.nlmsg_len += RTA_LENGTH(bclen);
1517 	}
1518 
1519 	msg = (struct msghdr) {
1520 		.msg_name = (void*)&nladdr,
1521 		.msg_namelen = sizeof(nladdr),
1522 		.msg_iov = iov,
1523 		.msg_iovlen = f->f ? 3 : 1,
1524 	};
1525 
1526 	if (sendmsg(fd, &msg, 0) < 0)
1527 		return -1;
1528 
1529 	iov[0] = (struct iovec){
1530 		.iov_base = buf,
1531 		.iov_len = sizeof(buf)
1532 	};
1533 
1534 	while (1) {
1535 		int status;
1536 		struct nlmsghdr *h;
1537 
1538 		msg = (struct msghdr) {
1539 			(void*)&nladdr, sizeof(nladdr),
1540 			iov,	1,
1541 			NULL,	0,
1542 			0
1543 		};
1544 
1545 		status = recvmsg(fd, &msg, 0);
1546 
1547 		if (status < 0) {
1548 			if (errno == EINTR)
1549 				continue;
1550 			perror("OVERRUN");
1551 			continue;
1552 		}
1553 		if (status == 0) {
1554 			fprintf(stderr, "EOF on netlink\n");
1555 			return 0;
1556 		}
1557 
1558 		if (dump_fp)
1559 			fwrite(buf, 1, NLMSG_ALIGN(status), dump_fp);
1560 
1561 		h = (struct nlmsghdr*)buf;
1562 		while (NLMSG_OK(h, status)) {
1563 			int err;
1564 			struct inet_diag_msg *r = NLMSG_DATA(h);
1565 
1566 			if (/*h->nlmsg_pid != rth->local.nl_pid ||*/
1567 			    h->nlmsg_seq != 123456)
1568 				goto skip_it;
1569 
1570 			if (h->nlmsg_type == NLMSG_DONE)
1571 				return 0;
1572 			if (h->nlmsg_type == NLMSG_ERROR) {
1573 				struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h);
1574 				if (h->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr))) {
1575 					fprintf(stderr, "ERROR truncated\n");
1576 				} else {
1577 					errno = -err->error;
1578 					perror("TCPDIAG answers");
1579 				}
1580 				return 0;
1581 			}
1582 			if (!dump_fp) {
1583 				if (!(f->families & (1<<r->idiag_family))) {
1584 					h = NLMSG_NEXT(h, status);
1585 					continue;
1586 				}
1587 				err = tcp_show_sock(h, NULL);
1588 				if (err < 0)
1589 					return err;
1590 			}
1591 
1592 skip_it:
1593 			h = NLMSG_NEXT(h, status);
1594 		}
1595 		if (msg.msg_flags & MSG_TRUNC) {
1596 			fprintf(stderr, "Message truncated\n");
1597 			continue;
1598 		}
1599 		if (status) {
1600 			fprintf(stderr, "!!!Remnant of size %d\n", status);
1601 			exit(1);
1602 		}
1603 	}
1604 	return 0;
1605 }
1606 
tcp_show_netlink_file(struct filter * f)1607 static int tcp_show_netlink_file(struct filter *f)
1608 {
1609 	FILE	*fp;
1610 	char	buf[8192];
1611 
1612 	if ((fp = fopen(getenv("TCPDIAG_FILE"), "r")) == NULL) {
1613 		perror("fopen($TCPDIAG_FILE)");
1614 		return -1;
1615 	}
1616 
1617 	while (1) {
1618 		int status, err;
1619 		struct nlmsghdr *h = (struct nlmsghdr*)buf;
1620 
1621 		status = fread(buf, 1, sizeof(*h), fp);
1622 		if (status < 0) {
1623 			perror("Reading header from $TCPDIAG_FILE");
1624 			return -1;
1625 		}
1626 		if (status != sizeof(*h)) {
1627 			perror("Unexpected EOF reading $TCPDIAG_FILE");
1628 			return -1;
1629 		}
1630 
1631 		status = fread(h+1, 1, NLMSG_ALIGN(h->nlmsg_len-sizeof(*h)), fp);
1632 
1633 		if (status < 0) {
1634 			perror("Reading $TCPDIAG_FILE");
1635 			return -1;
1636 		}
1637 		if (status + sizeof(*h) < h->nlmsg_len) {
1638 			perror("Unexpected EOF reading $TCPDIAG_FILE");
1639 			return -1;
1640 		}
1641 
1642 		/* The only legal exit point */
1643 		if (h->nlmsg_type == NLMSG_DONE)
1644 			return 0;
1645 
1646 		if (h->nlmsg_type == NLMSG_ERROR) {
1647 			struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h);
1648 			if (h->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr))) {
1649 				fprintf(stderr, "ERROR truncated\n");
1650 			} else {
1651 				errno = -err->error;
1652 				perror("TCPDIAG answered");
1653 			}
1654 			return -1;
1655 		}
1656 
1657 		err = tcp_show_sock(h, f);
1658 		if (err < 0)
1659 			return err;
1660 	}
1661 }
1662 
tcp_show(struct filter * f,int socktype)1663 static int tcp_show(struct filter *f, int socktype)
1664 {
1665 	FILE *fp = NULL;
1666 	char *buf = NULL;
1667 	int bufsize = 64*1024;
1668 
1669 	dg_proto = TCP_PROTO;
1670 
1671 	if (getenv("TCPDIAG_FILE"))
1672 		return tcp_show_netlink_file(f);
1673 
1674 	if (!getenv("PROC_NET_TCP") && !getenv("PROC_ROOT")
1675 	    && tcp_show_netlink(f, NULL, socktype) == 0)
1676 		return 0;
1677 
1678 	/* Sigh... We have to parse /proc/net/tcp... */
1679 
1680 
1681 	/* Estimate amount of sockets and try to allocate
1682 	 * huge buffer to read all the table at one read.
1683 	 * Limit it by 16MB though. The assumption is: as soon as
1684 	 * kernel was able to hold information about N connections,
1685 	 * it is able to give us some memory for snapshot.
1686 	 */
1687 	if (1) {
1688 		int guess = slabstat.socks+slabstat.tcp_syns;
1689 		if (f->states&(1<<SS_TIME_WAIT))
1690 			guess += slabstat.tcp_tws;
1691 		if (guess > (16*1024*1024)/128)
1692 			guess = (16*1024*1024)/128;
1693 		guess *= 128;
1694 		if (guess > bufsize)
1695 			bufsize = guess;
1696 	}
1697 	while (bufsize >= 64*1024) {
1698 		if ((buf = malloc(bufsize)) != NULL)
1699 			break;
1700 		bufsize /= 2;
1701 	}
1702 	if (buf == NULL) {
1703 		errno = ENOMEM;
1704 		return -1;
1705 	}
1706 
1707 	if (f->families & (1<<AF_INET)) {
1708 		if ((fp = net_tcp_open()) == NULL)
1709 			goto outerr;
1710 
1711 		setbuffer(fp, buf, bufsize);
1712 		if (generic_record_read(fp, tcp_show_line, f, AF_INET))
1713 			goto outerr;
1714 		fclose(fp);
1715 	}
1716 
1717 	if ((f->families & (1<<AF_INET6)) &&
1718 	    (fp = net_tcp6_open()) != NULL) {
1719 		setbuffer(fp, buf, bufsize);
1720 		if (generic_record_read(fp, tcp_show_line, f, AF_INET6))
1721 			goto outerr;
1722 		fclose(fp);
1723 	}
1724 
1725 	free(buf);
1726 	return 0;
1727 
1728 outerr:
1729 	do {
1730 		int saved_errno = errno;
1731 		if (buf)
1732 			free(buf);
1733 		if (fp)
1734 			fclose(fp);
1735 		errno = saved_errno;
1736 		return -1;
1737 	} while (0);
1738 }
1739 
1740 
dgram_show_line(char * line,const struct filter * f,int family)1741 int dgram_show_line(char *line, const struct filter *f, int family)
1742 {
1743 	struct tcpstat s;
1744 	char *loc, *rem, *data;
1745 	char opt[256];
1746 	int n;
1747 	char *p;
1748 
1749 	if ((p = strchr(line, ':')) == NULL)
1750 		return -1;
1751 	loc = p+2;
1752 
1753 	if ((p = strchr(loc, ':')) == NULL)
1754 		return -1;
1755 	p[5] = 0;
1756 	rem = p+6;
1757 
1758 	if ((p = strchr(rem, ':')) == NULL)
1759 		return -1;
1760 	p[5] = 0;
1761 	data = p+6;
1762 
1763 	do {
1764 		int state = (data[1] >= 'A') ? (data[1] - 'A' + 10) : (data[1] - '0');
1765 
1766 		if (!(f->states & (1<<state)))
1767 			return 0;
1768 	} while (0);
1769 
1770 	s.local.family = s.remote.family = family;
1771 	if (family == AF_INET) {
1772 		sscanf(loc, "%x:%x", s.local.data, (unsigned*)&s.lport);
1773 		sscanf(rem, "%x:%x", s.remote.data, (unsigned*)&s.rport);
1774 		s.local.bytelen = s.remote.bytelen = 4;
1775 	} else {
1776 		sscanf(loc, "%08x%08x%08x%08x:%x",
1777 		       s.local.data,
1778 		       s.local.data+1,
1779 		       s.local.data+2,
1780 		       s.local.data+3,
1781 		       &s.lport);
1782 		sscanf(rem, "%08x%08x%08x%08x:%x",
1783 		       s.remote.data,
1784 		       s.remote.data+1,
1785 		       s.remote.data+2,
1786 		       s.remote.data+3,
1787 		       &s.rport);
1788 		s.local.bytelen = s.remote.bytelen = 16;
1789 	}
1790 
1791 	if (f->f && run_ssfilter(f->f, &s) == 0)
1792 		return 0;
1793 
1794 	opt[0] = 0;
1795 	n = sscanf(data, "%x %x:%x %*x:%*x %*x %d %*d %u %d %llx %[^\n]\n",
1796 	       &s.state, &s.wq, &s.rq,
1797 	       &s.uid, &s.ino,
1798 	       &s.refcnt, &s.sk, opt);
1799 
1800 	if (n < 9)
1801 		opt[0] = 0;
1802 
1803 	if (netid_width)
1804 		printf("%-*s ", netid_width, dg_proto);
1805 	if (state_width)
1806 		printf("%-*s ", state_width, sstate_name[s.state]);
1807 
1808 	printf("%-6d %-6d ", s.rq, s.wq);
1809 
1810 	formatted_print(&s.local, s.lport);
1811 	formatted_print(&s.remote, s.rport);
1812 
1813 	if (show_users) {
1814 		char ubuf[4096];
1815 		if (find_users(s.ino, ubuf, sizeof(ubuf)) > 0)
1816 			printf(" users:(%s)", ubuf);
1817 	}
1818 
1819 	if (show_details) {
1820 		if (s.uid)
1821 			printf(" uid=%u", (unsigned)s.uid);
1822 		printf(" ino=%u", s.ino);
1823 		printf(" sk=%llx", s.sk);
1824 		if (opt[0])
1825 			printf(" opt:\"%s\"", opt);
1826 	}
1827 	printf("\n");
1828 
1829 	return 0;
1830 }
1831 
1832 
udp_show(struct filter * f)1833 int udp_show(struct filter *f)
1834 {
1835 	FILE *fp = NULL;
1836 
1837 	dg_proto = UDP_PROTO;
1838 
1839 	if (f->families&(1<<AF_INET)) {
1840 		if ((fp = net_udp_open()) == NULL)
1841 			goto outerr;
1842 		if (generic_record_read(fp, dgram_show_line, f, AF_INET))
1843 			goto outerr;
1844 		fclose(fp);
1845 	}
1846 
1847 	if ((f->families&(1<<AF_INET6)) &&
1848 	    (fp = net_udp6_open()) != NULL) {
1849 		if (generic_record_read(fp, dgram_show_line, f, AF_INET6))
1850 			goto outerr;
1851 		fclose(fp);
1852 	}
1853 	return 0;
1854 
1855 outerr:
1856 	do {
1857 		int saved_errno = errno;
1858 		if (fp)
1859 			fclose(fp);
1860 		errno = saved_errno;
1861 		return -1;
1862 	} while (0);
1863 }
1864 
raw_show(struct filter * f)1865 int raw_show(struct filter *f)
1866 {
1867 	FILE *fp = NULL;
1868 
1869 	dg_proto = RAW_PROTO;
1870 
1871 	if (f->families&(1<<AF_INET)) {
1872 		if ((fp = net_raw_open()) == NULL)
1873 			goto outerr;
1874 		if (generic_record_read(fp, dgram_show_line, f, AF_INET))
1875 			goto outerr;
1876 		fclose(fp);
1877 	}
1878 
1879 	if ((f->families&(1<<AF_INET6)) &&
1880 	    (fp = net_raw6_open()) != NULL) {
1881 		if (generic_record_read(fp, dgram_show_line, f, AF_INET6))
1882 			goto outerr;
1883 		fclose(fp);
1884 	}
1885 	return 0;
1886 
1887 outerr:
1888 	do {
1889 		int saved_errno = errno;
1890 		if (fp)
1891 			fclose(fp);
1892 		errno = saved_errno;
1893 		return -1;
1894 	} while (0);
1895 }
1896 
1897 
1898 struct unixstat
1899 {
1900 	struct unixstat *next;
1901 	int ino;
1902 	int peer;
1903 	int rq;
1904 	int wq;
1905 	int state;
1906 	int type;
1907 	char *name;
1908 };
1909 
1910 
1911 
1912 int unix_state_map[] = { SS_CLOSE, SS_SYN_SENT,
1913 			 SS_ESTABLISHED, SS_CLOSING };
1914 
1915 
1916 #define MAX_UNIX_REMEMBER (1024*1024/sizeof(struct unixstat))
1917 
unix_list_free(struct unixstat * list)1918 void unix_list_free(struct unixstat *list)
1919 {
1920 	while (list) {
1921 		struct unixstat *s = list;
1922 		list = list->next;
1923 		if (s->name)
1924 			free(s->name);
1925 		free(s);
1926 	}
1927 }
1928 
unix_list_print(struct unixstat * list,struct filter * f)1929 void unix_list_print(struct unixstat *list, struct filter *f)
1930 {
1931 	struct unixstat *s;
1932 	char *peer;
1933 
1934 	for (s = list; s; s = s->next) {
1935 		if (!(f->states & (1<<s->state)))
1936 			continue;
1937 		if (s->type == SOCK_STREAM && !(f->dbs&(1<<UNIX_ST_DB)))
1938 			continue;
1939 		if (s->type == SOCK_DGRAM && !(f->dbs&(1<<UNIX_DG_DB)))
1940 			continue;
1941 
1942 		peer = "*";
1943 		if (s->peer) {
1944 			struct unixstat *p;
1945 			for (p = list; p; p = p->next) {
1946 				if (s->peer == p->ino)
1947 					break;
1948 			}
1949 			if (!p) {
1950 				peer = "?";
1951 			} else {
1952 				peer = p->name ? : "*";
1953 			}
1954 		}
1955 
1956 		if (f->f) {
1957 			struct tcpstat tst;
1958 			tst.local.family = AF_UNIX;
1959 			tst.remote.family = AF_UNIX;
1960 			memcpy(tst.local.data, &s->name, sizeof(s->name));
1961 			if (strcmp(peer, "*") == 0)
1962 				memset(tst.remote.data, 0, sizeof(peer));
1963 			else
1964 				memcpy(tst.remote.data, &peer, sizeof(peer));
1965 			if (run_ssfilter(f->f, &tst) == 0)
1966 				continue;
1967 		}
1968 
1969 		if (netid_width)
1970 			printf("%-*s ", netid_width,
1971 			       s->type == SOCK_STREAM ? "u_str" : "u_dgr");
1972 		if (state_width)
1973 			printf("%-*s ", state_width, sstate_name[s->state]);
1974 		printf("%-6d %-6d ", s->rq, s->wq);
1975 		printf("%*s %-*d %*s %-*d",
1976 		       addr_width, s->name ? : "*", serv_width, s->ino,
1977 		       addr_width, peer, serv_width, s->peer);
1978 		if (show_users) {
1979 			char ubuf[4096];
1980 			if (find_users(s->ino, ubuf, sizeof(ubuf)) > 0)
1981 				printf(" users:(%s)", ubuf);
1982 		}
1983 		printf("\n");
1984 	}
1985 }
1986 
unix_show(struct filter * f)1987 int unix_show(struct filter *f)
1988 {
1989 	FILE *fp;
1990 	char buf[256];
1991 	char name[128];
1992 	int  newformat = 0;
1993 	int  cnt;
1994 	struct unixstat *list = NULL;
1995 
1996 	if ((fp = net_unix_open()) == NULL)
1997 		return -1;
1998 	fgets(buf, sizeof(buf)-1, fp);
1999 
2000 	if (memcmp(buf, "Peer", 4) == 0)
2001 		newformat = 1;
2002 	cnt = 0;
2003 
2004 	while (fgets(buf, sizeof(buf)-1, fp)) {
2005 		struct unixstat *u, **insp;
2006 		int flags;
2007 
2008 		if (!(u = malloc(sizeof(*u))))
2009 			break;
2010 		u->name = NULL;
2011 
2012 		if (sscanf(buf, "%x: %x %x %x %x %x %d %s",
2013 			   &u->peer, &u->rq, &u->wq, &flags, &u->type,
2014 			   &u->state, &u->ino, name) < 8)
2015 			name[0] = 0;
2016 
2017 		if (flags&(1<<16)) {
2018 			u->state = SS_LISTEN;
2019 		} else {
2020 			u->state = unix_state_map[u->state-1];
2021 			if (u->type == SOCK_DGRAM &&
2022 			    u->state == SS_CLOSE &&
2023 			    u->peer)
2024 				u->state = SS_ESTABLISHED;
2025 		}
2026 
2027 		if (!newformat) {
2028 			u->peer = 0;
2029 			u->rq = 0;
2030 			u->wq = 0;
2031 		}
2032 
2033 		insp = &list;
2034 		while (*insp) {
2035 			if (u->type < (*insp)->type ||
2036 			    (u->type == (*insp)->type &&
2037 			     u->ino < (*insp)->ino))
2038 				break;
2039 			insp = &(*insp)->next;
2040 		}
2041 		u->next = *insp;
2042 		*insp = u;
2043 
2044 		if (name[0]) {
2045 			if ((u->name = malloc(strlen(name)+1)) == NULL)
2046 				break;
2047 			strcpy(u->name, name);
2048 		}
2049 		if (++cnt > MAX_UNIX_REMEMBER) {
2050 			unix_list_print(list, f);
2051 			unix_list_free(list);
2052 			list = NULL;
2053 			cnt = 0;
2054 		}
2055 	}
2056 
2057 	if (list) {
2058 		unix_list_print(list, f);
2059 		unix_list_free(list);
2060 		list = NULL;
2061 		cnt = 0;
2062 	}
2063 
2064 	return 0;
2065 }
2066 
2067 
packet_show(struct filter * f)2068 int packet_show(struct filter *f)
2069 {
2070 	FILE *fp;
2071 	char buf[256];
2072 	int type;
2073 	int prot;
2074 	int iface;
2075 	int state;
2076 	int rq;
2077 	int uid;
2078 	int ino;
2079 	unsigned long long sk;
2080 
2081 	if (!(f->states & (1<<SS_CLOSE)))
2082 		return 0;
2083 
2084 	if ((fp = net_packet_open()) == NULL)
2085 		return -1;
2086 	fgets(buf, sizeof(buf)-1, fp);
2087 
2088 	while (fgets(buf, sizeof(buf)-1, fp)) {
2089 		sscanf(buf, "%llx %*d %d %x %d %d %u %u %u",
2090 		       &sk,
2091 		       &type, &prot, &iface, &state,
2092 		       &rq, &uid, &ino);
2093 
2094 		if (type == SOCK_RAW && !(f->dbs&(1<<PACKET_R_DB)))
2095 			continue;
2096 		if (type == SOCK_DGRAM && !(f->dbs&(1<<PACKET_DG_DB)))
2097 			continue;
2098 		if (f->f) {
2099 			struct tcpstat tst;
2100 			tst.local.family = AF_PACKET;
2101 			tst.remote.family = AF_PACKET;
2102 			tst.rport = 0;
2103 			tst.lport = iface;
2104 			tst.local.data[0] = prot;
2105 			tst.remote.data[0] = 0;
2106 			if (run_ssfilter(f->f, &tst) == 0)
2107 				continue;
2108 		}
2109 
2110 		if (netid_width)
2111 			printf("%-*s ", netid_width,
2112 			       type == SOCK_RAW ? "p_raw" : "p_dgr");
2113 		if (state_width)
2114 			printf("%-*s ", state_width, "UNCONN");
2115 		printf("%-6d %-6d ", rq, 0);
2116 		if (prot == 3) {
2117 			printf("%*s:", addr_width, "*");
2118 		} else {
2119 			char tb[16];
2120 			printf("%*s:", addr_width,
2121 			       ll_proto_n2a(htons(prot), tb, sizeof(tb)));
2122 		}
2123 		if (iface == 0) {
2124 			printf("%-*s ", serv_width, "*");
2125 		} else {
2126 			printf("%-*s ", serv_width, xll_index_to_name(iface));
2127 		}
2128 		printf("%*s*%-*s",
2129 		       addr_width, "", serv_width, "");
2130 
2131 		if (show_users) {
2132 			char ubuf[4096];
2133 			if (find_users(ino, ubuf, sizeof(ubuf)) > 0)
2134 				printf(" users:(%s)", ubuf);
2135 		}
2136 		if (show_details) {
2137 			printf(" ino=%u uid=%u sk=%llx", ino, uid, sk);
2138 		}
2139 		printf("\n");
2140 	}
2141 
2142 	return 0;
2143 }
2144 
netlink_show(struct filter * f)2145 int netlink_show(struct filter *f)
2146 {
2147 	FILE *fp;
2148 	char buf[256];
2149 	int prot, pid;
2150 	unsigned groups;
2151 	int rq, wq, rc;
2152 	unsigned long long sk, cb;
2153 
2154 	if (!(f->states & (1<<SS_CLOSE)))
2155 		return 0;
2156 
2157 	if ((fp = net_netlink_open()) == NULL)
2158 		return -1;
2159 	fgets(buf, sizeof(buf)-1, fp);
2160 
2161 	while (fgets(buf, sizeof(buf)-1, fp)) {
2162 		sscanf(buf, "%llx %d %d %x %d %d %llx %d",
2163 		       &sk,
2164 		       &prot, &pid, &groups, &rq, &wq, &cb, &rc);
2165 
2166 		if (f->f) {
2167 			struct tcpstat tst;
2168 			tst.local.family = AF_NETLINK;
2169 			tst.remote.family = AF_NETLINK;
2170 			tst.rport = -1;
2171 			tst.lport = pid;
2172 			tst.local.data[0] = prot;
2173 			tst.remote.data[0] = 0;
2174 			if (run_ssfilter(f->f, &tst) == 0)
2175 				continue;
2176 		}
2177 
2178 		if (netid_width)
2179 			printf("%-*s ", netid_width, "nl");
2180 		if (state_width)
2181 			printf("%-*s ", state_width, "UNCONN");
2182 		printf("%-6d %-6d ", rq, wq);
2183 		if (resolve_services && prot == 0)
2184 			printf("%*s:", addr_width, "rtnl");
2185 		else if (resolve_services && prot == 3)
2186 			printf("%*s:", addr_width, "fw");
2187 		else if (resolve_services && prot == 4)
2188 			printf("%*s:", addr_width, "tcpdiag");
2189 		else
2190 			printf("%*d:", addr_width, prot);
2191 		if (pid == -1) {
2192 			printf("%-*s ", serv_width, "*");
2193 		} else if (resolve_services) {
2194 			int done = 0;
2195 			if (!pid) {
2196 				done = 1;
2197 				printf("%-*s ", serv_width, "kernel");
2198 			} else if (pid > 0) {
2199 				char procname[64];
2200 				FILE *fp;
2201 				sprintf(procname, "%s/%d/stat",
2202 					getenv("PROC_ROOT") ? : "/proc", pid);
2203 				if ((fp = fopen(procname, "r")) != NULL) {
2204 					if (fscanf(fp, "%*d (%[^)])", procname) == 1) {
2205 						sprintf(procname+strlen(procname), "/%d", pid);
2206 						printf("%-*s ", serv_width, procname);
2207 						done = 1;
2208 					}
2209 					fclose(fp);
2210 				}
2211 			}
2212 			if (!done)
2213 				printf("%-*d ", serv_width, pid);
2214 		} else {
2215 			printf("%-*d ", serv_width, pid);
2216 		}
2217 		printf("%*s*%-*s",
2218 		       addr_width, "", serv_width, "");
2219 
2220 		if (show_details) {
2221 			printf(" sk=%llx cb=%llx groups=0x%08x", sk, cb, groups);
2222 		}
2223 		printf("\n");
2224 	}
2225 
2226 	return 0;
2227 }
2228 
2229 struct snmpstat
2230 {
2231 	int tcp_estab;
2232 };
2233 
get_snmp_int(char * proto,char * key,int * result)2234 int get_snmp_int(char *proto, char *key, int *result)
2235 {
2236 	char buf[1024];
2237 	FILE *fp;
2238 	int protolen = strlen(proto);
2239 	int keylen = strlen(key);
2240 
2241 	*result = 0;
2242 
2243 	if ((fp = net_snmp_open()) == NULL)
2244 		return -1;
2245 
2246 	while (fgets(buf, sizeof(buf), fp) != NULL) {
2247 		char *p = buf;
2248 		int  pos = 0;
2249 		if (memcmp(buf, proto, protolen))
2250 			continue;
2251 		while ((p = strchr(p, ' ')) != NULL) {
2252 			pos++;
2253 			p++;
2254 			if (memcmp(p, key, keylen) == 0 &&
2255 			    (p[keylen] == ' ' || p[keylen] == '\n'))
2256 				break;
2257 		}
2258 		if (fgets(buf, sizeof(buf), fp) == NULL)
2259 			break;
2260 		if (memcmp(buf, proto, protolen))
2261 			break;
2262 		p = buf;
2263 		while ((p = strchr(p, ' ')) != NULL) {
2264 			p++;
2265 			if (--pos == 0) {
2266 				sscanf(p, "%d", result);
2267 				fclose(fp);
2268 				return 0;
2269 			}
2270 		}
2271 	}
2272 
2273 	fclose(fp);
2274 	errno = ESRCH;
2275 	return -1;
2276 }
2277 
2278 
2279 /* Get stats from sockstat */
2280 
2281 struct sockstat
2282 {
2283 	int socks;
2284 	int tcp_mem;
2285 	int tcp_total;
2286 	int tcp_orphans;
2287 	int tcp_tws;
2288 	int tcp4_hashed;
2289 	int udp4;
2290 	int raw4;
2291 	int frag4;
2292 	int frag4_mem;
2293 	int tcp6_hashed;
2294 	int udp6;
2295 	int raw6;
2296 	int frag6;
2297 	int frag6_mem;
2298 };
2299 
get_sockstat_line(char * line,struct sockstat * s)2300 static void get_sockstat_line(char *line, struct sockstat *s)
2301 {
2302 	char id[256], rem[256];
2303 
2304 	if (sscanf(line, "%[^ ] %[^\n]\n", id, rem) != 2)
2305 		return;
2306 
2307 	if (strcmp(id, "sockets:") == 0)
2308 		sscanf(rem, "%*s%d", &s->socks);
2309 	else if (strcmp(id, "UDP:") == 0)
2310 		sscanf(rem, "%*s%d", &s->udp4);
2311 	else if (strcmp(id, "UDP6:") == 0)
2312 		sscanf(rem, "%*s%d", &s->udp6);
2313 	else if (strcmp(id, "RAW:") == 0)
2314 		sscanf(rem, "%*s%d", &s->raw4);
2315 	else if (strcmp(id, "RAW6:") == 0)
2316 		sscanf(rem, "%*s%d", &s->raw6);
2317 	else if (strcmp(id, "TCP6:") == 0)
2318 		sscanf(rem, "%*s%d", &s->tcp6_hashed);
2319 	else if (strcmp(id, "FRAG:") == 0)
2320 		sscanf(rem, "%*s%d%*s%d", &s->frag4, &s->frag4_mem);
2321 	else if (strcmp(id, "FRAG6:") == 0)
2322 		sscanf(rem, "%*s%d%*s%d", &s->frag6, &s->frag6_mem);
2323 	else if (strcmp(id, "TCP:") == 0)
2324 		sscanf(rem, "%*s%d%*s%d%*s%d%*s%d%*s%d",
2325 		       &s->tcp4_hashed,
2326 		       &s->tcp_orphans, &s->tcp_tws, &s->tcp_total, &s->tcp_mem);
2327 }
2328 
get_sockstat(struct sockstat * s)2329 int get_sockstat(struct sockstat *s)
2330 {
2331 	char buf[256];
2332 	FILE *fp;
2333 
2334 	memset(s, 0, sizeof(*s));
2335 
2336 	if ((fp = net_sockstat_open()) == NULL)
2337 		return -1;
2338 	while(fgets(buf, sizeof(buf), fp) != NULL)
2339 		get_sockstat_line(buf, s);
2340 	fclose(fp);
2341 
2342 	if ((fp = net_sockstat6_open()) == NULL)
2343 		return 0;
2344 	while(fgets(buf, sizeof(buf), fp) != NULL)
2345 		get_sockstat_line(buf, s);
2346 	fclose(fp);
2347 
2348 	return 0;
2349 }
2350 
print_summary(void)2351 int print_summary(void)
2352 {
2353 	struct sockstat s;
2354 	struct snmpstat sn;
2355 
2356 	if (get_sockstat(&s) < 0)
2357 		perror("ss: get_sockstat");
2358 	if (get_snmp_int("Tcp:", "CurrEstab", &sn.tcp_estab) < 0)
2359 		perror("ss: get_snmpstat");
2360 
2361 	printf("Total: %d (kernel %d)\n", s.socks, slabstat.socks);
2362 
2363 	printf("TCP:   %d (estab %d, closed %d, orphaned %d, synrecv %d, timewait %d/%d), ports %d\n",
2364 	       s.tcp_total + slabstat.tcp_syns + s.tcp_tws,
2365 	       sn.tcp_estab,
2366 	       s.tcp_total - (s.tcp4_hashed+s.tcp6_hashed-s.tcp_tws),
2367 	       s.tcp_orphans,
2368 	       slabstat.tcp_syns,
2369 	       s.tcp_tws, slabstat.tcp_tws,
2370 	       slabstat.tcp_ports
2371 	       );
2372 
2373 	printf("\n");
2374 	printf("Transport Total     IP        IPv6\n");
2375 	printf("*	  %-9d %-9s %-9s\n", slabstat.socks, "-", "-");
2376 	printf("RAW	  %-9d %-9d %-9d\n", s.raw4+s.raw6, s.raw4, s.raw6);
2377 	printf("UDP	  %-9d %-9d %-9d\n", s.udp4+s.udp6, s.udp4, s.udp6);
2378 	printf("TCP	  %-9d %-9d %-9d\n", s.tcp4_hashed+s.tcp6_hashed, s.tcp4_hashed, s.tcp6_hashed);
2379 	printf("INET	  %-9d %-9d %-9d\n",
2380 	       s.raw4+s.udp4+s.tcp4_hashed+
2381 	       s.raw6+s.udp6+s.tcp6_hashed,
2382 	       s.raw4+s.udp4+s.tcp4_hashed,
2383 	       s.raw6+s.udp6+s.tcp6_hashed);
2384 	printf("FRAG	  %-9d %-9d %-9d\n", s.frag4+s.frag6, s.frag4, s.frag6);
2385 
2386 	printf("\n");
2387 
2388 	return 0;
2389 }
2390 
_usage(FILE * dest)2391 static void _usage(FILE *dest)
2392 {
2393 	fprintf(dest,
2394 "Usage: ss [ OPTIONS ]\n"
2395 "       ss [ OPTIONS ] [ FILTER ]\n"
2396 "   -h, --help		this message\n"
2397 "   -V, --version	output version information\n"
2398 "   -n, --numeric	don't resolve service names\n"
2399 "   -r, --resolve       resolve host names\n"
2400 "   -a, --all		display all sockets\n"
2401 "   -l, --listening	display listening sockets\n"
2402 "   -o, --options       show timer information\n"
2403 "   -e, --extended      show detailed socket information\n"
2404 "   -m, --memory        show socket memory usage\n"
2405 "   -p, --processes	show process using socket\n"
2406 "   -i, --info		show internal TCP information\n"
2407 "   -s, --summary	show socket usage summary\n"
2408 "\n"
2409 "   -4, --ipv4          display only IP version 4 sockets\n"
2410 "   -6, --ipv6          display only IP version 6 sockets\n"
2411 "   -0, --packet	display PACKET sockets\n"
2412 "   -t, --tcp		display only TCP sockets\n"
2413 "   -u, --udp		display only UDP sockets\n"
2414 "   -d, --dccp		display only DCCP sockets\n"
2415 "   -w, --raw		display only RAW sockets\n"
2416 "   -x, --unix		display only Unix domain sockets\n"
2417 "   -f, --family=FAMILY display sockets of type FAMILY\n"
2418 "\n"
2419 "   -A, --query=QUERY\n"
2420 "       QUERY := {all|inet|tcp|udp|raw|unix|packet|netlink}[,QUERY]\n"
2421 "\n"
2422 "   -F, --filter=FILE   read filter information from FILE\n"
2423 "       FILTER := [ state TCP-STATE ] [ EXPRESSION ]\n"
2424 		);
2425 }
2426 
2427 static void help(void) __attribute__((noreturn));
help(void)2428 static void help(void)
2429 {
2430 	_usage(stdout);
2431 	exit(0);
2432 }
2433 
2434 static void usage(void) __attribute__((noreturn));
usage(void)2435 static void usage(void)
2436 {
2437 	_usage(stderr);
2438 	exit(-1);
2439 }
2440 
2441 
scan_state(const char * state)2442 int scan_state(const char *state)
2443 {
2444 	int i;
2445 	if (strcasecmp(state, "close") == 0 ||
2446 	    strcasecmp(state, "closed") == 0)
2447 		return (1<<SS_CLOSE);
2448 	if (strcasecmp(state, "syn-rcv") == 0)
2449 		return (1<<SS_SYN_RECV);
2450 	if (strcasecmp(state, "established") == 0)
2451 		return (1<<SS_ESTABLISHED);
2452 	if (strcasecmp(state, "all") == 0)
2453 		return SS_ALL;
2454 	if (strcasecmp(state, "connected") == 0)
2455 		return SS_ALL & ~((1<<SS_CLOSE)|(1<<SS_LISTEN));
2456 	if (strcasecmp(state, "synchronized") == 0)
2457 		return SS_ALL & ~((1<<SS_CLOSE)|(1<<SS_LISTEN)|(1<<SS_SYN_SENT));
2458 	if (strcasecmp(state, "bucket") == 0)
2459 		return (1<<SS_SYN_RECV)|(1<<SS_TIME_WAIT);
2460 	if (strcasecmp(state, "big") == 0)
2461 		return SS_ALL & ~((1<<SS_SYN_RECV)|(1<<SS_TIME_WAIT));
2462 	for (i=0; i<SS_MAX; i++) {
2463 		if (strcasecmp(state, sstate_namel[i]) == 0)
2464 			return (1<<i);
2465 	}
2466 	return 0;
2467 }
2468 
2469 static const struct option long_opts[] = {
2470 	{ "numeric", 0, 0, 'n' },
2471 	{ "resolve", 0, 0, 'r' },
2472 	{ "options", 0, 0, 'o' },
2473 	{ "extended", 0, 0, 'e' },
2474 	{ "memory", 0, 0, 'm' },
2475 	{ "info", 0, 0, 'i' },
2476 	{ "processes", 0, 0, 'p' },
2477 	{ "dccp", 0, 0, 'd' },
2478 	{ "tcp", 0, 0, 't' },
2479 	{ "udp", 0, 0, 'u' },
2480 	{ "raw", 0, 0, 'w' },
2481 	{ "unix", 0, 0, 'x' },
2482 	{ "all", 0, 0, 'a' },
2483 	{ "listening", 0, 0, 'l' },
2484 	{ "ipv4", 0, 0, '4' },
2485 	{ "ipv6", 0, 0, '6' },
2486 	{ "packet", 0, 0, '0' },
2487 	{ "family", 1, 0, 'f' },
2488 	{ "socket", 1, 0, 'A' },
2489 	{ "summary", 0, 0, 's' },
2490 	{ "diag", 0, 0, 'D' },
2491 	{ "filter", 1, 0, 'F' },
2492 	{ "version", 0, 0, 'V' },
2493 	{ "help", 0, 0, 'h' },
2494 	{ 0 }
2495 
2496 };
2497 
main(int argc,char * argv[])2498 int main(int argc, char *argv[])
2499 {
2500 	int do_default = 1;
2501 	int saw_states = 0;
2502 	int saw_query = 0;
2503 	int do_summary = 0;
2504 	const char *dump_tcpdiag = NULL;
2505 	FILE *filter_fp = NULL;
2506 	int ch;
2507 
2508 	memset(&current_filter, 0, sizeof(current_filter));
2509 
2510 	current_filter.states = default_filter.states;
2511 
2512 	while ((ch = getopt_long(argc, argv, "dhaletuwxnro460spf:miA:D:F:vV",
2513 				 long_opts, NULL)) != EOF) {
2514 		switch(ch) {
2515 		case 'n':
2516 			resolve_services = 0;
2517 			break;
2518 		case 'r':
2519 			resolve_hosts = 1;
2520 			break;
2521 		case 'o':
2522 			show_options = 1;
2523 			break;
2524 		case 'e':
2525 			show_options = 1;
2526 			show_details++;
2527 			break;
2528 		case 'm':
2529 			show_mem = 1;
2530 			break;
2531 		case 'i':
2532 			show_tcpinfo = 1;
2533 			break;
2534 		case 'p':
2535 			show_users++;
2536 			user_ent_hash_build();
2537 			break;
2538 		case 'd':
2539 			current_filter.dbs |= (1<<DCCP_DB);
2540 			do_default = 0;
2541 			break;
2542 		case 't':
2543 			current_filter.dbs |= (1<<TCP_DB);
2544 			do_default = 0;
2545 			break;
2546 		case 'u':
2547 			current_filter.dbs |= (1<<UDP_DB);
2548 			do_default = 0;
2549 			break;
2550 		case 'w':
2551 			current_filter.dbs |= (1<<RAW_DB);
2552 			do_default = 0;
2553 			break;
2554 		case 'x':
2555 			current_filter.dbs |= UNIX_DBM;
2556 			do_default = 0;
2557 			break;
2558 		case 'a':
2559 			current_filter.states = SS_ALL;
2560 			break;
2561 		case 'l':
2562 			current_filter.states = (1<<SS_LISTEN);
2563 			break;
2564 		case '4':
2565 			preferred_family = AF_INET;
2566 			break;
2567 		case '6':
2568 			preferred_family = AF_INET6;
2569 			break;
2570 		case '0':
2571 			preferred_family = AF_PACKET;
2572 			break;
2573 		case 'f':
2574 			if (strcmp(optarg, "inet") == 0)
2575 				preferred_family = AF_INET;
2576 			else if (strcmp(optarg, "inet6") == 0)
2577 				preferred_family = AF_INET6;
2578 			else if (strcmp(optarg, "link") == 0)
2579 				preferred_family = AF_PACKET;
2580 			else if (strcmp(optarg, "unix") == 0)
2581 				preferred_family = AF_UNIX;
2582 			else if (strcmp(optarg, "netlink") == 0)
2583 				preferred_family = AF_NETLINK;
2584 			else if (strcmp(optarg, "help") == 0)
2585 				help();
2586 			else {
2587 				fprintf(stderr, "ss: \"%s\" is invalid family\n", optarg);
2588 				usage();
2589 			}
2590 			break;
2591 		case 'A':
2592 		{
2593 			char *p, *p1;
2594 			if (!saw_query) {
2595 				current_filter.dbs = 0;
2596 				saw_query = 1;
2597 				do_default = 0;
2598 			}
2599 			p = p1 = optarg;
2600 			do {
2601 				if ((p1 = strchr(p, ',')) != NULL)
2602 					*p1 = 0;
2603 				if (strcmp(p, "all") == 0) {
2604 					current_filter.dbs = ALL_DB;
2605 				} else if (strcmp(p, "inet") == 0) {
2606 					current_filter.dbs |= (1<<TCP_DB)|(1<<DCCP_DB)|(1<<UDP_DB)|(1<<RAW_DB);
2607 				} else if (strcmp(p, "udp") == 0) {
2608 					current_filter.dbs |= (1<<UDP_DB);
2609 				} else if (strcmp(p, "dccp") == 0) {
2610 					current_filter.dbs |= (1<<DCCP_DB);
2611 				} else if (strcmp(p, "tcp") == 0) {
2612 					current_filter.dbs |= (1<<TCP_DB);
2613 				} else if (strcmp(p, "raw") == 0) {
2614 					current_filter.dbs |= (1<<RAW_DB);
2615 				} else if (strcmp(p, "unix") == 0) {
2616 					current_filter.dbs |= UNIX_DBM;
2617 				} else if (strcasecmp(p, "unix_stream") == 0 ||
2618 					   strcmp(p, "u_str") == 0) {
2619 					current_filter.dbs |= (1<<UNIX_ST_DB);
2620 				} else if (strcasecmp(p, "unix_dgram") == 0 ||
2621 					   strcmp(p, "u_dgr") == 0) {
2622 					current_filter.dbs |= (1<<UNIX_DG_DB);
2623 				} else if (strcmp(p, "packet") == 0) {
2624 					current_filter.dbs |= PACKET_DBM;
2625 				} else if (strcmp(p, "packet_raw") == 0 ||
2626 					   strcmp(p, "p_raw") == 0) {
2627 					current_filter.dbs |= (1<<PACKET_R_DB);
2628 				} else if (strcmp(p, "packet_dgram") == 0 ||
2629 					   strcmp(p, "p_dgr") == 0) {
2630 					current_filter.dbs |= (1<<PACKET_DG_DB);
2631 				} else if (strcmp(p, "netlink") == 0) {
2632 					current_filter.dbs |= (1<<NETLINK_DB);
2633 				} else {
2634 					fprintf(stderr, "ss: \"%s\" is illegal socket table id\n", p);
2635 					usage();
2636 				}
2637 				p = p1 + 1;
2638 			} while (p1);
2639 			break;
2640 		}
2641 		case 's':
2642 			do_summary = 1;
2643 			break;
2644 		case 'D':
2645 			dump_tcpdiag = optarg;
2646 			break;
2647 		case 'F':
2648 			if (filter_fp) {
2649 				fprintf(stderr, "More than one filter file\n");
2650 				exit(-1);
2651 			}
2652 			if (optarg[0] == '-')
2653 				filter_fp = stdin;
2654 			else
2655 				filter_fp = fopen(optarg, "r");
2656 			if (!filter_fp) {
2657 				perror("fopen filter file");
2658 				exit(-1);
2659 			}
2660 			break;
2661 		case 'v':
2662 		case 'V':
2663 			printf("ss utility, iproute2-ss%s\n", SNAPSHOT);
2664 			exit(0);
2665 		case 'h':
2666 		case '?':
2667 			help();
2668 		default:
2669 			usage();
2670 		}
2671 	}
2672 
2673 	argc -= optind;
2674 	argv += optind;
2675 
2676 	get_slabstat(&slabstat);
2677 
2678 	if (do_summary) {
2679 		print_summary();
2680 		if (do_default && argc == 0)
2681 			exit(0);
2682 	}
2683 
2684 	if (do_default)
2685 		current_filter.dbs = default_filter.dbs;
2686 
2687 	if (preferred_family == AF_UNSPEC) {
2688 		if (!(current_filter.dbs&~UNIX_DBM))
2689 			preferred_family = AF_UNIX;
2690 		else if (!(current_filter.dbs&~PACKET_DBM))
2691 			preferred_family = AF_PACKET;
2692 		else if (!(current_filter.dbs&~(1<<NETLINK_DB)))
2693 			preferred_family = AF_NETLINK;
2694 	}
2695 
2696 	if (preferred_family != AF_UNSPEC) {
2697 		int mask2;
2698 		if (preferred_family == AF_INET ||
2699 		    preferred_family == AF_INET6) {
2700 			mask2= current_filter.dbs;
2701 		} else if (preferred_family == AF_PACKET) {
2702 			mask2 = PACKET_DBM;
2703 		} else if (preferred_family == AF_UNIX) {
2704 			mask2 = UNIX_DBM;
2705 		} else if (preferred_family == AF_NETLINK) {
2706 			mask2 = (1<<NETLINK_DB);
2707 		} else {
2708 			mask2 = 0;
2709 		}
2710 
2711 		if (do_default)
2712 			current_filter.dbs = mask2;
2713 		else
2714 			current_filter.dbs &= mask2;
2715 		current_filter.families = (1<<preferred_family);
2716 	} else {
2717 		if (!do_default)
2718 			current_filter.families = ~0;
2719 		else
2720 			current_filter.families = default_filter.families;
2721 	}
2722 	if (current_filter.dbs == 0) {
2723 		fprintf(stderr, "ss: no socket tables to show with such filter.\n");
2724 		exit(0);
2725 	}
2726 	if (current_filter.families == 0) {
2727 		fprintf(stderr, "ss: no families to show with such filter.\n");
2728 		exit(0);
2729 	}
2730 
2731 	if (resolve_services && resolve_hosts &&
2732 	    (current_filter.dbs&(UNIX_DBM|(1<<TCP_DB)|(1<<UDP_DB)|(1<<DCCP_DB))))
2733 		init_service_resolver();
2734 
2735 	/* Now parse filter... */
2736 	if (argc == 0 && filter_fp) {
2737 		if (ssfilter_parse(&current_filter.f, 0, NULL, filter_fp))
2738 			usage();
2739 	}
2740 
2741 	while (argc > 0) {
2742 		if (strcmp(*argv, "state") == 0) {
2743 			NEXT_ARG();
2744 			if (!saw_states)
2745 				current_filter.states = 0;
2746 			current_filter.states |= scan_state(*argv);
2747 			saw_states = 1;
2748 		} else if (strcmp(*argv, "exclude") == 0 ||
2749 			   strcmp(*argv, "excl") == 0) {
2750 			NEXT_ARG();
2751 			if (!saw_states)
2752 				current_filter.states = SS_ALL;
2753 			current_filter.states &= ~scan_state(*argv);
2754 			saw_states = 1;
2755 		} else {
2756 			if (ssfilter_parse(&current_filter.f, argc, argv, filter_fp))
2757 				usage();
2758 			break;
2759 		}
2760 		argc--; argv++;
2761 	}
2762 
2763 	if (current_filter.states == 0) {
2764 		fprintf(stderr, "ss: no socket states to show with such filter.\n");
2765 		exit(0);
2766 	}
2767 
2768 	if (dump_tcpdiag) {
2769 		FILE *dump_fp = stdout;
2770 		if (!(current_filter.dbs & (1<<TCP_DB))) {
2771 			fprintf(stderr, "ss: tcpdiag dump requested and no tcp in filter.\n");
2772 			exit(0);
2773 		}
2774 		if (dump_tcpdiag[0] != '-') {
2775 			dump_fp = fopen(dump_tcpdiag, "w");
2776 			if (!dump_tcpdiag) {
2777 				perror("fopen dump file");
2778 				exit(-1);
2779 			}
2780 		}
2781 		tcp_show_netlink(&current_filter, dump_fp, TCPDIAG_GETSOCK);
2782 		fflush(dump_fp);
2783 		exit(0);
2784 	}
2785 
2786 	netid_width = 0;
2787 	if (current_filter.dbs&(current_filter.dbs-1))
2788 		netid_width = 5;
2789 
2790 	state_width = 0;
2791 	if (current_filter.states&(current_filter.states-1))
2792 		state_width = 10;
2793 
2794 	screen_width = 80;
2795 	if (isatty(STDOUT_FILENO)) {
2796 		struct winsize w;
2797 
2798 		if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) != -1) {
2799 			if (w.ws_col > 0)
2800 				screen_width = w.ws_col;
2801 		}
2802 	}
2803 
2804 	addrp_width = screen_width;
2805 	addrp_width -= netid_width+1;
2806 	addrp_width -= state_width+1;
2807 	addrp_width -= 14;
2808 
2809 	if (addrp_width&1) {
2810 		if (netid_width)
2811 			netid_width++;
2812 		else if (state_width)
2813 			state_width++;
2814 	}
2815 
2816 	addrp_width /= 2;
2817 	addrp_width--;
2818 
2819 	serv_width = resolve_services ? 7 : 5;
2820 
2821 	if (addrp_width < 15+serv_width+1)
2822 		addrp_width = 15+serv_width+1;
2823 
2824 	addr_width = addrp_width - serv_width - 1;
2825 
2826 	if (netid_width)
2827 		printf("%-*s ", netid_width, "Netid");
2828 	if (state_width)
2829 		printf("%-*s ", state_width, "State");
2830 	printf("%-6s %-6s ", "Recv-Q", "Send-Q");
2831 
2832 	printf("%*s:%-*s %*s:%-*s\n",
2833 	       addr_width, "Local Address", serv_width, "Port",
2834 	       addr_width, "Peer Address", serv_width, "Port");
2835 
2836 	fflush(stdout);
2837 
2838 	if (current_filter.dbs & (1<<NETLINK_DB))
2839 		netlink_show(&current_filter);
2840 	if (current_filter.dbs & PACKET_DBM)
2841 		packet_show(&current_filter);
2842 	if (current_filter.dbs & UNIX_DBM)
2843 		unix_show(&current_filter);
2844 	if (current_filter.dbs & (1<<RAW_DB))
2845 		raw_show(&current_filter);
2846 	if (current_filter.dbs & (1<<UDP_DB))
2847 		udp_show(&current_filter);
2848 	if (current_filter.dbs & (1<<TCP_DB))
2849 		tcp_show(&current_filter, TCPDIAG_GETSOCK);
2850 	if (current_filter.dbs & (1<<DCCP_DB))
2851 		tcp_show(&current_filter, DCCPDIAG_GETSOCK);
2852 	return 0;
2853 }
2854