o Implement net.inet.tcp.drop sysctl and userland part, tcpdrop(8)
utility: The tcpdrop command drops the TCP connection specified by the local address laddr, port lport and the foreign address faddr, port fport. Obtained from: OpenBSD Reviewed by: rwatson (locking), ru (man page), -current MFC after: 1 month
This commit is contained in:
parent
3045c8af3f
commit
212a79b010
@ -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");
|
||||
|
@ -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 }, \
|
||||
|
@ -159,6 +159,7 @@ SUBDIR= ac \
|
||||
syslogd \
|
||||
tcpdchk \
|
||||
tcpdmatch \
|
||||
tcpdrop \
|
||||
tcpdump \
|
||||
timed \
|
||||
traceroute \
|
||||
|
8
usr.sbin/tcpdrop/Makefile
Normal file
8
usr.sbin/tcpdrop/Makefile
Normal file
@ -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>
|
64
usr.sbin/tcpdrop/tcpdrop.8
Normal file
64
usr.sbin/tcpdrop/tcpdrop.8
Normal file
@ -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
|
88
usr.sbin/tcpdrop/tcpdrop.c
Normal file
88
usr.sbin/tcpdrop/tcpdrop.c
Normal file
@ -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);
|
||||
}
|
Loading…
Reference in New Issue
Block a user