diff options
-rw-r--r-- | sys/netinet6/icmp6.c | 112 |
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; |