sockstat tcp/udp switches

Josh Carroll josh.carroll at psualum.com
Tue Nov 7 18:51:37 UTC 2006


Below is the patch using strsep instead. I also updated the
gather_inet function to print a message that a protocol is not
supported if it exists in /etc/protocols, but does not have a case in
the gather_inet function.

patch is here if you'd rather just fetch it:

http://pflog.net/~floyd/sockstat.patch

Thanks,
Josh


--- sockstat.c.orig	Thu Jun  9 23:36:03 2005
+++ sockstat.c	Tue Nov  7 10:49:28 2006
@@ -66,8 +66,15 @@
 static int	 opt_u;		/* Show Unix domain sockets */
 static int	 opt_v;		/* Verbose mode */

+/* default protocols to use if no -P was defined, currently
+	tcp, udp and divert */
+const char *default_protos[] = {"tcp", "udp", "divert", NULL};
+
+static int *protos;		/* protocols to use */
+
 static int	*ports;

+
 #define INT_BIT (sizeof(int)*CHAR_BIT)
 #define SET_PORT(p) do { ports[p / INT_BIT] |= 1 << (p % INT_BIT); } while (0)
 #define CHK_PORT(p) (ports[p / INT_BIT] & (1 << (p % INT_BIT)))
@@ -104,6 +111,68 @@
 	return (len);
 }

+
+/* this function needs to be updated to reflect additional protocols
+	that are to be supported */
+static int
+get_proto_type(const char *proto)
+{
+	struct protoent *pent;
+
+	if(strlen(proto) == 0)
+		return 0;
+
+	pent = getprotobyname(proto);
+	if(pent == NULL) {
+		printf("Unrecognized protocol: %s\n", proto);
+		return -1;
+	} else {
+		return pent->p_proto;
+	}
+}
+
+
+static void init_protos(int num)
+{
+	int proto_count = 0;
+
+	if(num > 0) {
+		proto_count = num;
+	} else {
+		/* find the maximum number of possible protocols */
+		while(getprotoent() != NULL)
+			proto_count++;
+		endprotoent();
+	}
+
+	if ((protos = malloc(sizeof(int) * proto_count)) == NULL)
+		err(1, "malloc()");
+}
+
+
+static int
+parse_protos(char *protospec)
+{
+	char **prot;
+	char *tmp = protospec;
+	int protos_defined = 0, proto_type, proto_index = 0;
+
+	init_protos(0);
+
+	while( (*prot = strsep(&tmp, ",")) != NULL) {
+		/* handle ,, */
+		if(strlen(*prot) > 0) {
+			proto_type = get_proto_type(*prot);
+			if(proto_type != -1) {
+				protos[proto_index++] = proto_type;
+				protos_defined++;
+			}
+		}
+	}
+	return protos_defined;
+}
+
+
 static void
 parse_ports(const char *portspec)
 {
@@ -188,6 +257,7 @@
 	size_t len, bufsize;
 	void *buf;
 	int hash, retry, vflag;
+	struct protoent *pent;

 	vflag = 0;
 	if (opt_4)
@@ -209,7 +279,9 @@
 		protoname = "div";
 		break;
 	default:
-		abort();
+		pent = getprotobynumber(proto);
+		printf("protocol `%s' not supported.\n", pent->p_name);
+		exit(EXIT_FAILURE);
 	}

 	buf = NULL;
@@ -264,7 +336,9 @@
 			so = &xip->xi_socket;
 			break;
 		default:
-			abort();
+			pent = getprotobynumber(proto);
+			printf("protocol `%s' not supported.\n", pent->p_name);
+			exit(EXIT_FAILURE);
 		}
 		if ((inp->inp_vflag & vflag) == 0)
 			continue;
@@ -573,19 +647,49 @@
 	}
 }

+static int set_default_protos(void)
+{
+	struct protoent *prot;
+	const char **curr_proto;
+	int proto_index = 0;
+	int proto_count = 0;
+
+	/* determine the number of default protocols */
+	for(curr_proto = default_protos; *curr_proto; curr_proto++, proto_count++)
+		;
+
+	init_protos(proto_count);
+
+	for(curr_proto = default_protos; *curr_proto; curr_proto++) {
+		prot = getprotobyname(*curr_proto);
+		if(prot == NULL) {
+			printf("Cannot determine default protocols\n");
+			exit(EXIT_FAILURE);
+		}
+		protos[proto_index++] = prot->p_proto;
+	}
+
+	return proto_index;
+}
+
+
 static void
 usage(void)
 {
-	fprintf(stderr, "Usage: sockstat [-46clu] [-p ports]\n");
+	fprintf(stderr, "Usage: sockstat [-46clu] [-p ports] [-P protos]\n");
 	exit(1);
 }

 int
 main(int argc, char *argv[])
 {
-	int o;
+	/* if protos_defined remains -1, no -P was provided, sowe avoid
+		attempting to read from that int array later */
+	int protos_defined = -1;
+
+	int o, i;

-	while ((o = getopt(argc, argv, "46clp:uv")) != -1)
+	while ((o = getopt(argc, argv, "46clp:P:uv")) != -1)
 		switch (o) {
 		case '4':
 			opt_4 = 1;
@@ -602,6 +706,9 @@
 		case 'p':
 			parse_ports(optarg);
 			break;
+		case 'P':
+			protos_defined = parse_protos(optarg);
+			break;
 		case 'u':
 			opt_u = 1;
 			break;
@@ -618,17 +725,25 @@
 	if (argc > 0)
 		usage();

-	if (!opt_4 && !opt_6 && !opt_u)
-		opt_4 = opt_6 = opt_u = 1;
+
+	if (!opt_4 && !opt_6 && !opt_u && protos_defined == -1) {
+		opt_u = 1;
+		/* show tcp, udp and divert by default if no -P was specified */
+		/* restore protos_defined to the number of default protocols */
+		protos_defined = set_default_protos();
+	}
+
+	if (!opt_4 && !opt_6)
+		opt_4 = opt_6 = 1;
 	if (!opt_c && !opt_l)
 		opt_c = opt_l = 1;

 	if (opt_4 || opt_6) {
-		gather_inet(IPPROTO_TCP);
-		gather_inet(IPPROTO_UDP);
-		gather_inet(IPPROTO_DIVERT);
+		for(i=0; i < protos_defined; i++)
+			gather_inet(protos[i]);
 	}
-	if (opt_u) {
+
+	if ( opt_u || (protos_defined == -1 && !opt_4 && !opt_6)) {
 		gather_unix(SOCK_STREAM);
 		gather_unix(SOCK_DGRAM);
 	}


More information about the freebsd-hackers mailing list