summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>1996-09-20 22:53:14 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>1996-09-20 22:53:14 +0000
commitc922f1a659a0bb42a2e826c000568c540770e4af (patch)
treea4e78fa7dccb50511704fecbc4877af2064ffbcd
parent33a9681c867009363487e3d4d4201e9d7c4d25fb (diff)
`solve' the syn bomb problem as well as currently known; add sysctl's for
SOMAXCONN (kern.somaxconn), SOMINCONN (kern.sominconn), and TCPTV_KEEP_INIT (net.inet.tcp.keepinittime). when this is not enough (ie. overfull), start doing tail drop, but slightly prefer the same port.
-rw-r--r--sys/kern/kern_sysctl.c7
-rw-r--r--sys/kern/uipc_socket.c16
-rw-r--r--sys/kern/uipc_socket2.c4
-rw-r--r--sys/netinet/tcp_input.c63
-rw-r--r--sys/netinet/tcp_usrreq.c8
-rw-r--r--sys/netinet/tcp_var.h7
-rw-r--r--sys/sys/sysctl.h8
7 files changed, 95 insertions, 18 deletions
diff --git a/sys/kern/kern_sysctl.c b/sys/kern/kern_sysctl.c
index ce090a7baf3..c3c20b170dd 100644
--- a/sys/kern/kern_sysctl.c
+++ b/sys/kern/kern_sysctl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_sysctl.c,v 1.11 1996/08/08 06:36:45 tholo Exp $ */
+/* $OpenBSD: kern_sysctl.c,v 1.12 1996/09/20 22:53:09 deraadt Exp $ */
/* $NetBSD: kern_sysctl.c,v 1.17 1996/05/20 17:49:05 mrg Exp $ */
/*-
@@ -204,6 +204,7 @@ kern_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
{
int error, level, inthostid;
extern char ostype[], osrelease[], osversion[], version[];
+ extern int somaxconn, sominconn;
/* all sysctl names at this level are terminal */
if (namelen != 1 && !(name[0] == KERN_PROC || name[0] == KERN_PROF))
@@ -289,6 +290,10 @@ kern_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
return (sysctl_rdint(oldp, oldlenp, newp, RAW_PART));
case KERN_NTPTIME:
return (sysctl_ntptime(oldp, oldlenp));
+ case KERN_SOMAXCONN:
+ return (sysctl_int(oldp, oldlenp, newp, newlen, &somaxconn));
+ case KERN_SOMINCONN:
+ return (sysctl_int(oldp, oldlenp, newp, newlen, &sominconn));
default:
return (EOPNOTSUPP);
}
diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c
index 9cfe26d7f68..c71551fbfca 100644
--- a/sys/kern/uipc_socket.c
+++ b/sys/kern/uipc_socket.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uipc_socket.c,v 1.6 1996/08/24 04:56:36 deraadt Exp $ */
+/* $OpenBSD: uipc_socket.c,v 1.7 1996/09/20 22:53:10 deraadt Exp $ */
/* $NetBSD: uipc_socket.c,v 1.21 1996/02/04 02:17:52 christos Exp $ */
/*
@@ -50,6 +50,12 @@
#include <sys/signalvar.h>
#include <sys/resourcevar.h>
+#ifndef SOMINCONN
+#define SOMINCONN 80
+#endif /* SOMINCONN */
+int somaxconn = SOMAXCONN;
+int sominconn = SOMINCONN;
+
/*
* Socket operation routines.
* These routines are called by the routines in
@@ -131,9 +137,11 @@ solisten(so, backlog)
}
if (so->so_q == 0)
so->so_options |= SO_ACCEPTCONN;
- if (backlog < 0)
- backlog = 0;
- so->so_qlimit = min(backlog, SOMAXCONN);
+ if (backlog < 0 || backlog > somaxconn)
+ backlog = somaxconn;
+ if (backlog < sominconn)
+ backlog = sominconn;
+ so->so_qlimit = backlog;
splx(s);
return (0);
}
diff --git a/sys/kern/uipc_socket2.c b/sys/kern/uipc_socket2.c
index 66b22eb336e..92ab13de5e1 100644
--- a/sys/kern/uipc_socket2.c
+++ b/sys/kern/uipc_socket2.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uipc_socket2.c,v 1.3 1996/08/24 04:56:37 deraadt Exp $ */
+/* $OpenBSD: uipc_socket2.c,v 1.4 1996/09/20 22:53:10 deraadt Exp $ */
/* $NetBSD: uipc_socket2.c,v 1.11 1996/02/04 02:17:55 christos Exp $ */
/*
@@ -160,7 +160,7 @@ sonewconn1(head, connstatus)
register struct socket *so;
int soqueue = connstatus ? 1 : 0;
- if (head->so_qlen + head->so_q0len > 3 * head->so_qlimit / 2)
+ if (head->so_qlen + head->so_q0len > head->so_qlimit * 3)
return ((struct socket *)0);
MALLOC(so, struct socket *, sizeof(*so), M_SOCKET, M_DONTWAIT);
if (so == NULL)
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
index 8b7da3d6e30..0be9bed6e99 100644
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tcp_input.c,v 1.6 1996/08/07 06:36:26 tholo Exp $ */
+/* $OpenBSD: tcp_input.c,v 1.7 1996/09/20 22:53:11 deraadt Exp $ */
/* $NetBSD: tcp_input.c,v 1.23 1996/02/13 23:43:44 christos Exp $ */
/*
@@ -66,6 +66,7 @@
int tcprexmtthresh = 3;
struct tcpiphdr tcp_saveti;
+int tcptv_keep_init = TCPTV_KEEP_INIT;
extern u_long sb_max;
@@ -232,6 +233,51 @@ present:
}
/*
+ * First check for a port-specific bomb. We do not want to drop half-opens
+ * for other ports if this is the only port being bombed. We only check
+ * the bottom 40 half open connections, to avoid wasting too much time.
+ *
+ * Or, otherwise it is more likely a generic syn bomb, so delete the oldest
+ * half-open connection.
+ */
+void
+tcpdropoldhalfopen(avoidtp, port)
+ struct tcpcb *avoidtp;
+ u_int16_t port;
+{
+ register struct inpcb *inp;
+ register struct tcpcb *tp, *droptp = NULL;
+ int ncheck = 40;
+ int s;
+
+ s = splnet();
+ inp = tcbtable.inpt_queue.cqh_first;
+ if (inp) /* XXX */
+ for (; inp != (struct inpcb *)&tcbtable.inpt_queue && --ncheck;
+ inp = inp->inp_queue.cqe_prev) {
+ if ((tp = (struct tcpcb *)inp->inp_ppcb) &&
+ tp != avoidtp &&
+ tp->t_state == TCPS_SYN_RECEIVED &&
+ port == inp->inp_lport) {
+ tcp_close(tp);
+ goto done;
+ }
+ }
+
+ inp = tcbtable.inpt_queue.cqh_first;
+ if (inp) /* XXX */
+ for (; inp != (struct inpcb *)&tcbtable.inpt_queue;
+ inp = inp->inp_queue.cqe_prev) {
+ if ((tp = (struct tcpcb *)inp->inp_ppcb) &&
+ tp != avoidtp &&
+ tp->t_state == TCPS_SYN_RECEIVED)
+ break;
+ }
+done:
+ splx(s);
+}
+
+/*
* TCP input routine, follows pages 65-76 of the
* protocol specification dated September, 1981 very closely.
*/
@@ -386,9 +432,16 @@ findpcb:
tcp_saveti = *ti;
}
if (so->so_options & SO_ACCEPTCONN) {
- so = sonewconn(so, 0);
- if (so == 0)
- goto drop;
+ struct socket *so1;
+
+ so1 = sonewconn(so, 0);
+ if (so1 == NULL) {
+ tcpdropoldhalfopen(tp, ti->ti_dport);
+ so1 = sonewconn(so, 0);
+ if (so1 == NULL)
+ goto drop;
+ }
+ so = so1;
/*
* This is ugly, but ....
*
@@ -630,7 +683,7 @@ findpcb:
tcp_rcvseqinit(tp);
tp->t_flags |= TF_ACKNOW;
tp->t_state = TCPS_SYN_RECEIVED;
- tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT;
+ tp->t_timer[TCPT_KEEP] = tcptv_keep_init;
dropsocket = 0; /* committed to socket */
tcpstat.tcps_accepts++;
goto trimthenstep6;
diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c
index a4e731ffc85..233403a8680 100644
--- a/sys/netinet/tcp_usrreq.c
+++ b/sys/netinet/tcp_usrreq.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tcp_usrreq.c,v 1.6 1996/07/29 22:01:51 niklas Exp $ */
+/* $OpenBSD: tcp_usrreq.c,v 1.7 1996/09/20 22:53:12 deraadt Exp $ */
/* $NetBSD: tcp_usrreq.c,v 1.20 1996/02/13 23:44:16 christos Exp $ */
/*
@@ -72,6 +72,7 @@
* TCP protocol interface to socket abstraction.
*/
extern char *tcpstates[];
+extern int tcptv_keep_init;
/*
* Process a TCP user request for TCP tb. If this is a send request
@@ -209,7 +210,7 @@ tcp_usrreq(so, req, m, nam, control)
soisconnecting(so);
tcpstat.tcps_connattempt++;
tp->t_state = TCPS_SYN_SENT;
- tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT;
+ tp->t_timer[TCPT_KEEP] = tcptv_keep_init;
tp->iss = tcp_iss;
#ifdef TCP_COMPAT_42
tcp_iss += TCP_ISSINCR/2;
@@ -574,6 +575,9 @@ tcp_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
case TCPCTL_RFC1323:
return (sysctl_int(oldp, oldlenp, newp, newlen,
&tcp_do_rfc1323));
+ case TCPCTL_KEEPINITTIME:
+ return (sysctl_int(oldp, oldlenp, newp, newlen,
+ &tcptv_keep_init));
default:
return (ENOPROTOOPT);
diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h
index dde7c1b1e77..d7e84dd6201 100644
--- a/sys/netinet/tcp_var.h
+++ b/sys/netinet/tcp_var.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: tcp_var.h,v 1.4 1996/09/12 06:19:57 tholo Exp $ */
+/* $OpenBSD: tcp_var.h,v 1.5 1996/09/20 22:53:13 deraadt Exp $ */
/* $NetBSD: tcp_var.h,v 1.17 1996/02/13 23:44:24 christos Exp $ */
/*
@@ -232,11 +232,13 @@ struct tcpstat {
*/
/* enable/disable RFC1323 timestamps/scaling */
#define TCPCTL_RFC1323 1
-#define TCPCTL_MAXID 2
+#define TCPCTL_KEEPINITTIME 2
+#define TCPCTL_MAXID 3
#define TCPCTL_NAMES { \
{ 0, 0 }, \
{ "rfc1323", CTLTYPE_INT }, \
+ { "keepinittime", CTLTYPE_INT }, \
}
#ifdef _KERNEL
@@ -285,4 +287,5 @@ int tcp_sysctl __P((int *, u_int, void *, size_t *, void *, size_t));
int tcp_usrreq __P((struct socket *,
int, struct mbuf *, struct mbuf *, struct mbuf *));
void tcp_xmit_timer __P((struct tcpcb *, int));
+void tcpdropoldhalfopen __P((struct tcpcb *, u_int16_t));
#endif
diff --git a/sys/sys/sysctl.h b/sys/sys/sysctl.h
index 2bbb2a6189f..7e985d36995 100644
--- a/sys/sys/sysctl.h
+++ b/sys/sys/sysctl.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: sysctl.h,v 1.9 1996/08/11 20:35:12 niklas Exp $ */
+/* $OpenBSD: sysctl.h,v 1.10 1996/09/20 22:53:05 deraadt Exp $ */
/* $NetBSD: sysctl.h,v 1.16 1996/04/09 20:55:36 cgd Exp $ */
/*
@@ -138,7 +138,9 @@ struct ctlname {
#define KERN_NTPTIME 25 /* struct: extended-precision time */
#define KERN_TIMEX 26 /* struct: ntp timekeeping state */
#define KERN_OSVERSION 27 /* string: kernel build version */
-#define KERN_MAXID 28 /* number of valid kern ids */
+#define KERN_SOMAXCONN 28 /* int: listen queue maximum */
+#define KERN_SOMINCONN 29 /* int: half-open controllable param */
+#define KERN_MAXID 30 /* number of valid kern ids */
#define CTL_KERN_NAMES { \
{ 0, 0 }, \
@@ -169,6 +171,8 @@ struct ctlname {
{ "ntptime", CTLTYPE_STRUCT }, \
{ "timex", CTLTYPE_STRUCT }, \
{ "osversion", CTLTYPE_STRING }, \
+ { "somaxconn", CTLTYPE_INT }, \
+ { "sominconn", CTLTYPE_INT }, \
}
/*