summaryrefslogtreecommitdiff
path: root/sys/netinet
diff options
context:
space:
mode:
authorMike Silbersack <silby@FreeBSD.org>2003-02-22 06:41:47 +0000
committerMike Silbersack <silby@FreeBSD.org>2003-02-22 06:41:47 +0000
commit375386e284b734aa8e16ad8ecf6b8b5bca72eb53 (patch)
treecbeddee447e399a02ac9205d707c9b970aedfb06 /sys/netinet
parent750a91d8b1d767af02a509406cd7ec72e4ec7fb1 (diff)
downloadsrc-test2-375386e284b734aa8e16ad8ecf6b8b5bca72eb53.tar.gz
src-test2-375386e284b734aa8e16ad8ecf6b8b5bca72eb53.zip
Notes
Diffstat (limited to 'sys/netinet')
-rw-r--r--sys/netinet/ip_input.c32
-rw-r--r--sys/netinet/ip_var.h1
2 files changed, 29 insertions, 4 deletions
diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c
index 3e1f8a508dc1..04aa1c37f379 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);
diff --git a/sys/netinet/ip_var.h b/sys/netinet/ip_var.h
index c03c44658252..c8df2e673e4a 100644
--- a/sys/netinet/ip_var.h
+++ b/sys/netinet/ip_var.h
@@ -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 */