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
This commit is contained in:
Mike Silbersack 2003-02-22 06:41:47 +00:00
parent 750a91d8b1
commit 375386e284
2 changed files with 29 additions and 4 deletions

View File

@ -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 @@ ip_reass(struct mbuf *m, struct ipqhead *head, struct ipq *fp,
#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 @@ ip_reass(struct mbuf *m, struct ipqhead *head, struct ipq *fp,
*divert_rule = 0;
#endif
ipstat.ips_fragdropped++;
if (fp != 0)
fp->ipq_nfrags--;
m_freem(m);
return (0);

View File

@ -68,6 +68,7 @@ struct ipq {
u_short ipq_id; /* sequence id for reassembly */
struct mbuf *ipq_frags; /* to ip headers of fragments */
struct in_addr ipq_src,ipq_dst;
u_char ipq_nfrags; /* # frags in this packet */
u_int32_t ipq_div_info; /* ipfw divert port & flags */
u_int16_t ipq_div_cookie; /* ipfw divert cookie */
struct label ipq_label; /* MAC label */