Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. =================================================================== RCS file: /ftp/cvs/cvsroot/src/sys/netinet6/ip6_input.c,v rcsdiff: /ftp/cvs/cvsroot/src/sys/netinet6/ip6_input.c,v: warning: Unknown phrases like `commitid ...;' are present. retrieving revision 1.1.2.2 retrieving revision 1.1.2.3 diff -u -p -r1.1.2.2 -r1.1.2.3 --- src/sys/netinet6/ip6_input.c 1999/07/06 11:03:01 1.1.2.2 +++ src/sys/netinet6/ip6_input.c 1999/11/30 13:35:53 1.1.2.3 @@ -67,6 +67,9 @@ #endif #if (defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined(__NetBSD__) #include "opt_inet.h" +#ifdef __NetBSD__ /*XXX*/ +#include "opt_ipsec.h" +#endif #endif #include @@ -81,7 +84,7 @@ #include #include #include -#ifdef __NetBSD__ +#if !defined(__bsdi__) && !(defined(__FreeBSD__) && __FreeBSD__ < 3) #include #endif @@ -92,38 +95,58 @@ #include #include -#include #include +#ifdef INET +#include +#include +#endif /*INET*/ +#if (defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined(__OpenBSD__) || (defined(__bsdi__) && _BSDI_VERSION >= 199802) +#include +#endif +#include #include -#if !defined(__FreeBSD__) || __FreeBSD__ < 3 +#if !((defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined(__OpenBSD__) || (defined(__bsdi__) && _BSDI_VERSION >= 199802)) #include -#else -#include #endif #include #include #include #include +#include -#ifdef INET -#include -#include -#endif /*INET*/ +#ifdef IPV6FIREWALL +#include +#endif + +#ifdef ALTQ +#include +#endif #include /* we need it for NLOOP. */ +#ifndef __bsdi__ #include "loop.h" +#endif #include "faith.h" #include "gif.h" #include "bpfilter.h" +#include + +#ifdef __OpenBSD__ /*KAME IPSEC*/ +#undef IPSEC +#endif + extern struct domain inet6domain; extern struct ip6protosw inet6sw[]; -#ifdef __bsdi__ +#if (defined(__bsdi__) && _BSDI_VERSION < 199802) || defined(__OpenBSD__) extern struct ifnet loif; #endif +#if defined(__bsdi__) && _BSDI_VERSION >= 199802 +extern struct ifnet *loifp; +#endif u_char ip6_protox[IPPROTO_MAX]; static int ip6qmaxlen = IFQ_MAXLEN; @@ -132,16 +155,29 @@ struct ifqueue ip6intrq; #ifdef __NetBSD__ extern struct ifnet loif[NLOOP]; +#endif int ip6_forward_srcrt; /* XXX */ int ip6_sourcecheck; /* XXX */ int ip6_sourcecheck_interval; /* XXX */ + +#ifdef IPV6FIREWALL +/* firewall hooks */ +ip6_fw_chk_t *ip6_fw_chk_ptr; +ip6_fw_ctl_t *ip6_fw_ctl_ptr; #endif struct ip6stat ip6stat; static void ip6_init2 __P((void *)); -static int ip6_hopopts_input __P((u_int32_t *, long *, struct mbuf **, int *)); +static int ip6_hopopts_input __P((u_int32_t *, u_int32_t *, struct mbuf **, int *)); + +#if defined(PTR) +extern int ip6_protocol_tr; + +int ptr_in6 __P((struct mbuf *, struct mbuf **)); +extern void ip_forward __P((struct mbuf *, int)); +#endif /* * IP6 initialization: fill in IP6 protocol switch table. @@ -167,37 +203,55 @@ ip6_init() ip6intrq.ifq_maxlen = ip6qmaxlen; nd6_init(); frag6_init(); +#ifdef IPV6FIREWALL + ip6_fw_init(); +#endif /* * in many cases, random() here does NOT return random number * as initialization during bootstrap time occur in fixed order. */ microtime(&tv); ip6_flow_seq = random() ^ tv.tv_usec; - in6_iflladdr = malloc(i, M_IFADDR, M_WAITOK); - bzero(in6_iflladdr, i); +#ifndef __FreeBSD__ ip6_init2((void *)0); +#endif } static void ip6_init2(dummy) void *dummy; { +#if !(defined(__bsdi__) || defined(__OpenBSD__)) int i; +#endif + int ret; +#if (defined(__bsdi__) && _BSDI_VERSION < 199802) || defined(__OpenBSD__) + struct ifnet *loifp = &loif; +#endif + + /* get EUI64 from somewhere */ + ret = in6_ifattach_getifid(NULL); /* * to route local address of p2p link to loopback, * assign loopback address first. */ +#if defined(__bsdi__) || defined(__OpenBSD__) + in6_ifattach(loifp, IN6_IFT_LOOP, NULL, 0); +#else for (i = 0; i < NLOOP; i++) in6_ifattach(&loif[i], IN6_IFT_LOOP, NULL, 0); +#endif - /* get EUI64 from somewhere, attach pseudo interfaces */ - if (in6_ifattach_getifid(NULL) == 0) + /* attach pseudo interfaces */ + if (ret == 0) in6_ifattach_p2p(); /* nd6_timer_init */ timeout(nd6_timer, (caddr_t)0, hz); + /* router renumbering prefix list maintenance */ + timeout(in6_rr_timer, (caddr_t)0, hz); } #ifdef __FreeBSD__ @@ -234,11 +288,15 @@ void ip6_input(m) struct mbuf *m; { - register struct ip6_hdr *ip6; + struct ip6_hdr *ip6; int off = sizeof(struct ip6_hdr), nest; u_int32_t plen; - long rtalert = -1; + u_int32_t rtalert = ~0; int nxt, ours = 0; + struct ifnet *deliverifp = NULL; +#if (defined(__bsdi__) && _BSDI_VERSION < 199802) || defined(__OpenBSD__) + struct ifnet *loifp = &loif; +#endif #ifdef IPSEC /* @@ -250,6 +308,7 @@ ip6_input(m) m->m_flags &= ~M_AUTHIPDGM; } #endif + /* * mbuf statistics by kazu */ @@ -260,8 +319,13 @@ ip6_input(m) ip6stat.ip6s_mext1++; } else { if (m->m_next) { - if (m->m_flags & M_LOOP) + if (m->m_flags & M_LOOP) { +#if defined(__bsdi__) || defined(__OpenBSD__) + ip6stat.ip6s_m2m[loifp->if_index]++; /*XXX*/ +#else ip6stat.ip6s_m2m[loif[0].if_index]++; /*XXX*/ +#endif + } else if (m->m_pkthdr.rcvif->if_index <= 31) ip6stat.ip6s_m2m[m->m_pkthdr.rcvif->if_index]++; else @@ -270,40 +334,76 @@ ip6_input(m) ip6stat.ip6s_m1++; } - IP6_EXTHDR_CHECK(m, 0, sizeof(struct ip6_hdr), /*nothing*/); - + in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_receive); ip6stat.ip6s_total++; - if (m->m_len < sizeof(struct ip6_hdr) && - (m = m_pullup(m, sizeof(struct ip6_hdr))) == 0) { - ip6stat.ip6s_toosmall++; - return; +#ifndef PULLDOWN_TEST + /* XXX is the line really necessary? */ + IP6_EXTHDR_CHECK(m, 0, sizeof(struct ip6_hdr), /*nothing*/); +#endif + + if (m->m_len < sizeof(struct ip6_hdr)) { + struct ifnet *inifp; + inifp = m->m_pkthdr.rcvif; + if ((m = m_pullup(m, sizeof(struct ip6_hdr))) == 0) { + ip6stat.ip6s_toosmall++; + in6_ifstat_inc(inifp, ifs6_in_hdrerr); + return; + } } ip6 = mtod(m, struct ip6_hdr *); if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) { ip6stat.ip6s_badvers++; + in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr); goto bad; } ip6stat.ip6s_nxthist[ip6->ip6_nxt]++; +#ifdef IPV6FIREWALL + /* + * Check with the firewall... + */ + if (ip6_fw_chk_ptr) { + u_short port = 0; + /* If ipfw says divert, we have to just drop packet */ + /* use port as a dummy argument */ + if ((*ip6_fw_chk_ptr)(&ip6, NULL, &port, &m)) { + m_freem(m); + m = NULL; + } + if (!m) + return; + } +#endif + +#ifdef ALTQ + if (altq_input != NULL && (*altq_input)(m, AF_INET6) == 0) { + /* packet is dropped by traffic conditioner */ + return; + } +#endif + /* * Scope check */ if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_src) || IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_dst)) { ip6stat.ip6s_badscope++; + in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr); goto bad; } if (IN6_IS_ADDR_LOOPBACK(&ip6->ip6_src) || IN6_IS_ADDR_LOOPBACK(&ip6->ip6_dst)) { if (m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) { ours = 1; + deliverifp = m->m_pkthdr.rcvif; goto hbhcheck; } else { ip6stat.ip6s_badscope++; + in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr); goto bad; } } @@ -311,6 +411,7 @@ ip6_input(m) if (m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) { if (IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_dst)) { ours = 1; + deliverifp = m->m_pkthdr.rcvif; goto hbhcheck; } } else { @@ -322,11 +423,39 @@ ip6_input(m) = htons(m->m_pkthdr.rcvif->if_index); } +#if defined(PTR) + /* + * + */ + if (ip6_protocol_tr) + { + struct mbuf *m1 = NULL; + + switch (ptr_in6(m, &m1)) + { + case IPPROTO_IP: goto mcastcheck; + case IPPROTO_IPV4: ip_forward(m1, 0); break; + case IPPROTO_IPV6: ip6_forward(m1, 0); break; + case IPPROTO_MAX: /* discard this packet */ + default: + } + + if (m != m1) + m_freem(m); + + return; + } + + mcastcheck: +#endif + /* * Multicast check */ if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) { struct in6_multi *in6m = 0; + + in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_mcast); /* * See if we belong to the destination multicast group on the * arrival interface. @@ -337,8 +466,10 @@ ip6_input(m) else if (!ip6_mrouter) { ip6stat.ip6s_notmember++; ip6stat.ip6s_cantforward++; + in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard); goto bad; } + deliverifp = m->m_pkthdr.rcvif; goto hbhcheck; } @@ -388,12 +519,7 @@ ip6_input(m) IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst, &rt6_key(ip6_forward_rt.ro_rt)->sin6_addr) && #endif -#ifdef __bsdi__ - ip6_foward.rt.ro_rt->rt_ifp == &loif -#else - ip6_forward_rt.ro_rt->rt_ifp == &loif[0] -#endif - ) { + ip6_forward_rt.ro_rt->rt_ifp->if_type == IFT_LOOP) { struct in6_ifaddr *ia6 = (struct in6_ifaddr *)ip6_forward_rt.ro_rt->rt_ifa; /* packet to tentative address must not be received */ @@ -402,6 +528,7 @@ ip6_input(m) if (!(ia6->ia6_flags & IN6_IFF_NOTREADY)) { /* this interface is ready */ ours = 1; + deliverifp = ia6->ia_ifp; /* correct? */ goto hbhcheck; } else { /* this interface is not ready, fall through */ @@ -417,17 +544,42 @@ ip6_input(m) && ip6_forward_rt.ro_rt->rt_ifp->if_type == IFT_FAITH) { /* XXX do we need more sanity checks? */ ours = 1; + deliverifp = ip6_forward_rt.ro_rt->rt_ifp; /*faith*/ goto hbhcheck; } } #endif +#ifdef __OpenBSD__ + { + /* + * Last resort: check in6_ifaddr for incoming interface. + * The code is here until I update the "goto ours hack" code above + * working right. + */ + struct ifaddr *ifa; + for (ifa = m->m_pkthdr.rcvif->if_addrlist.tqh_first; + ifa; + ifa = ifa->ifa_list.tqe_next) { + if (ifa->ifa_addr == NULL) + continue; /* just for safety */ + if (ifa->ifa_addr->sa_family != AF_INET6) + continue; + if (IN6_ARE_ADDR_EQUAL(IFA_IN6(ifa), &ip6->ip6_dst)) { + ours = 1; + deliverifp = ifa->ifa_ifp; + goto hbhcheck; + } + } + } +#endif /* * Now there is no reason to process the packet if it's not our own * and we're not a router. */ if (!ip6_forwarding) { ip6stat.ip6s_cantforward++; + in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard); goto bad; } @@ -439,17 +591,34 @@ ip6_input(m) */ plen = (u_int32_t)ntohs(ip6->ip6_plen); if (ip6->ip6_nxt == IPPROTO_HOPOPTS) { - if (ip6_hopopts_input(&plen, &rtalert, &m, &off)) + struct ip6_hbh *hbh; + + if (ip6_hopopts_input(&plen, &rtalert, &m, &off)) { +#if 0 /*touches NULL pointer*/ + in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard); +#endif return; /* m have already been freed */ + } /* adjust pointer */ ip6 = mtod(m, struct ip6_hdr *); - nxt = ((struct ip6_hbh *)(ip6 + 1))->ip6h_nxt; +#ifndef PULLDOWN_TEST + /* ip6_hopopts_input() ensures that mbuf is contiguous */ + hbh = (struct ip6_hbh *)(ip6 + 1); +#else + IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m, sizeof(struct ip6_hdr), + sizeof(struct ip6_hbh)); + if (hbh == NULL) { + ip6stat.ip6s_tooshort++; + return; + } +#endif + nxt = hbh->ip6h_nxt; /* * accept the packet if a router alert option is included * and we act as an IPv6 router. */ - if (rtalert >= 0 && ip6_forwarding) + if (rtalert != ~0 && ip6_forwarding) ours = 1; } else nxt = ip6->ip6_nxt; @@ -462,6 +631,7 @@ ip6_input(m) */ if (m->m_pkthdr.len - sizeof(struct ip6_hdr) < plen) { ip6stat.ip6s_tooshort++; + in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated); goto bad; } if (m->m_pkthdr.len > sizeof(struct ip6_hdr) + plen) { @@ -502,13 +672,34 @@ ip6_input(m) /* * Tell launch routine the next header */ +#if defined(__NetBSD__) && defined(IFA_STATS) + if (IFA_STATS && deliverifp != NULL) { + struct in6_ifaddr *ia6; + ip6 = mtod(m, struct ip6_hdr *); + ia6 = in6_ifawithifp(deliverifp, &ip6->ip6_dst); + if (ia6) + ia6->ia_ifa.ifa_data.ifad_inbytes += m->m_pkthdr.len; + } +#endif ip6stat.ip6s_delivered++; + in6_ifstat_inc(deliverifp, ifs6_in_deliver); nest = 0; while (nxt != IPPROTO_DONE) { if (ip6_hdrnestlimit && (++nest > ip6_hdrnestlimit)) { ip6stat.ip6s_toomanyhdr++; goto bad; } + + /* + * protection against faulty packet - there should be + * more sanity checks in header chain processing. + */ + if (m->m_pkthdr.len < off) { + ip6stat.ip6s_tooshort++; + in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated); + goto bad; + } + nxt = (*inet6sw[ip6_protox[nxt]].pr_input)(&m, &off, nxt); } return; @@ -523,7 +714,7 @@ ip6_input(m) static int ip6_hopopts_input(plenp, rtalertp, mp, offp) u_int32_t *plenp; - long *rtalertp; /* XXX: should be stored more smart way */ + u_int32_t *rtalertp; /* XXX: should be stored more smart way */ struct mbuf **mp; int *offp; { @@ -533,12 +724,28 @@ ip6_hopopts_input(plenp, rtalertp, mp, o u_int8_t *opt; /* validation of the length of the header */ +#ifndef PULLDOWN_TEST IP6_EXTHDR_CHECK(m, off, sizeof(*hbh), -1); hbh = (struct ip6_hbh *)(mtod(m, caddr_t) + off); hbhlen = (hbh->ip6h_len + 1) << 3; IP6_EXTHDR_CHECK(m, off, hbhlen, -1); hbh = (struct ip6_hbh *)(mtod(m, caddr_t) + off); +#else + IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m, + sizeof(struct ip6_hdr), sizeof(struct ip6_hbh)); + if (hbh == NULL) { + ip6stat.ip6s_tooshort++; + return -1; + } + hbhlen = (hbh->ip6h_len + 1) << 3; + IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m, sizeof(struct ip6_hdr), + hbhlen); + if (hbh == NULL) { + ip6stat.ip6s_tooshort++; + return -1; + } +#endif off += hbhlen; hbhlen -= sizeof(struct ip6_hbh); opt = (u_int8_t *)hbh + sizeof(struct ip6_hbh); @@ -563,7 +770,7 @@ ip6_process_hopopts(m, opthead, hbhlen, struct mbuf *m; u_int8_t *opthead; int hbhlen; - long *rtalertp; + u_int32_t *rtalertp; u_int32_t *plenp; { struct ip6_hdr *ip6; @@ -584,6 +791,7 @@ ip6_process_hopopts(m, opthead, hbhlen, optlen = *(opt + 1) + 2; break; case IP6OPT_RTALERT: + /* XXX may need check for alignment */ if (hbhlen < IP6OPT_RTALERT_LEN) { ip6stat.ip6s_toosmall++; goto bad; @@ -597,6 +805,7 @@ ip6_process_hopopts(m, opthead, hbhlen, *rtalertp = ntohs(rtalert_val); break; case IP6OPT_JUMBO: + /* XXX may need check for alignment */ if (hbhlen < IP6OPT_JUMBO_LEN) { ip6stat.ip6s_toosmall++; goto bad; @@ -612,7 +821,12 @@ ip6_process_hopopts(m, opthead, hbhlen, * We can simply cast because of the alignment * requirement of the jumbo payload option. */ +#if 0 *plenp = ntohl(*(u_int32_t *)(opt + 2)); +#else + bcopy(opt + 2, plenp, sizeof(*plenp)); + *plenp = htonl(*plenp); +#endif if (*plenp <= IPV6_MAXPACKET) { /* * jumbo payload length must be larger @@ -705,22 +919,53 @@ ip6_unknown_opt(optp, m, off) } /* - * Create the "control" list for this pcb + * Create the "control" list for this pcb. + * + * The routine will be called from upper layer handlers like tcp6_input(). + * Thus the routine assumes that the caller (tcp6_input) have already + * called IP6_EXTHDR_CHECK() and all the extension headers are located in the + * very first mbuf on the mbuf chain. + * 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()) */ void ip6_savecontrol(in6p, mp, ip6, m) +#if (defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined(HAVE_NRL_INPCB) + register struct inpcb *in6p; +#else register struct in6pcb *in6p; +#endif register struct mbuf **mp; register struct ip6_hdr *ip6; register struct mbuf *m; { -#ifdef __NetBSD__ +#ifdef HAVE_NRL_INPCB +# define in6p_flags inp_flags +#endif +#if defined(__NetBSD__) || (defined(__FreeBSD__) && __FreeBSD__ >= 3) struct proc *p = curproc; /* XXX */ #endif #ifdef __bsdi__ # define sbcreatecontrol so_cmsg #endif + int privileged; + privileged = 0; +#if defined(__NetBSD__) || (defined(__FreeBSD__) && __FreeBSD__ >= 3) + if (p && !suser(p->p_ucred, &p->p_acflag)) + privileged++; +#else +#ifdef HAVE_NRL_INPCB + if ((in6p->inp_socket->so_state & SS_PRIV) != 0) + privileged++; +#else + if ((in6p->in6p_socket->so_state & SS_PRIV) != 0) + privileged++; +#endif +#endif + +#ifdef SO_TIMESTAMP if (in6p->in6p_socket->so_options & SO_TIMESTAMP) { struct timeval tv; @@ -730,6 +975,7 @@ ip6_savecontrol(in6p, mp, ip6, m) if (*mp) mp = &(*mp)->m_next; } +#endif if (in6p->in6p_flags & IN6P_RECVDSTADDR) { *mp = sbcreatecontrol((caddr_t) &ip6->ip6_dst, sizeof(struct in6_addr), IPV6_RECVDSTADDR, @@ -777,8 +1023,7 @@ ip6_savecontrol(in6p, mp, ip6, m) * be some hop-by-hop options which can be returned to normal user. * See RFC 2292 section 6. */ - if ((in6p->in6p_flags & IN6P_HOPOPTS) && - p && !suser(p->p_ucred, &p->p_acflag)) { + if ((in6p->in6p_flags & IN6P_HOPOPTS) && privileged) { /* * Check if a hop-by-hop options header is contatined in the * received packet, and if so, store the options as ancillary @@ -788,7 +1033,27 @@ ip6_savecontrol(in6p, mp, ip6, m) */ struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); if (ip6->ip6_nxt == IPPROTO_HOPOPTS) { - struct ip6_hbh *hbh = (struct ip6_hbh *)(ip6 + 1); + struct ip6_hbh *hbh; + int hbhlen; + +#ifndef PULLDOWN_TEST + hbh = (struct ip6_hbh *)(ip6 + 1); + hbhlen = (hbh->ip6h_len + 1) << 3; +#else + IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m, + sizeof(struct ip6_hdr), sizeof(struct ip6_hbh)); + if (hbh == NULL) { + ip6stat.ip6s_tooshort++; + return; + } + hbhlen = (hbh->ip6h_len + 1) << 3; + IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m, + sizeof(struct ip6_hdr), hbhlen); + if (hbh == NULL) { + ip6stat.ip6s_tooshort++; + return; + } +#endif /* * XXX: We copy whole the header even if a jumbo @@ -796,8 +1061,7 @@ ip6_savecontrol(in6p, mp, ip6, m) * be removed before returning in the RFC 2292. * But it's too painful operation... */ - *mp = sbcreatecontrol((caddr_t)hbh, - (hbh->ip6h_len + 1) << 3, + *mp = sbcreatecontrol((caddr_t)hbh, hbhlen, IPV6_HOPOPTS, IPPROTO_IPV6); if (*mp) mp = &(*mp)->m_next; @@ -817,8 +1081,32 @@ ip6_savecontrol(in6p, mp, ip6, m) * the chain of ancillary data. */ while(1) { /* is explicit loop prevention necessary? */ - struct ip6_ext *ip6e = - (struct ip6_ext *)(mtod(m, caddr_t) + off); + struct ip6_ext *ip6e; + int elen; + +#ifndef PULLDOWN_TEST + ip6e = (struct ip6_ext *)(mtod(m, caddr_t) + off); + if (nxt == IPPROTO_AH) + elen = (ip6e->ip6e_len + 2) << 2; + else + elen = (ip6e->ip6e_len + 1) << 3; +#else + IP6_EXTHDR_GET(ip6e, struct ip6_ext *, m, off, + sizeof(struct ip6_ext)); + if (ip6e == NULL) { + ip6stat.ip6s_tooshort++; + return; + } + if (nxt == IPPROTO_AH) + elen = (ip6e->ip6e_len + 2) << 2; + else + elen = (ip6e->ip6e_len + 1) << 3; + IP6_EXTHDR_GET(ip6e, struct ip6_ext *, m, off, elen); + if (ip6e == NULL) { + ip6stat.ip6s_tooshort++; + return; + } +#endif switch(nxt) { case IPPROTO_DSTOPTS: @@ -830,11 +1118,10 @@ ip6_savecontrol(in6p, mp, ip6, m) * the option. * See the comments on IN6_HOPOPTS. */ - if (!p || !suser(p->p_ucred, &p->p_acflag)) + if (!privileged) break; - *mp = sbcreatecontrol((caddr_t)ip6e, - (ip6e->ip6e_len + 1) << 3, + *mp = sbcreatecontrol((caddr_t)ip6e, elen, IPV6_DSTOPTS, IPPROTO_IPV6); if (*mp) @@ -845,8 +1132,7 @@ ip6_savecontrol(in6p, mp, ip6, m) if (!in6p->in6p_flags & IN6P_RTHDR) break; - *mp = sbcreatecontrol((caddr_t)ip6e, - (ip6e->ip6e_len + 1) << 3, + *mp = sbcreatecontrol((caddr_t)ip6e, elen, IPV6_RTHDR, IPPROTO_IPV6); if (*mp) @@ -869,20 +1155,15 @@ ip6_savecontrol(in6p, mp, ip6, m) } /* proceed with the next header. */ - if (nxt == IPPROTO_AH) - off += (ip6e->ip6e_len + 2) << 2; - else - off += (ip6e->ip6e_len + 1) << 3; + off += elen; nxt = ip6e->ip6e_nxt; } loopend: } - if ((in6p->in6p_flags & IN6P_HOPOPTS) - && p && !suser(p->p_ucred, &p->p_acflag)) { + if ((in6p->in6p_flags & IN6P_HOPOPTS) && privileged) { /* to be done */ } - if ((in6p->in6p_flags & IN6P_DSTOPTS) - && p && !suser(p->p_ucred, &p->p_acflag)) { + if ((in6p->in6p_flags & IN6P_DSTOPTS) && privileged) { /* to be done */ } /* IN6P_RTHDR - to be done */ @@ -890,6 +1171,9 @@ ip6_savecontrol(in6p, mp, ip6, m) #ifdef __bsdi__ # undef sbcreatecontrol #endif +#ifdef __OpenBSD__ +# undef in6p_flags +#endif } /* @@ -955,7 +1239,7 @@ u_char inet6ctlerrmap[PRC_NCMDS] = { ENOPROTOOPT }; -#ifdef __NetBSD__ +#if defined(__NetBSD__) || defined(__OpenBSD__) #include #include @@ -1009,9 +1293,40 @@ ip6_sysctl(name, namelen, oldp, oldlenp, &ip6_gif_hlim); case IPV6CTL_KAME_VERSION: return sysctl_rdstring(oldp, oldlenp, newp, __KAME_VERSION); + case IPV6CTL_USE_DEPRECATED: + return sysctl_int(oldp, oldlenp, newp, newlen, + &ip6_use_deprecated); default: return EOPNOTSUPP; } /* NOTREACHED */ } -#endif /* __NetBSD__ */ +#endif /* __NetBSD__ || __OpenBSD__ */ + +#ifdef __bsdi__ +int *ip6_sysvars[] = IPV6CTL_VARS; + +int +ip6_sysctl(name, namelen, oldp, oldlenp, newp, newlen) + int *name; + u_int namelen; + void *oldp; + size_t *oldlenp; + void *newp; + size_t newlen; +{ + if (name[0] >= IPV6CTL_MAXID) + return (EOPNOTSUPP); + + switch (name[0]) { + case IPV6CTL_STATS: + return sysctl_rdtrunc(oldp, oldlenp, newp, &ip6stat, + sizeof(ip6stat)); + case IPV6CTL_KAME_VERSION: + return sysctl_rdstring(oldp, oldlenp, newp, __KAME_VERSION); + default: + return (sysctl_int_arr(ip6_sysvars, name, namelen, + oldp, oldlenp, newp, newlen)); + } +} +#endif /* __bsdi__ */