Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/netinet ip_reass_packet: finish abstraction; some clean-up.
details: https://anonhg.NetBSD.org/src/rev/f08b87378c6e
branches: trunk
changeset: 758447:f08b87378c6e
user: rmind <rmind%NetBSD.org@localhost>
date: Fri Nov 05 00:21:51 2010 +0000
description:
ip_reass_packet: finish abstraction; some clean-up.
Discussed some time ago with matt@.
diffstat:
sys/netinet/ip_input.c | 53 +++-----------------
sys/netinet/ip_reass.c | 128 ++++++++++++++++++++++++++++++++----------------
sys/netinet/ip_var.h | 4 +-
3 files changed, 96 insertions(+), 89 deletions(-)
diffs (truncated from 337 to 300 lines):
diff -r 27c8d787a3e1 -r f08b87378c6e sys/netinet/ip_input.c
--- a/sys/netinet/ip_input.c Thu Nov 04 23:38:18 2010 +0000
+++ b/sys/netinet/ip_input.c Fri Nov 05 00:21:51 2010 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ip_input.c,v 1.289 2010/07/19 14:09:45 rmind Exp $ */
+/* $NetBSD: ip_input.c,v 1.290 2010/11/05 00:21:51 rmind Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -91,7 +91,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ip_input.c,v 1.289 2010/07/19 14:09:45 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip_input.c,v 1.290 2010/11/05 00:21:51 rmind Exp $");
#include "opt_inet.h"
#include "opt_compat_netbsd.h"
@@ -806,58 +806,21 @@
* If offset or IP_MF are set, must reassemble.
*/
if (ip->ip_off & ~htons(IP_DF|IP_RF)) {
- struct mbuf *m_final;
- u_int off, flen;
- bool mff;
-
- /*
- * Prevent TCP blind data attacks by not allowing non-initial
- * fragments to start at less than 68 bytes (minimal fragment
- * size) and making sure the first fragment is at least 68
- * bytes.
- */
- off = (ntohs(ip->ip_off) & IP_OFFMASK) << 3;
- if ((off > 0 ? off + hlen : len) < IP_MINFRAGSIZE - 1) {
- IP_STATINC(IP_STAT_BADFRAGS);
- goto bad;
- }
-
- /* Fragment length and MF flag. */
- flen = ntohs(ip->ip_len) - hlen;
- mff = (ip->ip_off & htons(IP_MF)) != 0;
- if (mff) {
- /*
- * Make sure that fragments have a data length
- * which is non-zero and multiple of 8 bytes.
- */
- if (flen == 0 || (flen & 0x7) != 0) {
- IP_STATINC(IP_STAT_BADFRAGS);
- goto bad;
- }
- }
-
- /*
- * Adjust total IP length to not reflect header and convert
- * offset of this to bytes. XXX: clobbers struct ip.
- */
- ip->ip_len = htons(flen);
- ip->ip_off = htons(off);
-
/*
* Pass to IP reassembly mechanism.
*/
- if (ip_reass_packet(m, ip, mff, &m_final) != 0) {
+ if (ip_reass_packet(&m, ip) != 0) {
/* Failed; invalid fragment(s) or packet. */
goto bad;
}
- if (m_final == NULL) {
+ if (m == NULL) {
/* More fragments should come; silently return. */
return;
}
- /* Reassembly is done, we have the final packet. */
- m = m_final;
-
- /* Updated local variable(s). */
+ /*
+ * Reassembly is done, we have the final packet.
+ * Updated cached data in local variable(s).
+ */
ip = mtod(m, struct ip *);
hlen = ip->ip_hl << 2;
}
diff -r 27c8d787a3e1 -r f08b87378c6e sys/netinet/ip_reass.c
--- a/sys/netinet/ip_reass.c Thu Nov 04 23:38:18 2010 +0000
+++ b/sys/netinet/ip_reass.c Fri Nov 05 00:21:51 2010 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ip_reass.c,v 1.6 2010/10/07 03:15:49 yamt Exp $ */
+/* $NetBSD: ip_reass.c,v 1.7 2010/11/05 00:21:51 rmind Exp $ */
/*
* Copyright (c) 1982, 1986, 1988, 1993
@@ -46,7 +46,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ip_reass.c,v 1.6 2010/10/07 03:15:49 yamt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip_reass.c,v 1.7 2010/11/05 00:21:51 rmind Exp $");
#include <sys/param.h>
#include <sys/types.h>
@@ -86,9 +86,11 @@
bool ipqe_mff;
} ipfr_qent_t;
+TAILQ_HEAD(ipfr_qent_head, ipfr_qent);
+
typedef struct ipfr_queue {
LIST_ENTRY(ipfr_queue) ipq_q; /* to other reass headers */
- TAILQ_HEAD(, ipfr_qent) ipq_fragq; /* queue of fragment entries */
+ struct ipfr_qent_head ipq_fragq; /* queue of fragment entries */
uint8_t ipq_ttl; /* time for reass q to live */
uint8_t ipq_p; /* protocol of this fragment */
uint16_t ipq_id; /* sequence id for reassembly */
@@ -221,10 +223,10 @@
struct mbuf *
ip_reass(ipfr_qent_t *ipqe, ipfr_queue_t *fp, const u_int hash)
{
- const int hlen = ipqe->ipqe_ip->ip_hl << 2;
+ struct ip *ip = ipqe->ipqe_ip, *qip;
+ const int hlen = ip->ip_hl << 2;
struct mbuf *m = ipqe->ipqe_m, *t;
ipfr_qent_t *nq, *p, *q;
- struct ip *ip;
int i, next;
KASSERT(mutex_owned(&ipfr_lock));
@@ -270,15 +272,15 @@
if (fp == NULL) {
goto dropfrag;
}
- LIST_INSERT_HEAD(&ip_frags[hash], fp, ipq_q);
+ TAILQ_INIT(&fp->ipq_fragq);
fp->ipq_nfrags = 1;
fp->ipq_ttl = IPFRAGTTL;
- fp->ipq_p = ipqe->ipqe_ip->ip_p;
- fp->ipq_id = ipqe->ipqe_ip->ip_id;
- fp->ipq_tos = ipqe->ipqe_ip->ip_tos;
- TAILQ_INIT(&fp->ipq_fragq);
- fp->ipq_src = ipqe->ipqe_ip->ip_src;
- fp->ipq_dst = ipqe->ipqe_ip->ip_dst;
+ fp->ipq_p = ip->ip_p;
+ fp->ipq_id = ip->ip_id;
+ fp->ipq_tos = ip->ip_tos;
+ fp->ipq_src = ip->ip_src;
+ fp->ipq_dst = ip->ip_dst;
+ LIST_INSERT_HEAD(&ip_frags[hash], fp, ipq_q);
p = NULL;
goto insert;
} else {
@@ -288,10 +290,15 @@
/*
* Find a segment which begins after this one does.
*/
- for (p = NULL, q = TAILQ_FIRST(&fp->ipq_fragq); q != NULL;
- p = q, q = TAILQ_NEXT(q, ipqe_q))
- if (ntohs(q->ipqe_ip->ip_off) > ntohs(ipqe->ipqe_ip->ip_off))
+ TAILQ_FOREACH(q, &fp->ipq_fragq, ipqe_q) {
+ if (ntohs(q->ipqe_ip->ip_off) > ntohs(ip->ip_off))
break;
+ }
+ if (q != NULL) {
+ p = TAILQ_PREV(q, ipfr_qent_head, ipqe_q);
+ } else {
+ p = TAILQ_LAST(&fp->ipq_fragq, ipfr_qent_head);
+ }
/*
* If there is a preceding segment, it may provide some of our
@@ -300,16 +307,14 @@
*/
if (p != NULL) {
i = ntohs(p->ipqe_ip->ip_off) + ntohs(p->ipqe_ip->ip_len) -
- ntohs(ipqe->ipqe_ip->ip_off);
+ ntohs(ip->ip_off);
if (i > 0) {
- if (i >= ntohs(ipqe->ipqe_ip->ip_len)) {
+ if (i >= ntohs(ip->ip_len)) {
goto dropfrag;
}
m_adj(ipqe->ipqe_m, i);
- ipqe->ipqe_ip->ip_off =
- htons(ntohs(ipqe->ipqe_ip->ip_off) + i);
- ipqe->ipqe_ip->ip_len =
- htons(ntohs(ipqe->ipqe_ip->ip_len) - i);
+ ip->ip_off = htons(ntohs(ip->ip_off) + i);
+ ip->ip_len = htons(ntohs(ip->ip_len) - i);
}
}
@@ -317,16 +322,18 @@
* While we overlap succeeding segments trim them or, if they are
* completely covered, dequeue them.
*/
- for (; q != NULL &&
- ntohs(ipqe->ipqe_ip->ip_off) + ntohs(ipqe->ipqe_ip->ip_len) >
- ntohs(q->ipqe_ip->ip_off); q = nq) {
- i = (ntohs(ipqe->ipqe_ip->ip_off) +
- ntohs(ipqe->ipqe_ip->ip_len)) - ntohs(q->ipqe_ip->ip_off);
- if (i < ntohs(q->ipqe_ip->ip_len)) {
- q->ipqe_ip->ip_len =
- htons(ntohs(q->ipqe_ip->ip_len) - i);
- q->ipqe_ip->ip_off =
- htons(ntohs(q->ipqe_ip->ip_off) + i);
+ while (q != NULL) {
+ size_t end;
+
+ qip = q->ipqe_ip;
+ end = ntohs(ip->ip_off) + ntohs(ip->ip_len);
+ if (end <= ntohs(qip->ip_off)) {
+ break;
+ }
+ i = end - ntohs(qip->ip_off);
+ if (i < ntohs(qip->ip_len)) {
+ qip->ip_len = htons(ntohs(qip->ip_len) - i);
+ qip->ip_off = htons(ntohs(qip->ip_off) + i);
m_adj(q->ipqe_m, i);
break;
}
@@ -336,6 +343,7 @@
pool_cache_put(ipfren_cache, q);
fp->ipq_nfrags--;
ip_nfrags--;
+ q = nq;
}
insert:
@@ -348,18 +356,20 @@
TAILQ_INSERT_AFTER(&fp->ipq_fragq, p, ipqe, ipqe_q);
}
next = 0;
- for (p = NULL, q = TAILQ_FIRST(&fp->ipq_fragq); q != NULL;
- p = q, q = TAILQ_NEXT(q, ipqe_q)) {
- if (ntohs(q->ipqe_ip->ip_off) != next) {
+ TAILQ_FOREACH(q, &fp->ipq_fragq, ipqe_q) {
+ qip = q->ipqe_ip;
+ if (ntohs(qip->ip_off) != next) {
mutex_exit(&ipfr_lock);
return NULL;
}
- next += ntohs(q->ipqe_ip->ip_len);
+ next += ntohs(qip->ip_len);
}
+ p = TAILQ_LAST(&fp->ipq_fragq, ipfr_qent_head);
if (p->ipqe_mff) {
mutex_exit(&ipfr_lock);
return NULL;
}
+
/*
* Reassembly is complete. Check for a bogus message size.
*/
@@ -602,15 +612,49 @@
* => Passed fragment should have IP_MF flag and/or offset set.
* => Fragment should not have other than IP_MF flags set.
*
- * => Returns 0 on success or error otherwise. When reassembly is complete,
- * m_final representing a constructed final packet is set.
+ * => Returns 0 on success or error otherwise.
+ * => On complete, m0 represents a constructed final packet.
*/
int
-ip_reass_packet(struct mbuf *m, struct ip *ip, bool mff, struct mbuf **m_final)
+ip_reass_packet(struct mbuf **m0, struct ip *ip)
{
+ const int hlen = ip->ip_hl << 2;
+ const int len = ntohs(ip->ip_len);
+ struct mbuf *m = *m0;
ipfr_queue_t *fp;
ipfr_qent_t *ipqe;
- u_int hash;
+ u_int hash, off, flen;
+ bool mff;
+
+ /*
+ * Prevent TCP blind data attacks by not allowing non-initial
+ * fragments to start at less than 68 bytes (minimal fragment
+ * size) and making sure the first fragment is at least 68
+ * bytes.
+ */
+ off = (ntohs(ip->ip_off) & IP_OFFMASK) << 3;
+ if ((off > 0 ? off + hlen : len) < IP_MINFRAGSIZE - 1) {
+ IP_STATINC(IP_STAT_BADFRAGS);
+ return EINVAL;
+ }
+
+ /*
+ * Fragment length and MF flag. Make sure that fragments have
+ * a data length which is non-zero and multiple of 8 bytes.
+ */
+ flen = ntohs(ip->ip_len) - hlen;
+ mff = (ip->ip_off & htons(IP_MF)) != 0;
+ if (mff && (flen == 0 || (flen & 0x7) != 0)) {
+ IP_STATINC(IP_STAT_BADFRAGS);
+ return EINVAL;
+ }
+
+ /*
+ * Adjust total IP length to not reflect header and convert
+ * offset of this to bytes. XXX: clobbers struct ip.
Home |
Main Index |
Thread Index |
Old Index