[PATCH] Allow tcpdrop to use non-space separators

John Baldwin jhb at freebsd.org
Tue Jan 29 17:05:43 UTC 2013


A common use case I have at work is to find a busted connection using netstat 
-n or sockstat and then want to tcpdrop it.  However, tcpdrop requires spaces 
between the address and port so I can't simply cut and paste from one terminal 
window into another to generate the tcpdrop command.  This patch adds support 
for having a decimal (netstat output) or colon (sockstat output) between the 
address and port instead of a space.  It is careful to look for the last of 
these tokens to avoid parsing part of the address as the port.

Index: tcpdrop.8
===================================================================
--- tcpdrop.8	(revision 246073)
+++ tcpdrop.8	(working copy)
@@ -62,6 +62,9 @@
 .Pp
 Addresses and ports may be specified by name or numeric value.
 Both IPv4 and IPv6 address formats are supported.
+.Pp
+The addresses and ports may be separated by periods or colons
+instead of spaces.
 .Sh EXIT STATUS
 .Ex -std
 .Sh EXAMPLES
Index: tcpdrop.c
===================================================================
--- tcpdrop.c	(revision 246073)
+++ tcpdrop.c	(working copy)
@@ -50,6 +50,7 @@
 
 static bool tcpdrop_list_commands = false;
 
+static char *findport(const char *);
 static struct xinpgen *getxpcblist(const char *);
 static void sockinfo(const struct sockaddr *, struct host_service *);
 static bool tcpdrop(const struct sockaddr *, const struct sockaddr *);
@@ -65,6 +66,7 @@
 int
 main(int argc, char *argv[])
 {
+	char *lport, *fport;
 	bool dropall;
 	int ch;
 
@@ -93,15 +95,43 @@
 		exit(0);
 	}
 
-	if (argc != 4 || tcpdrop_list_commands)
+	if ((argc != 2 && argc != 4) || tcpdrop_list_commands)
 		usage();
 
-	if (!tcpdropbyname(argv[0], argv[1], argv[2], argv[3]))
+	if (argc == 2) {
+		lport = findport(argv[0]);
+		fport = findport(argv[1]);
+		if (lport == NULL || lport[1] == '\0' || rport == NULL ||
+		    rport[1] == '\0')
+			usage();
+		*lport++ = '\0';
+		*fport++ = '\0';
+		if (!tcpdropbyname(argv[0], lport, argv[1], fport))
+			exit(1);
+	} else if (!tcpdropbyname(argv[0], argv[1], argv[2], argv[3]))
 		exit(1);
 
 	exit(0);
 }
 
+static char *
+findport(const char *arg)
+{
+	char *dot, *colon;
+
+	/* A strrspn() or strrpbrk() would be nice. */
+	dot = strrchr(arg, '.');
+	colon = strrchr(arg, ':');
+	if (dot == NULL)
+		return (colon);
+	if (colon == NULL)
+		return (dot);
+	if (dot < colon)
+		return (colon);
+	else
+		return (dot);
+}
+
 static struct xinpgen *
 getxpcblist(const char *name)
 {
@@ -237,7 +267,7 @@
 	error = getaddrinfo(fhost, fport, &hints, &foreign);
 	if (error != 0) {
 		freeaddrinfo(local); /* XXX gratuitous */
-		errx(1, "getaddrinfo: %s port %s: %s", lhost, lport,
+		errx(1, "getaddrinfo: %s port %s: %s", fhost, fport,
 		    gai_strerror(error));
 	}
 
@@ -318,6 +348,8 @@
 {
 	fprintf(stderr,
 "usage: tcpdrop local-address local-port foreign-address foreign-port\n"
+"       tcpdrop local-address:local-port foreign-address:foreign-port\n"
+"       tcpdrop local-address.local-port foreign-address.foreign-port\n"
 "       tcpdrop [-l] -a\n");
 	exit(1);
 }

-- 
John Baldwin


More information about the freebsd-net mailing list