summaryrefslogtreecommitdiffstats
path: root/sys/netinet/ip_input.c
diff options
context:
space:
mode:
authorsilby <silby@FreeBSD.org>2003-02-22 06:41:47 +0000
committersilby <silby@FreeBSD.org>2003-02-22 06:41:47 +0000
commitbefb0ff113682be7457ade6d3300be70bc2516f4 (patch)
treecbeddee447e399a02ac9205d707c9b970aedfb06 /sys/netinet/ip_input.c
parent8ccfd800bd5c63b6d8c475e3e310baa626166219 (diff)
downloadFreeBSD-src-befb0ff113682be7457ade6d3300be70bc2516f4.zip
FreeBSD-src-befb0ff113682be7457ade6d3300be70bc2516f4.tar.gz
Add the ability to limit the number of IP fragments allowed per packet,
and enable it by default, with a limit of 16. At the same time, tweak maxfragpackets downward so that in the worst possible case, IP reassembly can use only 1/2 of all mbuf clusters. MFC after: 3 days Reviewed by: hsu Liked by: bmah
Diffstat (limited to 'sys/netinet/ip_input.c')
-rw-r--r--sys/netinet/ip_input.c32
1 files changed, 28 insertions, 4 deletions
diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c
index 3e1f8a5..04aa1c3 100644
--- a/sys/netinet/ip_input.c
+++ b/sys/netinet/ip_input.c
@@ -125,6 +125,11 @@ SYSCTL_INT(_net_inet_ip, OID_AUTO, maxfragpackets, CTLFLAG_RW,
&maxnipq, 0,
"Maximum number of IPv4 fragment reassembly queue entries");
+static int maxfragsperpacket;
+SYSCTL_INT(_net_inet_ip, OID_AUTO, maxfragsperpacket, CTLFLAG_RW,
+ &maxfragsperpacket, 0,
+ "Maximum number of IPv4 fragments allowed per packet");
+
static int ip_sendsourcequench = 0;
SYSCTL_INT(_net_inet_ip, OID_AUTO, sendsourcequench, CTLFLAG_RW,
&ip_sendsourcequench, 0,
@@ -256,7 +261,8 @@ ip_init()
for (i = 0; i < IPREASS_NHASH; i++)
TAILQ_INIT(&ipq[i]);
- maxnipq = nmbclusters / 4;
+ maxnipq = nmbclusters / 32;
+ maxfragsperpacket = 16;
#ifndef RANDOM_IP_ID
ip_id = time_second & 0xffff;
@@ -994,6 +1000,7 @@ ip_reass(struct mbuf *m, struct ipqhead *head, struct ipq *fp,
#endif
TAILQ_INSERT_HEAD(head, fp, ipq_list);
nipq++;
+ fp->ipq_nfrags = 1;
fp->ipq_ttl = IPFRAGTTL;
fp->ipq_p = ip->ip_p;
fp->ipq_id = ip->ip_id;
@@ -1007,6 +1014,7 @@ ip_reass(struct mbuf *m, struct ipqhead *head, struct ipq *fp,
#endif
goto inserted;
} else {
+ fp->ipq_nfrags++;
#ifdef MAC
mac_update_ipq(m, fp);
#endif
@@ -1064,6 +1072,7 @@ ip_reass(struct mbuf *m, struct ipqhead *head, struct ipq *fp,
}
nq = q->m_nextpkt;
m->m_nextpkt = nq;
+ fp->ipq_nfrags--;
m_freem(q);
}
@@ -1083,17 +1092,30 @@ inserted:
#endif
/*
- * Check for complete reassembly.
+ * Check for complete reassembly and perform frag per packet
+ * limiting.
+ *
+ * Frag limiting is performed here so that the nth frag has
+ * a chance to complete the packet before we drop the packet.
+ * As a result, n+1 frags are actually allowed per packet, but
+ * only n will ever be stored. (n = maxfragsperpacket.)
+ *
*/
next = 0;
for (p = NULL, q = fp->ipq_frags; q; p = q, q = q->m_nextpkt) {
- if (GETIP(q)->ip_off != next)
+ if (GETIP(q)->ip_off != next) {
+ if (fp->ipq_nfrags > maxfragsperpacket)
+ ip_freef(head, fp);
return (0);
+ }
next += GETIP(q)->ip_len;
}
/* Make sure the last packet didn't have the IP_MF flag */
- if (p->m_flags & M_FRAG)
+ if (p->m_flags & M_FRAG) {
+ if (fp->ipq_nfrags > maxfragsperpacket)
+ ip_freef(head, fp);
return (0);
+ }
/*
* Reassembly is complete. Make sure the packet is a sane size.
@@ -1160,6 +1182,8 @@ dropfrag:
*divert_rule = 0;
#endif
ipstat.ips_fragdropped++;
+ if (fp != 0)
+ fp->ipq_nfrags--;
m_freem(m);
return (0);
OpenPOWER on IntegriCloud