[BACK]Return to ip6_input.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / netinet6

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/sys/netinet6/ip6_input.c between version 1.157 and 1.169

version 1.157, 2016/04/01 08:12:00 version 1.169, 2016/10/18 07:30:31
Line 70  __KERNEL_RCSID(0, "$NetBSD$");
Line 70  __KERNEL_RCSID(0, "$NetBSD$");
 #include "opt_inet6.h"  #include "opt_inet6.h"
 #include "opt_ipsec.h"  #include "opt_ipsec.h"
 #include "opt_compat_netbsd.h"  #include "opt_compat_netbsd.h"
   #include "opt_net_mpsafe.h"
 #endif  #endif
   
 #include <sys/param.h>  #include <sys/param.h>
Line 87  __KERNEL_RCSID(0, "$NetBSD$");
Line 88  __KERNEL_RCSID(0, "$NetBSD$");
 #include <sys/proc.h>  #include <sys/proc.h>
 #include <sys/sysctl.h>  #include <sys/sysctl.h>
 #include <sys/cprng.h>  #include <sys/cprng.h>
   #include <sys/percpu.h>
   
 #include <net/if.h>  #include <net/if.h>
 #include <net/if_types.h>  #include <net/if_types.h>
Line 133  __KERNEL_RCSID(0, "$NetBSD$");
Line 135  __KERNEL_RCSID(0, "$NetBSD$");
 extern struct domain inet6domain;  extern struct domain inet6domain;
   
 u_char ip6_protox[IPPROTO_MAX];  u_char ip6_protox[IPPROTO_MAX];
 struct in6_ifaddr *in6_ifaddr;  
 pktqueue_t *ip6_pktq __read_mostly;  pktqueue_t *ip6_pktq __read_mostly;
   
 int ip6_forward_srcrt;                  /* XXX */  int ip6_forward_srcrt;                  /* XXX */
Line 144  pfil_head_t *inet6_pfil_hook;
Line 145  pfil_head_t *inet6_pfil_hook;
   
 percpu_t *ip6stat_percpu;  percpu_t *ip6stat_percpu;
   
   percpu_t *ip6_forward_rt_percpu __cacheline_aligned;
   
 static void ip6_init2(void);  static void ip6_init2(void);
 static void ip6intr(void *);  static void ip6intr(void *);
 static struct m_tag *ip6_setdstifaddr(struct mbuf *, const struct in6_ifaddr *);  static struct m_tag *ip6_setdstifaddr(struct mbuf *, const struct in6_ifaddr *);
