summaryrefslogtreecommitdiffstats
path: root/sys/netinet
diff options
context:
space:
mode:
authormaxim <maxim@FreeBSD.org>2005-02-06 10:47:12 +0000
committermaxim <maxim@FreeBSD.org>2005-02-06 10:47:12 +0000
commitc183200317c0c27caa6b904e4f129d69c101c487 (patch)
tree81a82bbce807e9b9f91a45a84bac02a9d5a74e61 /sys/netinet
parent98ffca48ea5dc716f1f9420ed241eef776bd605a (diff)
downloadFreeBSD-src-c183200317c0c27caa6b904e4f129d69c101c487.zip
FreeBSD-src-c183200317c0c27caa6b904e4f129d69c101c487.tar.gz
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
Diffstat (limited to 'sys/netinet')
-rw-r--r--sys/netinet/tcp_usrreq.c86
-rw-r--r--sys/netinet/tcp_var.h8
2 files changed, 93 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 }, \
OpenPOWER on IntegriCloud