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:
parent
750a91d8b1
commit
375386e284
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=111244
@ -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);
|
||||
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user