Line 153  static int ip6_process_hopopts(struct mb
Line 156  static int ip6_process_hopopts(struct mb
 static struct mbuf *ip6_pullexthdr(struct mbuf *, size_t, int);  static struct mbuf *ip6_pullexthdr(struct mbuf *, size_t, int);
 static void sysctl_net_inet6_ip6_setup(struct sysctllog **);  static void sysctl_net_inet6_ip6_setup(struct sysctllog **);
   
   #ifdef NET_MPSAFE
   #define SOFTNET_LOCK()          mutex_enter(softnet_lock)
   #define SOFTNET_UNLOCK()        mutex_exit(softnet_lock)
   #else
   #define SOFTNET_LOCK()          KASSERT(mutex_owned(softnet_lock))
   #define SOFTNET_UNLOCK()        KASSERT(mutex_owned(softnet_lock))
   #endif
   
 /*  /*
  * IP6 initialization: fill in IP6 protocol switch table.   * IP6 initialization: fill in IP6 protocol switch table.
  * All protocols not implemented in kernel go to raw IP6 protocol handler.   * All protocols not implemented in kernel go to raw IP6 protocol handler.
Line 163  ip6_init(void)
Line 174  ip6_init(void)
         const struct ip6protosw *pr;          const struct ip6protosw *pr;
         int i;          int i;
   
           in6_init();
   
         sysctl_net_inet6_ip6_setup(NULL);          sysctl_net_inet6_ip6_setup(NULL);
         pr = (const struct ip6protosw *)pffindproto(PF_INET6, IPPROTO_RAW, SOCK_RAW);          pr = (const struct ip6protosw *)pffindproto(PF_INET6, IPPROTO_RAW, SOCK_RAW);
         if (pr == 0)          if (pr == 0)
Line 193  ip6_init(void)
Line 206  ip6_init(void)
         KASSERT(inet6_pfil_hook != NULL);          KASSERT(inet6_pfil_hook != NULL);
   
         ip6stat_percpu = percpu_alloc(sizeof(uint64_t) * IP6_NSTATS);          ip6stat_percpu = percpu_alloc(sizeof(uint64_t) * IP6_NSTATS);
   
           ip6_forward_rt_percpu = percpu_alloc(sizeof(struct route));
           if (ip6_forward_rt_percpu == NULL)
                   panic("failed to alllocate ip6_forward_rt_percpu");
 }  }
   
 static void  static void
Line 215  ip6intr(void *arg __unused)
Line 232  ip6intr(void *arg __unused)
 {  {
         struct mbuf *m;          struct mbuf *m;
   
   #ifndef NET_MPSAFE
         mutex_enter(softnet_lock);          mutex_enter(softnet_lock);
   #endif
         while ((m = pktq_dequeue(ip6_pktq)) != NULL) {          while ((m = pktq_dequeue(ip6_pktq)) != NULL) {
                 const ifnet_t *ifp = m->m_pkthdr.rcvif;                  struct psref psref;
                   struct ifnet *rcvif = m_get_rcvif_psref(m, &psref);
   
                   if (rcvif == NULL) {
                           m_freem(m);
                           continue;
                   }
                 /*                  /*
                  * Drop the packet if IPv6 is disabled on the interface.                   * Drop the packet if IPv6 is disabled on the interface.
                  */                   */
                 if ((ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED)) {                  if ((ND_IFINFO(rcvif)->flags & ND6_IFF_IFDISABLED)) {
                           m_put_rcvif_psref(rcvif, &psref);
                         m_freem(m);                          m_freem(m);
                         continue;                          continue;
                 }                  }
                 ip6_input(m);                  ip6_input(m, rcvif);
                   m_put_rcvif_psref(rcvif, &psref);
         }          }
   #ifndef NET_MPSAFE
         mutex_exit(softnet_lock);          mutex_exit(softnet_lock);
   #endif
 }  }
   
 extern struct   route ip6_forward_rt;  
   
 void  void
 ip6_input(struct mbuf *m)  ip6_input(struct mbuf *m, struct ifnet *rcvif)
 {  {
         struct ip6_hdr *ip6;          struct ip6_hdr *ip6;
         int hit, off = sizeof(struct ip6_hdr), nest;          int hit, off = sizeof(struct ip6_hdr), nest;
Line 248  ip6_input(struct mbuf *m)
Line 274  ip6_input(struct mbuf *m)
                 struct sockaddr         dst;                  struct sockaddr         dst;
                 struct sockaddr_in6     dst6;                  struct sockaddr_in6     dst6;
         } u;          } u;
           struct route *ro;
   
         /*          /*
          * make sure we don't have onion peering information into m_tag.           * make sure we don't have onion peering information into m_tag.
Line 265  ip6_input(struct mbuf *m)
Line 292  ip6_input(struct mbuf *m)
         } else {          } else {
 #define M2MMAX  32  #define M2MMAX  32
                 if (m->m_next) {                  if (m->m_next) {
                         if (m->m_flags & M_LOOP) {                          if (m->m_flags & M_LOOP)
                         /*XXX*/ IP6_STATINC(IP6_STAT_M2M + lo0ifp->if_index);                          /*XXX*/ IP6_STATINC(IP6_STAT_M2M + lo0ifp->if_index);
                         } else if (m->m_pkthdr.rcvif->if_index < M2MMAX) {                          else if (rcvif->if_index < M2MMAX)
                                 IP6_STATINC(IP6_STAT_M2M +                                  IP6_STATINC(IP6_STAT_M2M + rcvif->if_index);
                                             m->m_pkthdr.rcvif->if_index);                          else
                         } else  
                                 IP6_STATINC(IP6_STAT_M2M);                                  IP6_STATINC(IP6_STAT_M2M);
                 } else                  } else
                         IP6_STATINC(IP6_STAT_M1);                          IP6_STATINC(IP6_STAT_M1);
 #undef M2MMAX  #undef M2MMAX
         }          }
   
         in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_receive);          in6_ifstat_inc(rcvif, ifs6_in_receive);
         IP6_STATINC(IP6_STAT_TOTAL);          IP6_STATINC(IP6_STAT_TOTAL);
   
         /*          /*
Line 287  ip6_input(struct mbuf *m)
Line 313  ip6_input(struct mbuf *m)
          * IPv6 header is in the first mbuf of the chain.           * IPv6 header is in the first mbuf of the chain.
          */           */
         if (IP6_HDR_ALIGNED_P(mtod(m, void *)) == 0) {          if (IP6_HDR_ALIGNED_P(mtod(m, void *)) == 0) {
                 struct ifnet *inifp = m->m_pkthdr.rcvif;  
                 if ((m = m_copyup(m, sizeof(struct ip6_hdr),                  if ((m = m_copyup(m, sizeof(struct ip6_hdr),
                                   (max_linkhdr + 3) & ~3)) == NULL) {                                    (max_linkhdr + 3) & ~3)) == NULL) {
                         /* XXXJRT new stat, please */                          /* XXXJRT new stat, please */
                         IP6_STATINC(IP6_STAT_TOOSMALL);                          IP6_STATINC(IP6_STAT_TOOSMALL);
                         in6_ifstat_inc(inifp, ifs6_in_hdrerr);                          in6_ifstat_inc(rcvif, ifs6_in_hdrerr);
                         return;                          return;
                 }                  }
         } else if (__predict_false(m->m_len < sizeof(struct ip6_hdr))) {          } else if (__predict_false(m->m_len < sizeof(struct ip6_hdr))) {
                 struct ifnet *inifp = m->m_pkthdr.rcvif;  
                 if ((m = m_pullup(m, sizeof(struct ip6_hdr))) == NULL) {                  if ((m = m_pullup(m, sizeof(struct ip6_hdr))) == NULL) {
                         IP6_STATINC(IP6_STAT_TOOSMALL);                          IP6_STATINC(IP6_STAT_TOOSMALL);
                         in6_ifstat_inc(inifp, ifs6_in_hdrerr);                          in6_ifstat_inc(rcvif, ifs6_in_hdrerr);
                         return;                          return;
                 }                  }
         }          }
