This is version two of this patch.
To apply:
cd /usr/src/sys/netinet
patch -p0 < maxqueue.patch
Recompile your kernel.
Index: in.h
===================================================================
RCS file: /cvs/src/sys/netinet/in.h,v
retrieving revision 1.12
diff -u -r1.12 in.h
--- in.h 1998/02/11 03:58:31 1.12
+++ in.h 1999/02/18 04:33:56
@@ -1,4 +1,4 @@
-/* $OpenBSD: in.h,v 1.12 1998/02/11 03:58:31 deraadt Exp $ */
+/* $OpenBSD: in.h,v 1.18 1999/02/17 23:51:12 deraadt Exp $ */
/* $NetBSD: in.h,v 1.20 1996/02/13 23:41:47 christos Exp $ */
/*
@@ -325,7 +325,8 @@
#define IPCTL_IPPORT_LASTAUTO 8
#define IPCTL_IPPORT_HIFIRSTAUTO 9
#define IPCTL_IPPORT_HILASTAUTO 10
-#define IPCTL_MAXID 11
+#define IPCTL_IPPORT_MAXQUEUE 11
+#define IPCTL_MAXID 12
#define IPCTL_NAMES { \
{ 0, 0 }, \
@@ -339,6 +340,7 @@
{ "portlast", CTLTYPE_INT }, \
{ "porthifirst", CTLTYPE_INT }, \
{ "porthilast", CTLTYPE_INT }, \
+ { "maxqueue", CTLTYPE_INT }, \
}
#ifndef _KERNEL
Index: ip_input.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_input.c,v
retrieving revision 1.30
diff -u -r1.30 ip_input.c
--- ip_input.c 1998/02/14 18:50:36 1.30
+++ ip_input.c 1999/02/18 04:33:56
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_input.c,v 1.30 1998/02/14 18:50:36 mickey Exp $ */
+/* $OpenBSD: ip_input.c,v 1.35 1999/02/17 23:51:12 deraadt Exp $ */
/* $NetBSD: ip_input.c,v 1.30 1996/03/16 23:53:58 christos Exp $ */
/*
@@ -99,6 +99,10 @@
u_char ipsec_esp_trans_default_level = IPSEC_ESP_TRANS_LEVEL_DEFAULT;
u_char ipsec_esp_network_default_level = IPSEC_ESP_NETWORK_LEVEL_DEFAULT;
+/* Keep track of memory used for reassembly */
+int ip_maxqueue = 300;
+int ip_frags = 0;
+
/* from in_pcb.c */
extern int ipport_firstauto;
extern int ipport_lastauto;
@@ -117,7 +121,6 @@
struct mbuf **));
#endif
-
char *
inet_ntoa(ina)
struct in_addr ina;
@@ -279,10 +282,10 @@
}
#if defined(IPFILTER) || defined(IPFILTER_LKM)
- /*
- * Check if we want to allow this packet to be processed.
- * Consider it to be bad if not.
- */
+ /*
+ * Check if we want to allow this packet to be processed.
+ * Consider it to be bad if not.
+ */
{
struct mbuf *m0 = m;
if (fr_checkp && (*fr_checkp)(ip, hlen, m->m_pkthdr.rcvif, 0, &m0))
@@ -433,12 +436,19 @@
*/
if (mff || ip->ip_off) {
ipstat.ips_fragments++;
+ if (ip_frags + 1 > ip_maxqueue) {
+ ip_flush();
+ ipstat.ips_rcvmemdrop++;
+ goto bad;
+ }
+
MALLOC(ipqe, struct ipqent *, sizeof (struct ipqent),
M_IPQ, M_NOWAIT);
if (ipqe == NULL) {
ipstat.ips_rcvmemdrop++;
goto bad;
}
+ ip_frags++;
ipqe->ipqe_mff = mff;
ipqe->ipqe_ip = ip;
ip = ip_reass(ipqe, fp);
@@ -580,6 +590,7 @@
m_freem(dtom(q->ipqe_ip));
LIST_REMOVE(q, ipqe_q);
FREE(q, M_IPQ);
+ ip_frags--;
}
insert:
@@ -619,10 +630,12 @@
m_cat(m, t);
nq = q->ipqe_q.le_next;
FREE(q, M_IPQ);
+ ip_frags--;
for (q = nq; q != NULL; q = nq) {
t = dtom(q->ipqe_ip);
nq = q->ipqe_q.le_next;
FREE(q, M_IPQ);
+ ip_frags--;
m_cat(m, t);
}
@@ -652,6 +665,7 @@
ipstat.ips_fragdropped++;
m_freem(m);
FREE(ipqe, M_IPQ);
+ ip_frags--;
return (0);
}
@@ -670,6 +684,7 @@
m_freem(dtom(q->ipqe_ip));
LIST_REMOVE(q, ipqe_q);
FREE(q, M_IPQ);
+ ip_frags--;
}
LIST_REMOVE(fp, ipq_q);
(void) m_free(dtom(fp));
@@ -710,6 +725,19 @@
}
/*
+ * Flush a bunch of datagram fragments, till we are down to 75%.
+ */
+void
+ip_flush()
+{
+
+ while (ipq.lh_first != NULL && ip_frags > ip_maxqueue * 3 / 4) {
+ ipstat.ips_fragdropped++;
+ ip_freef(ipq.lh_first);
+ }
+}
+
+/*
* Do option processing on a datagram,
* possibly discarding it if bad options are encountered,
* or forwarding it if source-routed.
@@ -973,9 +1001,9 @@
*/
static int
ip_weadvertise(addr)
- u_int32_t addr;
+ u_int32_t addr;
{
- register struct rtentry *rt;
+ register struct rtentry *rt;
register struct ifnet *ifp;
register struct ifaddr *ifa;
struct sockaddr_inarp sin;
@@ -990,21 +1018,21 @@
RTFREE(rt);
- if ((rt->rt_flags & RTF_GATEWAY) || (rt->rt_flags & RTF_LLINFO) == 0
- || rt->rt_gateway->sa_family != AF_LINK)
+ if ((rt->rt_flags & RTF_GATEWAY) || (rt->rt_flags & RTF_LLINFO) == 0 ||
+ rt->rt_gateway->sa_family != AF_LINK)
return 0;
for (ifp = ifnet.tqh_first; ifp != 0; ifp = ifp->if_list.tqe_next)
- for (ifa = ifp->if_addrlist.tqh_first; ifa != 0; ifa = ifa->ifa_list.tqe_next)
- {
- if (ifa->ifa_addr->sa_family != rt->rt_gateway->sa_family)
- continue;
-
- if (!bcmp(LLADDR((struct sockaddr_dl *)ifa->ifa_addr),
- LLADDR((struct sockaddr_dl *)rt->rt_gateway),
- ETHER_ADDR_LEN))
- return 1;
- }
+ for (ifa = ifp->if_addrlist.tqh_first; ifa != 0;
+ ifa = ifa->ifa_list.tqe_next) {
+ if (ifa->ifa_addr->sa_family != rt->rt_gateway->sa_family)
+ continue;
+
+ if (!bcmp(LLADDR((struct sockaddr_dl *)ifa->ifa_addr),
+ LLADDR((struct sockaddr_dl *)rt->rt_gateway),
+ ETHER_ADDR_LEN))
+ return 1;
+ }
return 0;
}
@@ -1313,6 +1341,9 @@
case IPCTL_IPPORT_HILASTAUTO:
return (sysctl_int(oldp, oldlenp, newp, newlen,
&ipport_hilastauto));
+ case IPCTL_IPPORT_MAXQUEUE:
+ return (sysctl_int(oldp, oldlenp, newp, newlen,
+ &ip_maxqueue));
default:
return (EOPNOTSUPP);
}
Index: ip_var.h
===================================================================
RCS file: /cvs/src/sys/netinet/ip_var.h,v
retrieving revision 1.8
diff -u -r1.8 ip_var.h
--- ip_var.h 1998/02/14 18:50:36 1.8
+++ ip_var.h 1999/02/18 04:33:56
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_var.h,v 1.8 1998/02/14 18:50:36 mickey Exp $ */
+/* $OpenBSD: ip_var.h,v 1.11 1999/02/17 23:51:12 deraadt Exp $ */
/* $NetBSD: ip_var.h,v 1.16 1996/02/13 23:43:20 christos Exp $ */
/*
@@ -166,6 +166,7 @@
int ip_ctloutput __P((int, struct socket *, int, int, struct mbuf **));
int ip_dooptions __P((struct mbuf *));
void ip_drain __P((void));
+void ip_flush __P((void));
void ip_forward __P((struct mbuf *, int));
void ip_freef __P((struct ipq *));
void ip_freemoptions __P((struct ip_moptions *));