summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/netinet/tcp_usrreq.c86
-rw-r--r--sys/netinet/tcp_var.h8
-rw-r--r--usr.sbin/Makefile1
-rw-r--r--usr.sbin/tcpdrop/Makefile8
-rw-r--r--usr.sbin/tcpdrop/tcpdrop.864
-rw-r--r--usr.sbin/tcpdrop/tcpdrop.c88
6 files changed, 254 insertions, 1 deletions
diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c
index 660dd5b..a2e3d3c 100644
--- a/sys/netinet/tcp_usrreq.c
+++ b/sys/netinet/tcp_usrreq.c
@@ -1273,3 +1273,89 @@ tcp_usrclosed(tp)
return (tp);
}
+static int
+sysctl_drop(SYSCTL_HANDLER_ARGS)
+{
+ struct tcp_ident_mapping tir;
+ struct inpcb *inp;
+ struct tcpcb *tp;
+ struct sockaddr_in *fin, *lin;
+#ifdef INET6
+ struct sockaddr_in6 *fin6, *lin6;
+ struct in6_addr f6, l6;
+#endif
+ int error;
+
+ inp = NULL;
+ fin = lin = NULL;
+#ifdef INET6
+ fin6 = lin6 = NULL;
+#endif
+ error = 0;
+
+ if (req->oldptr != NULL || req->oldlen != 0)
+ return (EINVAL);
+ if (req->newptr == NULL)
+ return (EPERM);
+ if (req->newlen < sizeof(tir))
+ return (ENOMEM);
+ if ((error = copyin(req->newptr, &tir, sizeof(tir))) != 0)
+ return (error);
+
+ switch (tir.faddr.ss_family) {
+#ifdef INET6
+ case AF_INET6:
+ fin6 = (struct sockaddr_in6 *)&tir.faddr;
+ lin6 = (struct sockaddr_in6 *)&tir.laddr;
+ if (fin6->sin6_len != sizeof(struct sockaddr_in6) ||
+ lin6->sin6_len != sizeof(struct sockaddr_in6))
+ return (EINVAL);
+ error = in6_embedscope(&f6, fin6, NULL, NULL);
+ if (error)
+ return (EINVAL);
+ error = in6_embedscope(&l6, lin6, NULL, NULL);
+ if (error)
+ return (EINVAL);
+ break;
+#endif
+ case AF_INET:
+ fin = (struct sockaddr_in *)&tir.faddr;
+ lin = (struct sockaddr_in *)&tir.laddr;
+ if (fin->sin_len != sizeof(struct sockaddr_in) ||
+ lin->sin_len != sizeof(struct sockaddr_in))
+ return (EINVAL);
+ break;
+ default:
+ return (EINVAL);
+ }
+ INP_INFO_WLOCK(&tcbinfo);
+ switch (tir.faddr.ss_family) {
+#ifdef INET6
+ case AF_INET6:
+ inp = in6_pcblookup_hash(&tcbinfo, &f6, fin6->sin6_port,
+ &l6, lin6->sin6_port, 0, NULL);
+ break;
+#endif
+ case AF_INET:
+ inp = in_pcblookup_hash(&tcbinfo, fin->sin_addr, fin->sin_port,
+ lin->sin_addr, lin->sin_port, 0, NULL);
+ break;
+ }
+ if (inp != NULL) {
+ INP_LOCK(inp);
+ if ((tp = intotcpcb(inp)) &&
+ ((inp->inp_socket->so_options & SO_ACCEPTCONN) == 0)) {
+ tp = tcp_drop(tp, ECONNABORTED);
+ if (tp != NULL)
+ INP_UNLOCK(inp);
+ } else
+ INP_UNLOCK(inp);
+ } else
+ error = ESRCH;
+ INP_INFO_WUNLOCK(&tcbinfo);
+ return (error);
+}
+
+SYSCTL_PROC(_net_inet_tcp, TCPCTL_DROP, drop,
+ CTLTYPE_STRUCT|CTLFLAG_WR|CTLFLAG_SKIP, NULL,
+ 0, sysctl_drop, "", "Drop TCP connection");
diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h
index 4f87ef4..fa98508 100644
--- a/sys/netinet/tcp_var.h
+++ b/sys/netinet/tcp_var.h
@@ -451,6 +451,11 @@ struct xtcpcb {
};
#endif
+struct tcp_ident_mapping {
+ struct sockaddr_storage faddr, laddr;
+ uid_t euid, ruid;
+};
+
/*
* Names for TCP sysctl objects
*/
@@ -467,7 +472,8 @@ struct xtcpcb {
#define TCPCTL_DELACKTIME 12 /* time before sending delayed ACK */
#define TCPCTL_V6MSSDFLT 13 /* MSS default for IPv6 */
#define TCPCTL_SACK 14 /* Selective Acknowledgement,rfc 2018 */
-#define TCPCTL_MAXID 15
+#define TCPCTL_DROP 15 /* drop tcp connection */
+#define TCPCTL_MAXID 16
#define TCPCTL_NAMES { \
{ 0, 0 }, \
diff --git a/usr.sbin/Makefile b/usr.sbin/Makefile
index d8f78dc..55f7871 100644
--- a/usr.sbin/Makefile
+++ b/usr.sbin/Makefile
@@ -159,6 +159,7 @@ SUBDIR= ac \
syslogd \
tcpdchk \
tcpdmatch \
+ tcpdrop \
tcpdump \
timed \
traceroute \
diff --git a/usr.sbin/tcpdrop/Makefile b/usr.sbin/tcpdrop/Makefile
new file mode 100644
index 0000000..44766eb
--- /dev/null
+++ b/usr.sbin/tcpdrop/Makefile
@@ -0,0 +1,8 @@
+# $OpenBSD: Makefile,v 1.1 2004/04/26 19:51:20 markus Exp $
+# $FreeBSD$
+
+PROG= tcpdrop
+MAN= tcpdrop.8
+WARNS?= 6
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/tcpdrop/tcpdrop.8 b/usr.sbin/tcpdrop/tcpdrop.8
new file mode 100644
index 0000000..a77c1d3
--- /dev/null
+++ b/usr.sbin/tcpdrop/tcpdrop.8
@@ -0,0 +1,64 @@
+.\" $OpenBSD: tcpdrop.8,v 1.5 2004/05/24 13:57:31 jmc Exp $
+.\"
+.\" Copyright (c) 2004 Markus Friedl <markus@openbsd.org>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd March 21, 2004
+.Dt TCPDROP 8
+.Os
+.Sh NAME
+.Nm tcpdrop
+.Nd drop a TCP connection
+.Sh SYNOPSIS
+.Nm tcpdrop
+.Ar laddr
+.Ar lport
+.Ar faddr
+.Ar fport
+.Sh DESCRIPTION
+The
+.Nm
+command drops the TCP connection specified by the local address
+.Ar laddr ,
+port
+.Ar lport
+and the foreign address
+.Ar faddr ,
+port
+.Ar fport .
+Addresses and ports can be specified by name or numeric value.
+.Sh EXIT STATUS
+.Ex -std
+.Sh EXAMPLES
+If a connection to
+.Xr httpd 8
+is causing congestion on a network link, one can drop the TCP session
+in charge:
+.Bd -literal -offset indent
+# fstat | egrep 'httpd.*internet.*<--'
+www httpd 21307 3* internet stream tcp \e
+ 0xd1007ca8 192.168.5.41:80 <-- 192.168.5.1:26747
+.Ed
+.Pp
+The following command will drop the connection:
+.Bd -literal -offset indent
+# tcpdrop 192.168.5.41 80 192.168.5.1 26747
+.Ed
+.Sh SEE ALSO
+.Xr fstat 1 ,
+.Xr netstat 1
+.Sh AUTHORS
+.An Markus Friedl Aq markus@openbsd.org
diff --git a/usr.sbin/tcpdrop/tcpdrop.c b/usr.sbin/tcpdrop/tcpdrop.c
new file mode 100644
index 0000000..cfa8c2a
--- /dev/null
+++ b/usr.sbin/tcpdrop/tcpdrop.c
@@ -0,0 +1,88 @@
+/* $OpenBSD: tcpdrop.c,v 1.4 2004/05/22 23:55:22 deraadt Exp $ */
+
+/*-
+ * Copyright (c) 2004 Markus Friedl <markus@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+#include <netinet/in.h>
+#include <netinet/tcp_var.h>
+
+#include <err.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/*
+ * Drop a tcp connection.
+ */
+int
+main(int argc, char *argv[])
+{
+ struct addrinfo hints, *ail, *aif, *laddr, *faddr;
+ struct tcp_ident_mapping tir;
+ int mib[] = { CTL_NET, PF_INET, IPPROTO_TCP, TCPCTL_DROP };
+ int gaierr, rval = 0;
+ char fhbuf[NI_MAXHOST], fsbuf[NI_MAXSERV], lhbuf[NI_MAXHOST],
+ lsbuf[NI_MAXSERV];
+
+ if (argc != 5)
+ errx(1, "usage: tcpdrop laddr lport faddr fport\n");
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ if ((gaierr = getaddrinfo(argv[1], argv[2], &hints, &laddr)) != 0)
+ errx(1, "%s port %s: %s", argv[1], argv[2],
+ gai_strerror(gaierr));
+ if ((gaierr = getaddrinfo(argv[3], argv[4], &hints, &faddr)) != 0) {
+ freeaddrinfo(laddr);
+ errx(1, "%s port %s: %s", argv[3], argv[4],
+ gai_strerror(gaierr));
+ }
+ for (ail = laddr; ail; ail = ail->ai_next) {
+ for (aif = faddr; aif; aif = aif->ai_next) {
+ if (ail->ai_family != aif->ai_family)
+ continue;
+ memcpy(&tir.faddr, aif->ai_addr, aif->ai_addrlen);
+ memcpy(&tir.laddr, ail->ai_addr, ail->ai_addrlen);
+ if (getnameinfo(aif->ai_addr, aif->ai_addrlen,
+ fhbuf, sizeof(fhbuf),
+ fsbuf, sizeof(fsbuf),
+ NI_NUMERICHOST | NI_NUMERICSERV) == -1)
+ err(1, "getnameinfo");
+ if (getnameinfo(ail->ai_addr, ail->ai_addrlen,
+ lhbuf, sizeof(lhbuf),
+ lsbuf, sizeof(lsbuf),
+ NI_NUMERICHOST | NI_NUMERICSERV) == -1)
+ err(1, "getnameinfo");
+ if (sysctl(mib, sizeof (mib) / sizeof (int), NULL,
+ NULL, &tir, sizeof(tir)) == -1) {
+ rval = 1;
+ warn("%s %s %s %s", lhbuf, lsbuf, fhbuf, fsbuf);
+ } else
+ printf("%s %s %s %s: dropped\n",
+ lhbuf, lsbuf, fhbuf, fsbuf);
+ }
+ }
+ freeaddrinfo(laddr);
+ freeaddrinfo(faddr);
+ exit(rval);
+}
OpenPOWER on IntegriCloud