Line 308  ip6_input(struct mbuf *m)
Line 332  ip6_input(struct mbuf *m)
   
         if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) {          if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) {
                 IP6_STATINC(IP6_STAT_BADVERS);                  IP6_STATINC(IP6_STAT_BADVERS);
                 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr);                  in6_ifstat_inc(rcvif, ifs6_in_hdrerr);
                 goto bad;                  goto bad;
         }          }
   
Line 338  ip6_input(struct mbuf *m)
Line 362  ip6_input(struct mbuf *m)
                 struct in6_addr odst;                  struct in6_addr odst;
   
                 odst = ip6->ip6_dst;                  odst = ip6->ip6_dst;
                 if (pfil_run_hooks(inet6_pfil_hook, &m, m->m_pkthdr.rcvif,                  if (pfil_run_hooks(inet6_pfil_hook, &m, rcvif, PFIL_IN) != 0)
                                    PFIL_IN) != 0)  
                         return;                          return;
                 if (m == NULL)                  if (m == NULL)
                         return;                          return;
Line 350  ip6_input(struct mbuf *m)
Line 373  ip6_input(struct mbuf *m)
         IP6_STATINC(IP6_STAT_NXTHIST + ip6->ip6_nxt);          IP6_STATINC(IP6_STAT_NXTHIST + ip6->ip6_nxt);
   
 #ifdef ALTQ  #ifdef ALTQ
         if (altq_input != NULL && (*altq_input)(m, AF_INET6) == 0) {          if (altq_input != NULL) {
                 /* packet is dropped by traffic conditioner */                  SOFTNET_LOCK();
                 return;                  if ((*altq_input)(m, AF_INET6) == 0) {
                           SOFTNET_UNLOCK();
                           /* packet is dropped by traffic conditioner */
                           return;
                   }
                   SOFTNET_UNLOCK();
         }          }
 #endif  #endif
   
