summaryrefslogtreecommitdiffstats
path: root/sys/kern/uipc_socket2.c
diff options
context:
space:
mode:
authorpst <pst@FreeBSD.org>1996-10-07 04:32:42 +0000
committerpst <pst@FreeBSD.org>1996-10-07 04:32:42 +0000
commitb51353f335c040b93b8b1ff67548f54b0583bf05 (patch)
tree814c80d2758967fd9cd0fbbf088e6190d2a39dbb /sys/kern/uipc_socket2.c
parente80eb7c64875936656241e55c93e705df082c3f7 (diff)
downloadFreeBSD-src-b51353f335c040b93b8b1ff67548f54b0583bf05.zip
FreeBSD-src-b51353f335c040b93b8b1ff67548f54b0583bf05.tar.gz
Increase robustness of FreeBSD against high-rate connection attempt
denial of service attacks. Reviewed by: bde,wollman,olah Inspired by: vjs@sgi.com
Diffstat (limited to 'sys/kern/uipc_socket2.c')
-rw-r--r--sys/kern/uipc_socket2.c52
1 files changed, 46 insertions, 6 deletions
diff --git a/sys/kern/uipc_socket2.c b/sys/kern/uipc_socket2.c
index 0590034..59c8ff1 100644
--- a/sys/kern/uipc_socket2.c
+++ b/sys/kern/uipc_socket2.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)uipc_socket2.c 8.1 (Berkeley) 6/10/93
- * $Id: uipc_socket2.c,v 1.13 1996/08/19 19:22:26 julian Exp $
+ * $Id: uipc_socket2.c,v 1.14 1996/09/19 00:54:36 pst Exp $
*/
#include <sys/param.h>
@@ -60,9 +60,6 @@ static u_long sb_efficiency = 8; /* parameter for sbreserve() */
SYSCTL_INT(_kern, OID_AUTO, sockbuf_waste_factor, CTLFLAG_RW, &sb_efficiency,
0, "");
-static int sominqueue = 0;
-SYSCTL_INT(_kern, KERN_SOMINQUEUE, sominqueue, CTLFLAG_RW, &sominqueue, 0, "");
-
/*
* Procedures to manipulate state flags of socket
* and do appropriate wakeups. Normal sequence from the
@@ -113,6 +110,7 @@ soisconnected(so)
if (head && (so->so_state & SS_INCOMP)) {
TAILQ_REMOVE(&head->so_incomp, so, so_list);
so->so_state &= ~SS_INCOMP;
+ so->so_incqlen--;
TAILQ_INSERT_TAIL(&head->so_comp, so, so_list);
so->so_state |= SS_COMP;
sorwakeup(head);
@@ -149,6 +147,47 @@ soisdisconnected(so)
}
/*
+ * Return a random connection that hasn't been serviced yet and
+ * is eligible for discard.
+ *
+ * This may be used in conjunction with protocol specific queue
+ * congestion routines.
+ */
+struct socket *
+sodropablereq(head)
+ register struct socket *head;
+{
+ register struct socket *so;
+ unsigned int i, j, qlen;
+
+ static int rnd;
+ static long old_mono_secs;
+ static unsigned int cur_cnt, old_cnt;
+
+ so = TAILQ_FIRST(&head->so_incomp);
+ if (!so)
+ return (so);
+
+ qlen = head->so_incqlen;
+
+ if ((i = (mono_time.tv_sec - old_mono_secs)) != 0) {
+ old_mono_secs = mono_time.tv_sec;
+ old_cnt = cur_cnt / i;
+ cur_cnt = 0;
+ }
+
+ if (++cur_cnt > qlen || old_cnt > qlen) {
+ rnd = (314159 * rnd + 66329) & 0xffff;
+ j = ((qlen + 1) * rnd) >> 16;
+
+ while (j-- && so)
+ so = TAILQ_NEXT(so, so_list);
+ }
+
+ return (so);
+}
+
+/*
* When an attempt at a new connection is noted on a socket
* which accepts connections, sonewconn is called. If the
* connection is possible (subject to space constraints, etc.)
@@ -166,8 +205,7 @@ sonewconn1(head, connstatus)
{
register struct socket *so;
- if ((head->so_qlen > 3 * head->so_qlimit / 2) &&
- (head->so_qlen > sominqueue))
+ if (head->so_qlen > 3 * head->so_qlimit / 2)
return ((struct socket *)0);
MALLOC(so, struct socket *, sizeof(*so), M_SOCKET, M_DONTWAIT);
if (so == NULL)
@@ -188,6 +226,7 @@ sonewconn1(head, connstatus)
} else {
TAILQ_INSERT_TAIL(&head->so_incomp, so, so_list);
so->so_state |= SS_INCOMP;
+ head->so_incqlen++;
}
head->so_qlen++;
if ((*so->so_proto->pr_usrreqs->pru_attach)(so, 0)) {
@@ -195,6 +234,7 @@ sonewconn1(head, connstatus)
TAILQ_REMOVE(&head->so_comp, so, so_list);
} else {
TAILQ_REMOVE(&head->so_incomp, so, so_list);
+ head->so_incqlen--;
}
head->so_qlen--;
(void) free((caddr_t)so, M_SOCKET);
OpenPOWER on IntegriCloud