summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/netinet6/icmp6.c112
1 files changed, 48 insertions, 64 deletions
diff --git a/sys/netinet6/icmp6.c b/sys/netinet6/icmp6.c
index 267a5509a78..1800667847c 100644
--- a/sys/netinet6/icmp6.c
+++ b/sys/netinet6/icmp6.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: icmp6.c,v 1.69 2003/06/02 23:28:15 millert Exp $ */
+/* $OpenBSD: icmp6.c,v 1.70 2003/06/03 06:25:26 itojun Exp $ */
/* $KAME: icmp6.c,v 1.217 2001/06/20 15:03:29 jinmei Exp $ */
/*
@@ -2554,77 +2554,61 @@ icmp6_redirect_output(m0, rt)
if (p - (u_char *)ip6 > maxlen)
goto noredhdropt;
- {
- /* redirected header option */
- int len;
- struct nd_opt_rd_hdr *nd_opt_rh;
+ {
+ /* redirected header option */
+ int len;
+ struct nd_opt_rd_hdr *nd_opt_rh;
- /*
- * compute the maximum size for icmp6 redirect header option.
- * XXX room for auth header?
- */
- len = maxlen - (p - (u_char *)ip6);
- len &= ~7;
-
- /* This is just for simplicity. */
- if (m0->m_pkthdr.len != m0->m_len) {
- if (m0->m_next) {
- m_freem(m0->m_next);
- m0->m_next = NULL;
- }
- m0->m_pkthdr.len = m0->m_len;
- }
+ /*
+ * compute the maximum size for icmp6 redirect header option.
+ * XXX room for auth header?
+ */
+ len = maxlen - (p - (u_char *)ip6);
+ len &= ~7;
- /*
- * Redirected header option spec (RFC2461 4.6.3) talks nothing
- * about padding/truncate rule for the original IP packet.
- * From the discussion on IPv6imp in Feb 1999, the consensus was:
- * - "attach as much as possible" is the goal
- * - pad if not aligned (original size can be guessed by original
- * ip6 header)
- * Following code adds the padding if it is simple enough,
- * and truncates if not.
- */
- if (m0->m_next || m0->m_pkthdr.len != m0->m_len)
- panic("assumption failed in %s:%d", __FILE__, __LINE__);
+ /*
+ * Redirected header option spec (RFC2461 4.6.3) talks nothing
+ * about padding/truncate rule for the original IP packet.
+ * From the discussion on IPv6imp in Feb 1999,
+ * the consensus was:
+ * - "attach as much as possible" is the goal
+ * - pad if not aligned (original size can be guessed by
+ * original ip6 header)
+ * Following code adds the padding if it is simple enough,
+ * and truncates if not.
+ */
+ if (len - sizeof(*nd_opt_rh) < m0->m_pkthdr.len) {
+ /* not enough room, truncate */
+ m_adj(m0, (len - sizeof(*nd_opt_rh)) -
+ m0->m_pkthdr.len);
+ } else {
+ /*
+ * enough room, truncate if not aligned.
+ * we don't pad here for simplicity.
+ */
+ size_t extra;
- if (len - sizeof(*nd_opt_rh) < m0->m_pkthdr.len) {
- /* not enough room, truncate */
- m0->m_pkthdr.len = m0->m_len = len - sizeof(*nd_opt_rh);
- } else {
- /* enough room, pad or truncate */
- size_t extra;
-
- extra = m0->m_pkthdr.len % 8;
- if (extra) {
- /* pad if easy enough, truncate if not */
- if (8 - extra <= M_TRAILINGSPACE(m0)) {
- /* pad */
- m0->m_len += (8 - extra);
- m0->m_pkthdr.len += (8 - extra);
- } else {
+ extra = m0->m_pkthdr.len % 8;
+ if (extra) {
/* truncate */
- m0->m_pkthdr.len -= extra;
- m0->m_len -= extra;
+ m_adj(m0, -extra);
}
+ len = m0->m_pkthdr.len + sizeof(*nd_opt_rh);
}
- len = m0->m_pkthdr.len + sizeof(*nd_opt_rh);
- m0->m_pkthdr.len = m0->m_len = len - sizeof(*nd_opt_rh);
- }
- nd_opt_rh = (struct nd_opt_rd_hdr *)p;
- bzero(nd_opt_rh, sizeof(*nd_opt_rh));
- nd_opt_rh->nd_opt_rh_type = ND_OPT_REDIRECTED_HEADER;
- nd_opt_rh->nd_opt_rh_len = len >> 3;
- p += sizeof(*nd_opt_rh);
- m->m_pkthdr.len = m->m_len = p - (u_char *)ip6;
+ nd_opt_rh = (struct nd_opt_rd_hdr *)p;
+ bzero(nd_opt_rh, sizeof(*nd_opt_rh));
+ nd_opt_rh->nd_opt_rh_type = ND_OPT_REDIRECTED_HEADER;
+ nd_opt_rh->nd_opt_rh_len = len >> 3;
+ p += sizeof(*nd_opt_rh);
+ m->m_pkthdr.len = m->m_len = p - (u_char *)ip6;
- /* connect m0 to m */
- m->m_next = m0;
- m->m_pkthdr.len = m->m_len + m0->m_len;
- m0 = NULL;
- }
-noredhdropt:;
+ /* connect m0 to m */
+ m_cat(m, m0);
+ m->m_pkthdr.len += m0->m_pkthdr.len;
+ m0 = NULL;
+ }
+noredhdropt:
if (m0) {
m_freem(m0);
m0 = NULL;