Line 365  ip6_input(struct mbuf *m)
Line 393  ip6_input(struct mbuf *m)
                  * XXX: "badscope" is not very suitable for a multicast source.                   * XXX: "badscope" is not very suitable for a multicast source.
                  */                   */
                 IP6_STATINC(IP6_STAT_BADSCOPE);                  IP6_STATINC(IP6_STAT_BADSCOPE);
                 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);                  in6_ifstat_inc(rcvif, ifs6_in_addrerr);
                 goto bad;                  goto bad;
         }          }
         /*          /*
Line 383  ip6_input(struct mbuf *m)
Line 411  ip6_input(struct mbuf *m)
         if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) ||          if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) ||
             IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)) {              IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)) {
                 IP6_STATINC(IP6_STAT_BADSCOPE);                  IP6_STATINC(IP6_STAT_BADSCOPE);
                 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);                  in6_ifstat_inc(rcvif, ifs6_in_addrerr);
                 goto bad;                  goto bad;
         }          }
 #if 0  #if 0
Line 397  ip6_input(struct mbuf *m)
Line 425  ip6_input(struct mbuf *m)
         if (IN6_IS_ADDR_V4COMPAT(&ip6->ip6_src) ||          if (IN6_IS_ADDR_V4COMPAT(&ip6->ip6_src) ||
             IN6_IS_ADDR_V4COMPAT(&ip6->ip6_dst)) {              IN6_IS_ADDR_V4COMPAT(&ip6->ip6_dst)) {
                 IP6_STATINC(IP6_STAT_BADSCOPE);                  IP6_STATINC(IP6_STAT_BADSCOPE);
                 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);                  in6_ifstat_inc(rcvif, ifs6_in_addrerr);
                 goto bad;                  goto bad;
         }          }
 #endif  #endif
Line 420  ip6_input(struct mbuf *m)
Line 448  ip6_input(struct mbuf *m)
                 IP6_STATINC(IP6_STAT_BADSCOPE); /* XXX */                  IP6_STATINC(IP6_STAT_BADSCOPE); /* XXX */
                 goto bad;                  goto bad;
         }          }
         if (in6_setscope(&ip6->ip6_src, m->m_pkthdr.rcvif, NULL) ||          if (in6_setscope(&ip6->ip6_src, rcvif, NULL) ||
             in6_setscope(&ip6->ip6_dst, m->m_pkthdr.rcvif, NULL)) {              in6_setscope(&ip6->ip6_dst, rcvif, NULL)) {
                 IP6_STATINC(IP6_STAT_BADSCOPE);                  IP6_STATINC(IP6_STAT_BADSCOPE);
                 goto bad;                  goto bad;
         }          }
Line 432  ip6_input(struct mbuf *m)
Line 460  ip6_input(struct mbuf *m)
         if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {          if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
                 struct  in6_multi *in6m = 0;                  struct  in6_multi *in6m = 0;
   
                 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_mcast);                  in6_ifstat_inc(rcvif, ifs6_in_mcast);
                 /*                  /*
                  * See if we belong to the destination multicast group on the                   * See if we belong to the destination multicast group on the
                  * arrival interface.                   * arrival interface.
                  */                   */
                 IN6_LOOKUP_MULTI(ip6->ip6_dst, m->m_pkthdr.rcvif, in6m);                  IN6_LOOKUP_MULTI(ip6->ip6_dst, rcvif, in6m);
                 if (in6m)                  if (in6m)
                         ours = 1;                          ours = 1;
                 else if (!ip6_mrouter) {                  else if (!ip6_mrouter) {
Line 445  ip6_input(struct mbuf *m)
Line 473  ip6_input(struct mbuf *m)
                         ip6s[IP6_STAT_NOTMEMBER]++;                          ip6s[IP6_STAT_NOTMEMBER]++;
                         ip6s[IP6_STAT_CANTFORWARD]++;                          ip6s[IP6_STAT_CANTFORWARD]++;
                         IP6_STAT_PUTREF();                          IP6_STAT_PUTREF();
                         in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);                          in6_ifstat_inc(rcvif, ifs6_in_discard);
                         goto bad;                          goto bad;
                 }                  }
                 deliverifp = m->m_pkthdr.rcvif;                  deliverifp = rcvif;
                 goto hbhcheck;                  goto hbhcheck;
         }          }
   
