Deleted Added
full compact
1,2c1,2
< /* $FreeBSD: head/sys/netinet6/ip6_input.c 77003 2001-05-22 17:32:02Z ume $ */
< /* $KAME: ip6_input.c,v 1.95 2000/07/02 07:49:37 jinmei Exp $ */
---
> /* $FreeBSD: head/sys/netinet6/ip6_input.c 78064 2001-06-11 12:39:29Z ume $ */
> /* $KAME: ip6_input.c,v 1.194 2001/05/27 13:28:35 itojun Exp $ */
75a76
> #include <sys/malloc.h>
110a112,118
> #ifdef IPSEC
> #include <netinet6/ipsec.h>
> #ifdef INET6
> #include <netinet6/ipsec6.h>
> #endif
> #endif
>
126a135,136
> extern struct callout in6_tmpaddrtimer_ch;
>
131a142,144
> int ip6_ours_check_algorithm;
>
>
139a153
> static struct mbuf *ip6_setdstifaddr __P((struct mbuf *, struct in6_ifaddr *));
145a160
>
153,154c168,169
< register struct ip6protosw *pr;
< register int i;
---
> struct ip6protosw *pr;
> int i;
156a172,175
> #ifdef DIAGNOSTIC
> if (sizeof(struct protosw) != sizeof(struct ip6protosw))
> panic("sizeof(protosw) != sizeof(ip6protosw)");
> #endif
177a197,198
> microtime(&tv);
> ip6_desync_factor = (random() ^ tv.tv_usec) % MAX_TEMP_DESYNC_FACTOR;
192c213,215
< timeout(nd6_timer, (caddr_t)0, hz);
---
> callout_init(&nd6_timer_ch, 0);
> callout_reset(&nd6_timer_ch, hz, nd6_timer, NULL);
>
194c217,224
< timeout(in6_rr_timer, (caddr_t)0, hz);
---
> callout_init(&in6_rr_timer_ch, 0);
> callout_reset(&in6_rr_timer_ch, hz, in6_rr_timer, NULL);
>
> /* timer for regeneranation of temporary addresses randomize ID */
> callout_reset(&in6_tmpaddrtimer_ch,
> (ip6_temp_preferred_lifetime - ip6_desync_factor -
> ip6_temp_regen_advance) * hz,
> in6_tmpaddrtimer, NULL);
249a280,284
> * make sure we don't have onion peering information into m_aux.
> */
> ip6_delaux(m);
>
> /*
257a293
> #define M2MMAX (sizeof(ip6stat.ip6s_m2m)/sizeof(ip6stat.ip6s_m2m[0]))
261c297
< } else if (m->m_pkthdr.rcvif->if_index <= 31)
---
> } else if (m->m_pkthdr.rcvif->if_index < M2MMAX)
266a303
> #undef M2MMAX
363c400
< * Scope check
---
> * Check against address spoofing/corruption.
366a404,406
> /*
> * XXX: "badscope" is not very suitable for a multicast source.
> */
371c411,417
<
---
> if ((IN6_IS_ADDR_LOOPBACK(&ip6->ip6_src) ||
> IN6_IS_ADDR_LOOPBACK(&ip6->ip6_dst)) &&
> (m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) == 0) {
> ip6stat.ip6s_badscope++;
> in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
> goto bad;
> }
373,375c419,428
< * Don't check IPv4 mapped address here. SIIT assumes that
< * routers would forward IPv6 native packets with IPv4 mapped
< * address normally.
---
> * The following check is not documented in specs. A malicious
> * party may be able to use IPv4 mapped addr to confuse tcp/udp stack
> * and bypass security checks (act as if it was from 127.0.0.1 by using
> * IPv6 src ::ffff:127.0.0.1). Be cautious.
> *
> * This check chokes if we are in an SIIT cloud. As none of BSDs
> * support IPv4-less kernel compilation, we cannot support SIIT
> * environment at all. So, it makes more sense for us to reject any
> * malicious packets for non-SIIT environment, than try to do a
> * partical support for SIIT environment.
376a430,435
> if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) ||
> IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)) {
> ip6stat.ip6s_badscope++;
> in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
> goto bad;
> }
392,395d450
< if (IN6_IS_ADDR_LOOPBACK(&ip6->ip6_src) ||
< IN6_IS_ADDR_LOOPBACK(&ip6->ip6_dst)) {
< if (m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) {
< struct in6_ifaddr *ia6;
397,413c452,455
< if ((ia6 = in6ifa_ifpwithaddr(m->m_pkthdr.rcvif,
< &ip6->ip6_dst)) != NULL) {
< ia6->ia_ifa.if_ipackets++;
< ia6->ia_ifa.if_ibytes += m->m_pkthdr.len;
< } else {
< /*
< * The packet is looped back, but we do not
< * have the destination address for some
< * reason.
< * XXX: should we return an icmp6 error?
< */
< goto bad;
< }
< ours = 1;
< deliverifp = m->m_pkthdr.rcvif;
< goto hbhcheck;
< } else {
---
> /* drop packets if interface ID portion is already filled */
> if ((m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) == 0) {
> if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src) &&
> ip6->ip6_src.s6_addr16[1]) {
415d456
< in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
417a459,463
> if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst) &&
> ip6->ip6_dst.s6_addr16[1]) {
> ip6stat.ip6s_badscope++;
> goto bad;
> }
420,432c466,471
< #ifndef FAKE_LOOPBACK_IF
< if ((m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) == 0)
< #else
< if (1)
< #endif
< {
< if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src))
< ip6->ip6_src.s6_addr16[1]
< = htons(m->m_pkthdr.rcvif->if_index);
< if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst))
< ip6->ip6_dst.s6_addr16[1]
< = htons(m->m_pkthdr.rcvif->if_index);
< }
---
> if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src))
> ip6->ip6_src.s6_addr16[1]
> = htons(m->m_pkthdr.rcvif->if_index);
> if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst))
> ip6->ip6_dst.s6_addr16[1]
> = htons(m->m_pkthdr.rcvif->if_index);
433a473
> #if 0 /* this case seems to be unnecessary. (jinmei, 20010401) */
435,438c475,481
< * XXX we need this since we do not have "goto ours" hack route
< * for some of our ifaddrs on loopback interface.
< * we should correct it by changing in6_ifattach to install
< * "goto ours" hack route.
---
> * We use rt->rt_ifp to determine if the address is ours or not.
> * If rt_ifp is lo0, the address is ours.
> * The problem here is, rt->rt_ifp for fe80::%lo0/64 is set to lo0,
> * so any address under fe80::%lo0/64 will be mistakenly considered
> * local. The special case is supplied to handle the case properly
> * by actually looking at interface addresses
> * (using in6ifa_ifpwithaddr).
440,488c483,489
< if ((m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) != 0) {
< if (IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_dst)) {
< struct in6_ifaddr *ia6;
< #ifndef FAKE_LOOPBACK_IF
< int deliverifid;
<
< /*
< * Get the "real" delivered interface, which should be
< * embedded in the second 16 bits of the destination
< * address. We can probably trust the value, but we
< * add validation for the value just for safety.
< */
< deliverifid = ntohs(ip6->ip6_dst.s6_addr16[1]);
< if (deliverifid > 0 && deliverifid <= if_index) {
< deliverifp = ifindex2ifnet[deliverifid];
<
< /*
< * XXX: fake the rcvif to the real interface.
< * Since m_pkthdr.rcvif should be lo0 (or a
< * variant), it would confuse scope handling
< * code later.
< */
< m->m_pkthdr.rcvif = deliverifp;
< }
< else {
< /*
< * Last resort; just use rcvif.
< * XXX: the packet would be discarded by the
< * succeeding check.
< */
< deliverifp = m->m_pkthdr.rcvif;
< }
< #else
< deliverifp = m->m_pkthdr.rcvif;
< #endif
< if ((ia6 = in6ifa_ifpwithaddr(deliverifp,
< &ip6->ip6_dst)) != NULL) {
< ia6->ia_ifa.if_ipackets++;
< ia6->ia_ifa.if_ibytes += m->m_pkthdr.len;
< } else {
< /*
< * We do not have the link-local address
< * specified as the destination.
< * XXX: should we return an icmp6 error?
< */
< goto bad;
< }
< ours = 1;
< goto hbhcheck;
---
> if ((m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) != 0 &&
> IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_dst)) {
> if (!in6ifa_ifpwithaddr(m->m_pkthdr.rcvif, &ip6->ip6_dst)) {
> icmp6_error(m, ICMP6_DST_UNREACH,
> ICMP6_DST_UNREACH_ADDR, 0);
> /* m is already freed */
> return;
489a491,494
>
> ours = 1;
> deliverifp = m->m_pkthdr.rcvif;
> goto hbhcheck;
490a496
> #endif
518a525,531
> switch (ip6_ours_check_algorithm) {
> default:
> /*
> * XXX: I intentionally broke our indentation rule here,
> * since this switch-case is just for measurement and
> * therefore should soon be removed.
> */
522c535
< &ip6_forward_rt.ro_dst.sin6_addr))
---
> &((struct sockaddr_in6 *)(&ip6_forward_rt.ro_dst))->sin6_addr))
524a538,539
> struct sockaddr_in6 *dst6;
>
533,535c548,551
< ip6_forward_rt.ro_dst.sin6_len = sizeof(struct sockaddr_in6);
< ip6_forward_rt.ro_dst.sin6_family = AF_INET6;
< ip6_forward_rt.ro_dst.sin6_addr = ip6->ip6_dst;
---
> dst6 = (struct sockaddr_in6 *)&ip6_forward_rt.ro_dst;
> dst6->sin6_len = sizeof(struct sockaddr_in6);
> dst6->sin6_family = AF_INET6;
> dst6->sin6_addr = ip6->ip6_dst;
553a570,580
> *
> * XXX: some OSes automatically make a cloned route for the destination
> * of an outgoing packet. If the outgoing interface of the packet
> * is a loopback one, the kernel would consider the packet to be
> * accepted, even if we have no such address assinged on the interface.
> * We check the cloned flag of the route entry to reject such cases,
> * assuming that route entries for our own addresses are not made by
> * cloning (it should be true because in6_addloop explicitly installs
> * the host route). However, we might have to do an explicit check
> * while it would be less efficient. Or, should we rather install a
> * reject route for such a case?
557a585,590
> #ifdef RTF_WASCLONED
> !(ip6_forward_rt.ro_rt->rt_flags & RTF_WASCLONED) &&
> #endif
> #ifdef RTF_CLONED
> !(ip6_forward_rt.ro_rt->rt_flags & RTF_CLONED) &&
> #endif
565c598
< &rt6_key(ip6_forward_rt.ro_rt)->sin6_addr) &&
---
> &rt6_key(ip6_forward_rt.ro_rt)->sin6_addr)
570,571c603
< if (ia6->ia6_flags & IN6_IFF_ANYCAST)
< m->m_flags |= M_ANYCAST6;
---
>
572a605,609
> * record address information into m_aux.
> */
> (void)ip6_setdstifaddr(m, ia6);
>
> /*
580d616
<
584d619
<
588,589c623,624
< log(LOG_INFO,
< "ip6_input: packet to an unready address %s->%s",
---
> nd6log((LOG_INFO,
> "ip6_input: packet to an unready address %s->%s\n",
591c626
< ip6_sprintf(&ip6->ip6_dst));
---
> ip6_sprintf(&ip6->ip6_dst)));
595a631
> } /* XXX indentation (see above) */
623a660,680
> * record address information into m_aux, if we don't have one yet.
> * note that we are unable to record it, if the address is not listed
> * as our interface address (e.g. multicast addresses, addresses
> * within FAITH prefixes and such).
> */
> if (deliverifp && !ip6_getdstifaddr(m)) {
> struct in6_ifaddr *ia6;
>
> ia6 = in6_ifawithifp(deliverifp, &ip6->ip6_dst);
> if (ia6) {
> if (!ip6_setdstifaddr(m, ia6)) {
> /*
> * XXX maybe we should drop the packet here,
> * as we could not provide enough information
> * to the upper layers.
> */
> }
> }
> }
>
> /*
751a809
>
767a826,854
> #if 0
> /*
> * do we need to do it for every header? yeah, other
> * functions can play with it (like re-allocate and copy).
> */
> mhist = ip6_addaux(m);
> if (mhist && M_TRAILINGSPACE(mhist) >= sizeof(nxt)) {
> hist = mtod(mhist, caddr_t) + mhist->m_len;
> bcopy(&nxt, hist, sizeof(nxt));
> mhist->m_len += sizeof(nxt);
> } else {
> ip6stat.ip6s_toomanyhdr++;
> goto bad;
> }
> #endif
>
> #ifdef IPSEC
> /*
> * enforce IPsec policy checking if we are seeing last header.
> * note that we do not visit this with protocols with pcb layer
> * code - like udp/tcp/raw ip.
> */
> if ((inet6sw[ip6_protox[nxt]].pr_flags & PR_LASTHDR) != 0 &&
> ipsec6_in_reject(m, NULL)) {
> ipsec6stat.in_polvio++;
> goto bad;
> }
> #endif
>
775a863,892
> * set/grab in6_ifaddr correspond to IPv6 destination address.
> * XXX backward compatibility wrapper
> */
> static struct mbuf *
> ip6_setdstifaddr(m, ia6)
> struct mbuf *m;
> struct in6_ifaddr *ia6;
> {
> struct mbuf *n;
>
> n = ip6_addaux(m);
> if (n)
> mtod(n, struct ip6aux *)->ip6a_dstia6 = ia6;
> return n; /* NULL if failed to set */
> }
>
> struct in6_ifaddr *
> ip6_getdstifaddr(m)
> struct mbuf *m;
> {
> struct mbuf *n;
>
> n = ip6_findaux(m);
> if (n)
> return mtod(n, struct ip6aux *)->ip6a_dstia6;
> else
> return NULL;
> }
>
> /*
786c903
< register struct mbuf *m = *mp;
---
> struct mbuf *m = *mp;
831a949,952
> *
> * The function assumes that hbh header is located right after the IPv6 header
> * (RFC2460 p7), opthead is pointer into data content in m, and opthead to
> * opthead + hbhlen is located in continuous memory region.
845a967
> const int erroff = sizeof(struct ip6_hdr) + sizeof(struct ip6_hbh);
848,873c970,981
< switch(*opt) {
< case IP6OPT_PAD1:
< optlen = 1;
< break;
< case IP6OPT_PADN:
< if (hbhlen < IP6OPT_MINLEN) {
< ip6stat.ip6s_toosmall++;
< goto bad;
< }
< optlen = *(opt + 1) + 2;
< break;
< case IP6OPT_RTALERT:
< /* XXX may need check for alignment */
< if (hbhlen < IP6OPT_RTALERT_LEN) {
< ip6stat.ip6s_toosmall++;
< goto bad;
< }
< if (*(opt + 1) != IP6OPT_RTALERT_LEN - 2)
< /* XXX: should we discard the packet? */
< log(LOG_ERR, "length of router alert opt is inconsitent(%d)",
< *(opt + 1));
< optlen = IP6OPT_RTALERT_LEN;
< bcopy((caddr_t)(opt + 2), (caddr_t)&rtalert_val, 2);
< *rtalertp = ntohs(rtalert_val);
< break;
< case IP6OPT_JUMBO:
---
> switch (*opt) {
> case IP6OPT_PAD1:
> optlen = 1;
> break;
> case IP6OPT_PADN:
> if (hbhlen < IP6OPT_MINLEN) {
> ip6stat.ip6s_toosmall++;
> goto bad;
> }
> optlen = *(opt + 1) + 2;
> break;
> case IP6OPT_RTALERT:
874a983,999
> if (hbhlen < IP6OPT_RTALERT_LEN) {
> ip6stat.ip6s_toosmall++;
> goto bad;
> }
> if (*(opt + 1) != IP6OPT_RTALERT_LEN - 2) {
> /* XXX stat */
> icmp6_error(m, ICMP6_PARAM_PROB,
> ICMP6_PARAMPROB_HEADER,
> erroff + opt + 1 - opthead);
> return(-1);
> }
> optlen = IP6OPT_RTALERT_LEN;
> bcopy((caddr_t)(opt + 2), (caddr_t)&rtalert_val, 2);
> *rtalertp = ntohs(rtalert_val);
> break;
> case IP6OPT_JUMBO:
> /* XXX may need check for alignment */
879,883c1004,1010
< if (*(opt + 1) != IP6OPT_JUMBO_LEN - 2)
< /* XXX: should we discard the packet? */
< log(LOG_ERR, "length of jumbopayload opt "
< "is inconsistent(%d)",
< *(opt + 1));
---
> if (*(opt + 1) != IP6OPT_JUMBO_LEN - 2) {
> /* XXX stat */
> icmp6_error(m, ICMP6_PARAM_PROB,
> ICMP6_PARAMPROB_HEADER,
> erroff + opt + 1 - opthead);
> return(-1);
> }
888c1015
< * must not contain a jumbo paylod option.
---
> * must not contain a jumbo payload option.
895,897c1022
< sizeof(struct ip6_hdr) +
< sizeof(struct ip6_hbh) +
< opt - opthead);
---
> erroff + opt - opthead);
921,923c1046
< sizeof(struct ip6_hdr) +
< sizeof(struct ip6_hbh) +
< opt + 2 - opthead);
---
> erroff + opt + 2 - opthead);
935,937c1058
< sizeof(struct ip6_hdr) +
< sizeof(struct ip6_hbh) +
< opt + 2 - opthead);
---
> erroff + opt + 2 - opthead);
943,954c1064,1074
< default: /* unknown option */
< if (hbhlen < IP6OPT_MINLEN) {
< ip6stat.ip6s_toosmall++;
< goto bad;
< }
< if ((optlen = ip6_unknown_opt(opt, m,
< sizeof(struct ip6_hdr) +
< sizeof(struct ip6_hbh) +
< opt - opthead)) == -1)
< return(-1);
< optlen += 2;
< break;
---
> default: /* unknown option */
> if (hbhlen < IP6OPT_MINLEN) {
> ip6stat.ip6s_toosmall++;
> goto bad;
> }
> optlen = ip6_unknown_opt(opt, m,
> erroff + opt - opthead);
> if (optlen == -1)
> return(-1);
> optlen += 2;
> break;
979,998c1099,1118
< switch(IP6OPT_TYPE(*optp)) {
< case IP6OPT_TYPE_SKIP: /* ignore the option */
< return((int)*(optp + 1));
< case IP6OPT_TYPE_DISCARD: /* silently discard */
< m_freem(m);
< return(-1);
< case IP6OPT_TYPE_FORCEICMP: /* send ICMP even if multicasted */
< ip6stat.ip6s_badoptions++;
< icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_OPTION, off);
< return(-1);
< case IP6OPT_TYPE_ICMP: /* send ICMP if not multicasted */
< ip6stat.ip6s_badoptions++;
< ip6 = mtod(m, struct ip6_hdr *);
< if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) ||
< (m->m_flags & (M_BCAST|M_MCAST)))
< m_freem(m);
< else
< icmp6_error(m, ICMP6_PARAM_PROB,
< ICMP6_PARAMPROB_OPTION, off);
< return(-1);
---
> switch (IP6OPT_TYPE(*optp)) {
> case IP6OPT_TYPE_SKIP: /* ignore the option */
> return((int)*(optp + 1));
> case IP6OPT_TYPE_DISCARD: /* silently discard */
> m_freem(m);
> return(-1);
> case IP6OPT_TYPE_FORCEICMP: /* send ICMP even if multicasted */
> ip6stat.ip6s_badoptions++;
> icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_OPTION, off);
> return(-1);
> case IP6OPT_TYPE_ICMP: /* send ICMP if not multicasted */
> ip6stat.ip6s_badoptions++;
> ip6 = mtod(m, struct ip6_hdr *);
> if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) ||
> (m->m_flags & (M_BCAST|M_MCAST)))
> m_freem(m);
> else
> icmp6_error(m, ICMP6_PARAM_PROB,
> ICMP6_PARAMPROB_OPTION, off);
> return(-1);
1006a1127
> * The function will not modify mbuf chain at all.
1007a1129
> * with KAME mbuf chain restriction:
1012,1014d1133
< * We may want to add some infinite loop prevention or sanity checks for safety.
< * (This applies only when you are using KAME mbuf chain restriction, i.e.
< * you are using IP6_EXTHDR_CHECK() not m_pulldown())
1018,1021c1137,1140
< register struct in6pcb *in6p;
< register struct mbuf **mp;
< register struct ip6_hdr *ip6;
< register struct mbuf *m;
---
> struct inpcb *in6p;
> struct mbuf **mp;
> struct ip6_hdr *ip6;
> struct mbuf *m;
1024c1143,1144
< int privileged;
---
> int privileged = 0;
> int rthdr_exist = 0;
1026c1146
< privileged = 0;
---
>
1028c1148
< privileged++;
---
> privileged++;
1030c1150,1151
< if (in6p->in6p_socket->so_options & SO_TIMESTAMP) {
---
> #ifdef SO_TIMESTAMP
> if ((in6p->in6p_socket->so_options & SO_TIMESTAMP) != 0) {
1035,1036c1156,1157
< SCM_TIMESTAMP, SOL_SOCKET);
< if (*mp)
---
> SCM_TIMESTAMP, SOL_SOCKET);
> if (*mp) {
1037a1159
> }
1039,1046d1160
<
< #ifdef noyet
< /* options were tossed above */
< if (in6p->in6p_flags & IN6P_RECVOPTS)
< /* broken */
< /* ip6_srcroute doesn't do what we want here, need to fix */
< if (in6p->in6p_flags & IPV6P_RECVRETOPTS)
< /* broken */
1050c1164
< if (in6p->in6p_flags & IN6P_PKTINFO) {
---
> if ((in6p->in6p_flags & IN6P_PKTINFO) != 0) {
1064c1178,1179
< if (in6p->in6p_flags & IN6P_HOPLIMIT) {
---
>
> if ((in6p->in6p_flags & IN6P_HOPLIMIT) != 0) {
1071d1185
< /* IN6P_NEXTHOP - for outgoing packet only */
1079c1193
< if ((in6p->in6p_flags & IN6P_HOPOPTS) && privileged) {
---
> if ((in6p->in6p_flags & IN6P_HOPOPTS) != 0 && privileged) {
1090c1204,1207
< int hbhlen;
---
> int hbhlen = 0;
> #ifdef PULLDOWN_TEST
> struct mbuf *ext;
> #endif
1096,1098c1213,1215
< IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m,
< sizeof(struct ip6_hdr), sizeof(struct ip6_hbh));
< if (hbh == NULL) {
---
> ext = ip6_pullexthdr(m, sizeof(struct ip6_hdr),
> ip6->ip6_nxt);
> if (ext == NULL) {
1101a1219
> hbh = mtod(ext, struct ip6_hbh *);
1103,1105c1221,1222
< IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m,
< sizeof(struct ip6_hdr), hbhlen);
< if (hbh == NULL) {
---
> if (hbhlen != ext->m_len) {
> m_freem(ext);
1115c1232
< * But it's too painful operation...
---
> * Note: this constraint is removed in 2292bis.
1120a1238,1240
> #ifdef PULLDOWN_TEST
> m_freem(ext);
> #endif
1125c1245,1276
< if (in6p->in6p_flags & (IN6P_DSTOPTS | IN6P_RTHDR)) {
---
> if ((in6p->in6p_flags & (IN6P_DSTOPTS | IN6P_RTHDRDSTOPTS)) != 0) {
> int proto, off, nxt;
>
> /*
> * go through the header chain to see if a routing header is
> * contained in the packet. We need this information to store
> * destination options headers (if any) properly.
> * XXX: performance issue. We should record this info when
> * processing extension headers in incoming routine.
> * (todo) use m_aux?
> */
> proto = IPPROTO_IPV6;
> off = 0;
> nxt = -1;
> while (1) {
> int newoff;
>
> newoff = ip6_nexthdr(m, off, proto, &nxt);
> if (newoff < 0)
> break;
> if (newoff < off) /* invalid, check for safety */
> break;
> if ((proto = nxt) == IPPROTO_ROUTING) {
> rthdr_exist = 1;
> break;
> }
> off = newoff;
> }
> }
>
> if ((in6p->in6p_flags &
> (IN6P_RTHDR | IN6P_DSTOPTS | IN6P_RTHDRDSTOPTS)) != 0) {
1127c1278
< int nxt = ip6->ip6_nxt, off = sizeof(struct ip6_hdr);;
---
> int nxt = ip6->ip6_nxt, off = sizeof(struct ip6_hdr);
1136,1137c1287,1288
< while(1) { /* is explicit loop prevention necessary? */
< struct ip6_ext *ip6e;
---
> while (1) { /* is explicit loop prevention necessary? */
> struct ip6_ext *ip6e = NULL;
1138a1290,1292
> #ifdef PULLDOWN_TEST
> struct mbuf *ext = NULL;
> #endif
1139a1294,1307
> /*
> * if it is not an extension header, don't try to
> * pull it from the chain.
> */
> switch (nxt) {
> case IPPROTO_DSTOPTS:
> case IPPROTO_ROUTING:
> case IPPROTO_HOPOPTS:
> case IPPROTO_AH: /* is it possible? */
> break;
> default:
> goto loopend;
> }
>
1140a1309,1310
> if (off + sizeof(*ip6e) > m->m_len)
> goto loopend;
1145a1316,1317
> if (off + elen > m->m_len)
> goto loopend;
1147,1149c1319,1320
< IP6_EXTHDR_GET(ip6e, struct ip6_ext *, m, off,
< sizeof(struct ip6_ext));
< if (ip6e == NULL) {
---
> ext = ip6_pullexthdr(m, off, nxt);
> if (ext == NULL) {
1152a1324
> ip6e = mtod(ext, struct ip6_ext *);
1157,1158c1329,1330
< IP6_EXTHDR_GET(ip6e, struct ip6_ext *, m, off, elen);
< if (ip6e == NULL) {
---
> if (elen != ext->m_len) {
> m_freem(ext);
1164,1167c1336,1339
< switch(nxt) {
< case IPPROTO_DSTOPTS:
< if (!in6p->in6p_flags & IN6P_DSTOPTS)
< break;
---
> switch (nxt) {
> case IPPROTO_DSTOPTS:
> if ((in6p->in6p_flags & IN6P_DSTOPTS) == 0)
> break;
1169,1175c1341,1347
< /*
< * We also require super-user privilege for
< * the option.
< * See the comments on IN6_HOPOPTS.
< */
< if (!privileged)
< break;
---
> /*
> * We also require super-user privilege for
> * the option.
> * See the comments on IN6_HOPOPTS.
> */
> if (!privileged)
> break;
1177,1182c1349,1357
< *mp = sbcreatecontrol((caddr_t)ip6e, elen,
< IPV6_DSTOPTS,
< IPPROTO_IPV6);
< if (*mp)
< mp = &(*mp)->m_next;
< break;
---
> *mp = sbcreatecontrol((caddr_t)ip6e, elen,
> IPV6_DSTOPTS,
> IPPROTO_IPV6);
> if (*mp)
> mp = &(*mp)->m_next;
> break;
> case IPPROTO_ROUTING:
> if (!in6p->in6p_flags & IN6P_RTHDR)
> break;
1184,1186c1359,1367
< case IPPROTO_ROUTING:
< if (!in6p->in6p_flags & IN6P_RTHDR)
< break;
---
> *mp = sbcreatecontrol((caddr_t)ip6e, elen,
> IPV6_RTHDR,
> IPPROTO_IPV6);
> if (*mp)
> mp = &(*mp)->m_next;
> break;
> case IPPROTO_HOPOPTS:
> case IPPROTO_AH: /* is it possible? */
> break;
1188,1193c1369,1379
< *mp = sbcreatecontrol((caddr_t)ip6e, elen,
< IPV6_RTHDR,
< IPPROTO_IPV6);
< if (*mp)
< mp = &(*mp)->m_next;
< break;
---
> default:
> /*
> * other cases have been filtered in the above.
> * none will visit this case. here we supply
> * the code just in case (nxt overwritten or
> * other cases).
> */
> #ifdef PULLDOWN_TEST
> m_freem(ext);
> #endif
> goto loopend;
1195,1207d1380
< case IPPROTO_UDP:
< case IPPROTO_TCP:
< case IPPROTO_ICMPV6:
< default:
< /*
< * stop search if we encounter an upper
< * layer protocol headers.
< */
< goto loopend;
<
< case IPPROTO_HOPOPTS:
< case IPPROTO_AH: /* is it possible? */
< break;
1212a1386,1390
> ip6e = NULL;
> #ifdef PULLDOWN_TEST
> m_freem(ext);
> ext = NULL;
> #endif
1214a1393
> ;
1216,1217c1395,1421
< if ((in6p->in6p_flags & IN6P_HOPOPTS) && privileged) {
< /* to be done */
---
>
> }
>
> #ifdef PULLDOWN_TEST
> /*
> * pull single extension header from mbuf chain. returns single mbuf that
> * contains the result, or NULL on error.
> */
> static struct mbuf *
> ip6_pullexthdr(m, off, nxt)
> struct mbuf *m;
> size_t off;
> int nxt;
> {
> struct ip6_ext ip6e;
> size_t elen;
> struct mbuf *n;
>
> #ifdef DIAGNOSTIC
> switch (nxt) {
> case IPPROTO_DSTOPTS:
> case IPPROTO_ROUTING:
> case IPPROTO_HOPOPTS:
> case IPPROTO_AH: /* is it possible? */
> break;
> default:
> printf("ip6_pullexthdr: invalid nxt=%d\n", nxt);
1219,1220c1423,1437
< if ((in6p->in6p_flags & IN6P_DSTOPTS) && privileged) {
< /* to be done */
---
> #endif
>
> m_copydata(m, off, sizeof(ip6e), (caddr_t)&ip6e);
> if (nxt == IPPROTO_AH)
> elen = (ip6e.ip6e_len + 2) << 2;
> else
> elen = (ip6e.ip6e_len + 1) << 3;
>
> MGET(n, M_DONTWAIT, MT_DATA);
> if (n && elen >= MLEN) {
> MCLGET(n, M_DONTWAIT);
> if ((n->m_flags & M_EXT) == 0) {
> m_free(n);
> n = NULL;
> }
1222c1439,1440
< /* IN6P_RTHDR - to be done */
---
> if (!n)
> return NULL;
1223a1442,1450
> n->m_len = 0;
> if (elen >= M_TRAILINGSPACE(n)) {
> m_free(n);
> return NULL;
> }
>
> m_copydata(m, off, elen, mtod(n, caddr_t));
> n->m_len = elen;
> return n;
1224a1452
> #endif
1256c1484
< switch(nxt) {
---
> switch (nxt) {
1384a1613,1661
> struct mbuf *
> ip6_addaux(m)
> struct mbuf *m;
> {
> struct mbuf *n;
>
> #ifdef DIAGNOSTIC
> if (sizeof(struct ip6aux) > MHLEN)
> panic("assumption failed on sizeof(ip6aux)");
> #endif
> n = m_aux_find(m, AF_INET6, -1);
> if (n) {
> if (n->m_len < sizeof(struct ip6aux)) {
> printf("conflicting use of ip6aux");
> return NULL;
> }
> } else {
> n = m_aux_add(m, AF_INET6, -1);
> n->m_len = sizeof(struct ip6aux);
> bzero(mtod(n, caddr_t), n->m_len);
> }
> return n;
> }
>
> struct mbuf *
> ip6_findaux(m)
> struct mbuf *m;
> {
> struct mbuf *n;
>
> n = m_aux_find(m, AF_INET6, -1);
> if (n && n->m_len < sizeof(struct ip6aux)) {
> printf("conflicting use of ip6aux");
> n = NULL;
> }
> return n;
> }
>
> void
> ip6_delaux(m)
> struct mbuf *m;
> {
> struct mbuf *n;
>
> n = m_aux_find(m, AF_INET6, -1);
> if (n)
> m_aux_delete(m, n);
> }
>