diff options
author | silby <silby@FreeBSD.org> | 2003-02-22 06:41:47 +0000 |
---|---|---|
committer | silby <silby@FreeBSD.org> | 2003-02-22 06:41:47 +0000 |
commit | befb0ff113682be7457ade6d3300be70bc2516f4 (patch) | |
tree | cbeddee447e399a02ac9205d707c9b970aedfb06 /sys/netinet/ip_input.c | |
parent | 8ccfd800bd5c63b6d8c475e3e310baa626166219 (diff) | |
download | FreeBSD-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.c | 32 |
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); |