Line 457  ip6_input(struct mbuf *m)
Line 485  ip6_input(struct mbuf *m)
         /*          /*
          *  Unicast check           *  Unicast check
          */           */
         rt = rtcache_lookup2(&ip6_forward_rt, &u.dst, 1, &hit);          ro = percpu_getref(ip6_forward_rt_percpu);
           rt = rtcache_lookup2(ro, &u.dst, 1, &hit);
           percpu_putref(ip6_forward_rt_percpu);
         if (hit)          if (hit)
                 IP6_STATINC(IP6_STAT_FORWARD_CACHEHIT);                  IP6_STATINC(IP6_STAT_FORWARD_CACHEHIT);
         else          else
Line 476  ip6_input(struct mbuf *m)
Line 506  ip6_input(struct mbuf *m)
          */           */
         if (rt != NULL &&          if (rt != NULL &&
             (rt->rt_flags & (RTF_HOST|RTF_GATEWAY)) == RTF_HOST &&              (rt->rt_flags & (RTF_HOST|RTF_GATEWAY)) == RTF_HOST &&
             !(rt->rt_flags & RTF_CLONED) &&  
 #if 0  #if 0
             /*              /*
              * The check below is redundant since the comparison of               * The check below is redundant since the comparison of
Line 493  ip6_input(struct mbuf *m)
Line 522  ip6_input(struct mbuf *m)
                  * packets to a tentative, duplicated, or somehow invalid                   * packets to a tentative, duplicated, or somehow invalid
                  * address must not be accepted.                   * address must not be accepted.
                  */                   */
                 if (!(ia6->ia6_flags & IN6_IFF_NOTREADY)) {                  if (!(ia6->ia6_flags & (IN6_IFF_NOTREADY | IN6_IFF_DETACHED))) {
                         /* this address is ready */                          /* this address is ready */
                         ours = 1;                          ours = 1;
                         deliverifp = ia6->ia_ifp;       /* correct? */                          deliverifp = ia6->ia_ifp;       /* correct? */
Line 531  ip6_input(struct mbuf *m)
Line 560  ip6_input(struct mbuf *m)
          * working right.           * working right.
          */           */
         struct ifaddr *ifa;          struct ifaddr *ifa;
         IFADDR_FOREACH(ifa, m->m_pkthdr.rcvif) {          IFADDR_READER_FOREACH(ifa, rcvif) {
                 if (ifa->ifa_addr == NULL)  
                         continue;       /* just for safety */  
                 if (ifa->ifa_addr->sa_family != AF_INET6)                  if (ifa->ifa_addr->sa_family != AF_INET6)
                         continue;                          continue;
                 if (IN6_ARE_ADDR_EQUAL(IFA_IN6(ifa), &ip6->ip6_dst)) {                  if (IN6_ARE_ADDR_EQUAL(IFA_IN6(ifa), &ip6->ip6_dst)) {
Line 551  ip6_input(struct mbuf *m)
Line 578  ip6_input(struct mbuf *m)
          */           */
         if (!ip6_forwarding) {          if (!ip6_forwarding) {
                 IP6_STATINC(IP6_STAT_CANTFORWARD);                  IP6_STATINC(IP6_STAT_CANTFORWARD);
                 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);                  in6_ifstat_inc(rcvif, ifs6_in_discard);
                 goto bad;                  goto bad;
         }          }
   
Line 564  ip6_input(struct mbuf *m)
Line 591  ip6_input(struct mbuf *m)
          */           */
         if (deliverifp && ip6_getdstifaddr(m) == NULL) {          if (deliverifp && ip6_getdstifaddr(m) == NULL) {
                 struct in6_ifaddr *ia6;                  struct in6_ifaddr *ia6;
                   int s = pserialize_read_enter();
   
                 ia6 = in6_ifawithifp(deliverifp, &ip6->ip6_dst);                  ia6 = in6_ifawithifp(deliverifp, &ip6->ip6_dst);
                   /* Depends on ip6_setdstifaddr never sleep */
                 if (ia6 != NULL && ip6_setdstifaddr(m, ia6) == NULL) {                  if (ia6 != NULL && ip6_setdstifaddr(m, ia6) == NULL) {
                         /*                          /*
                          * XXX maybe we should drop the packet here,                           * XXX maybe we should drop the packet here,
Line 573  ip6_input(struct mbuf *m)
Line 602  ip6_input(struct mbuf *m)
                          * to the upper layers.                           * to the upper layers.
                          */                           */
                 }                  }
                   pserialize_read_exit(s);
         }          }
   
         /*          /*
Line 586  ip6_input(struct mbuf *m)
Line 616  ip6_input(struct mbuf *m)
   
                 if (ip6_hopopts_input(&plen, &rtalert, &m, &off)) {                  if (ip6_hopopts_input(&plen, &rtalert, &m, &off)) {
 #if 0   /*touches NULL pointer*/  #if 0   /*touches NULL pointer*/
                         in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);                          in6_ifstat_inc(rcvif, ifs6_in_discard);
 #endif  #endif
                         return; /* m have already been freed */                          return; /* m have already been freed */
                 }                  }
Line 606  ip6_input(struct mbuf *m)
Line 636  ip6_input(struct mbuf *m)
                          * (non-zero) payload length to the variable plen.                           * (non-zero) payload length to the variable plen.
                          */                           */
                         IP6_STATINC(IP6_STAT_BADOPTIONS);                          IP6_STATINC(IP6_STAT_BADOPTIONS);
                         in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);                          in6_ifstat_inc(rcvif, ifs6_in_discard);
                         in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr);                          in6_ifstat_inc(rcvif, ifs6_in_hdrerr);
                         icmp6_error(m, ICMP6_PARAM_PROB,                          icmp6_error(m, ICMP6_PARAM_PROB,
                                     ICMP6_PARAMPROB_HEADER,                                      ICMP6_PARAMPROB_HEADER,
                                     (char *)&ip6->ip6_plen - (char *)ip6);                                      (char *)&ip6->ip6_plen - (char *)ip6);
Line 639  ip6_input(struct mbuf *m)
Line 669  ip6_input(struct mbuf *m)
          */           */
         if (m->m_pkthdr.len - sizeof(struct ip6_hdr) < plen) {          if (m->m_pkthdr.len - sizeof(struct ip6_hdr) < plen) {
                 IP6_STATINC(IP6_STAT_TOOSHORT);                  IP6_STATINC(IP6_STAT_TOOSHORT);
                 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated);                  in6_ifstat_inc(rcvif, ifs6_in_truncated);
                 goto bad;                  goto bad;
         }          }
         if (m->m_pkthdr.len > sizeof(struct ip6_hdr) + plen) {          if (m->m_pkthdr.len > sizeof(struct ip6_hdr) + plen) {
Line 662  ip6_input(struct mbuf *m)
Line 692  ip6_input(struct mbuf *m)
                  * ip6_mforward() returns a non-zero value, the packet                   * ip6_mforward() returns a non-zero value, the packet
                  * must be discarded, else it may be accepted below.                   * must be discarded, else it may be accepted below.
                  */                   */
                 if (ip6_mrouter && ip6_mforward(ip6, m->m_pkthdr.rcvif, m)) {                  if (ip6_mrouter != NULL) {
                         IP6_STATINC(IP6_STAT_CANTFORWARD);                          int error;
                         m_freem(m);  
                         return;                          SOFTNET_LOCK();
                           error = ip6_mforward(ip6, rcvif, m);
                           SOFTNET_UNLOCK();
   
                           if (error != 0) {
                                   IP6_STATINC(IP6_STAT_CANTFORWARD);
                                   m_freem(m);
                                   return;
                           }
                 }                  }
                 if (!ours) {                  if (!ours) {
                         m_freem(m);                          m_freem(m);
Line 690  ip6_input(struct mbuf *m)
Line 728  ip6_input(struct mbuf *m)
         if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) ||          if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) ||
             IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)) {              IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)) {
                 IP6_STATINC(IP6_STAT_BADSCOPE);                  IP6_STATINC(IP6_STAT_BADSCOPE);
                 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);                  in6_ifstat_inc(rcvif, ifs6_in_addrerr);
                 goto bad;                  goto bad;
         }          }
   
Line 700  ip6_input(struct mbuf *m)
Line 738  ip6_input(struct mbuf *m)
 #ifdef IFA_STATS  #ifdef IFA_STATS
         if (deliverifp != NULL) {          if (deliverifp != NULL) {
                 struct in6_ifaddr *ia6;                  struct in6_ifaddr *ia6;
                   int s = pserialize_read_enter();
                 ia6 = in6_ifawithifp(deliverifp, &ip6->ip6_dst);                  ia6 = in6_ifawithifp(deliverifp, &ip6->ip6_dst);
                 if (ia6)                  if (ia6)
                         ia6->ia_ifa.ifa_data.ifad_inbytes += m->m_pkthdr.len;                          ia6->ia_ifa.ifa_data.ifad_inbytes += m->m_pkthdr.len;
                   pserialize_read_exit(s);
         }          }
 #endif  #endif
         IP6_STATINC(IP6_STAT_DELIVERED);          IP6_STATINC(IP6_STAT_DELIVERED);
Line 713  ip6_input(struct mbuf *m)
Line 753  ip6_input(struct mbuf *m)
         while (nxt != IPPROTO_DONE) {          while (nxt != IPPROTO_DONE) {
                 if (ip6_hdrnestlimit && (++nest > ip6_hdrnestlimit)) {                  if (ip6_hdrnestlimit && (++nest > ip6_hdrnestlimit)) {
                         IP6_STATINC(IP6_STAT_TOOMANYHDR);                          IP6_STATINC(IP6_STAT_TOOMANYHDR);
                         in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr);                          in6_ifstat_inc(rcvif, ifs6_in_hdrerr);
                         goto bad;                          goto bad;
                 }                  }
   
Line 723  ip6_input(struct mbuf *m)
Line 763  ip6_input(struct mbuf *m)
                  */                   */
                 if (m->m_pkthdr.len < off) {                  if (m->m_pkthdr.len < off) {
                         IP6_STATINC(IP6_STAT_TOOSHORT);                          IP6_STATINC(IP6_STAT_TOOSHORT);
                         in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated);                          in6_ifstat_inc(rcvif, ifs6_in_truncated);
                         goto bad;                          goto bad;
                 }                  }
   
                 if (nxt == IPPROTO_ROUTING) {                  if (nxt == IPPROTO_ROUTING) {
                         if (rh_present++) {                          if (rh_present++) {
                                 in6_ifstat_inc(m->m_pkthdr.rcvif,                                  in6_ifstat_inc(rcvif, ifs6_in_hdrerr);
                                     ifs6_in_hdrerr);  
                                 IP6_STATINC(IP6_STAT_BADOPTIONS);                                  IP6_STATINC(IP6_STAT_BADOPTIONS);
                                 goto bad;                                  goto bad;
                         }                          }
Line 745  ip6_input(struct mbuf *m)
Line 784  ip6_input(struct mbuf *m)
                          */                           */
                         if ((inet6sw[ip_protox[nxt]].pr_flags                          if ((inet6sw[ip_protox[nxt]].pr_flags
                             & PR_LASTHDR) != 0) {                              & PR_LASTHDR) != 0) {
                                 int error = ipsec6_input(m);                                  int error;
   
                                   SOFTNET_LOCK();
                                   error = ipsec6_input(m);
                                   SOFTNET_UNLOCK();
                                 if (error)                                  if (error)
                                         goto bad;                                          goto bad;
                         }                          }
                 }                  }
 #endif /* IPSEC */  #endif /* IPSEC */
   
                   SOFTNET_LOCK();
                 nxt = (*inet6sw[ip6_protox[nxt]].pr_input)(&m, &off, nxt);                  nxt = (*inet6sw[ip6_protox[nxt]].pr_input)(&m, &off, nxt);
                   SOFTNET_UNLOCK();
         }          }
         return;          return;
  bad:   bad:
Line 1063  ip6_savecontrol(struct in6pcb *in6p, str
Line 1108  ip6_savecontrol(struct in6pcb *in6p, str
   
                 memcpy(&pi6.ipi6_addr, &ip6->ip6_dst, sizeof(struct in6_addr));                  memcpy(&pi6.ipi6_addr, &ip6->ip6_dst, sizeof(struct in6_addr));
                 in6_clearscope(&pi6.ipi6_addr); /* XXX */                  in6_clearscope(&pi6.ipi6_addr); /* XXX */
                 pi6.ipi6_ifindex = m->m_pkthdr.rcvif ?                  pi6.ipi6_ifindex = m->m_pkthdr.rcvif_index;
                     m->m_pkthdr.rcvif->if_index : 0;  
                 *mp = sbcreatecontrol((void *) &pi6,                  *mp = sbcreatecontrol((void *) &pi6,
                     sizeof(struct in6_pktinfo),                      sizeof(struct in6_pktinfo),
                     IS2292(IPV6_2292PKTINFO, IPV6_PKTINFO), IPPROTO_IPV6);                      IS2292(IPV6_2292PKTINFO, IPV6_PKTINFO), IPPROTO_IPV6);
Line 1526  ip6_delaux(struct mbuf *m)
Line 1570  ip6_delaux(struct mbuf *m)
                 m_tag_delete(m, mtag);                  m_tag_delete(m, mtag);
 }  }
   
 #ifdef GATEWAY  
 /*  
  * sysctl helper routine for net.inet.ip6.maxflows. Since  
  * we could reduce this value, call ip6flow_reap();  
  */  
 static int  
 sysctl_net_inet6_ip6_maxflows(SYSCTLFN_ARGS)  
 {  
         int error;  
   
         error = sysctl_lookup(SYSCTLFN_CALL(rnode));  
         if (error || newp == NULL)  
                 return (error);  
   
         mutex_enter(softnet_lock);  
         KERNEL_LOCK(1, NULL);  
   
         ip6flow_reap(0);  
   
         KERNEL_UNLOCK_ONE(NULL);  
         mutex_exit(softnet_lock);  
   
         return (0);  
 }  
   
 static int  
 sysctl_net_inet6_ip6_hashsize(SYSCTLFN_ARGS)  
 {  
         int error, tmp;  
         struct sysctlnode node;  
   
         node = *rnode;  
         tmp = ip6_hashsize;  
         node.sysctl_data = &tmp;  
         error = sysctl_lookup(SYSCTLFN_CALL(&node));  
         if (error || newp == NULL)  
                 return (error);  
   
         if ((tmp & (tmp - 1)) == 0 && tmp != 0) {  
                 /*  
                  * Can only fail due to malloc()  
                  */  
                 mutex_enter(softnet_lock);  
                 KERNEL_LOCK(1, NULL);  
   
                 error = ip6flow_invalidate_all(tmp);  
   
                 KERNEL_UNLOCK_ONE(NULL);  
                 mutex_exit(softnet_lock);  
         } else {  
                 /*  
                  * EINVAL if not a power of 2  
                  */  
                 error = EINVAL;  
         }  
   
         return error;  
 }  
 #endif /* GATEWAY */  
   
 /*  /*
  * System control for IP6   * System control for IP6
  */   */
Line 1904  sysctl_net_inet6_ip6_setup(struct sysctl
Line 1888  sysctl_net_inet6_ip6_setup(struct sysctl
                        NULL, 0, &ip6_mcast_pmtu, 0,                         NULL, 0, &ip6_mcast_pmtu, 0,
                        CTL_NET, PF_INET6, IPPROTO_IPV6,                         CTL_NET, PF_INET6, IPPROTO_IPV6,
                        CTL_CREATE, CTL_EOL);                         CTL_CREATE, CTL_EOL);
 #ifdef GATEWAY  
         sysctl_createv(clog, 0, NULL, NULL,  
                         CTLFLAG_PERMANENT|CTLFLAG_READWRITE,  
                         CTLTYPE_INT, "maxflows",  
                         SYSCTL_DESCR("Number of flows for fast forwarding (IPv6)"),  
                         sysctl_net_inet6_ip6_maxflows, 0, &ip6_maxflows, 0,  
                         CTL_NET, PF_INET6, IPPROTO_IPV6,  
                         CTL_CREATE, CTL_EOL);  
         sysctl_createv(clog, 0, NULL, NULL,  
                         CTLFLAG_PERMANENT|CTLFLAG_READWRITE,  
                         CTLTYPE_INT, "hashsize",  
                         SYSCTL_DESCR("Size of hash table for fast forwarding (IPv6)"),  
                         sysctl_net_inet6_ip6_hashsize, 0, &ip6_hashsize, 0,  
                         CTL_NET, PF_INET6, IPPROTO_IPV6,  
                         CTL_CREATE, CTL_EOL);  
 #endif  
         /* anonportalgo RFC6056 subtree */          /* anonportalgo RFC6056 subtree */
         const struct sysctlnode *portalgo_node;          const struct sysctlnode *portalgo_node;
         sysctl_createv(clog, 0, NULL, &portalgo_node,          sysctl_createv(clog, 0, NULL, &portalgo_node,

Legend:
Removed from v.1.157  
changed lines
  Added in v.1.169

CVSweb <webmaster@jp.NetBSD.org>