[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.149.4.10 and 1.178.2.8

version 1.149.4.10, 2017/02/05 13:40:59 version 1.178.2.8, 2019/09/17 18:57:23
Line 75  __KERNEL_RCSID(0, "$NetBSD$");
Line 75  __KERNEL_RCSID(0, "$NetBSD$");
   
 #include <sys/param.h>  #include <sys/param.h>
 #include <sys/systm.h>  #include <sys/systm.h>
 #include <sys/malloc.h>  
 #include <sys/mbuf.h>  #include <sys/mbuf.h>
 #include <sys/domain.h>  #include <sys/domain.h>
 #include <sys/protosw.h>  #include <sys/protosw.h>
Line 206  ip6_init(void)
Line 205  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));          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 232  ip6intr(void *arg __unused)
Line 228  ip6intr(void *arg __unused)
 {  {
         struct mbuf *m;          struct mbuf *m;
   
 #ifndef NET_MPSAFE          SOFTNET_KERNEL_LOCK_UNLESS_NET_MPSAFE();
         mutex_enter(softnet_lock);  
 #endif  
         while ((m = pktq_dequeue(ip6_pktq)) != NULL) {          while ((m = pktq_dequeue(ip6_pktq)) != NULL) {
                 struct psref psref;                  struct psref psref;
                 struct ifnet *rcvif = m_get_rcvif_psref(m, &psref);                  struct ifnet *rcvif = m_get_rcvif_psref(m, &psref);
Line 254  ip6intr(void *arg __unused)
Line 248  ip6intr(void *arg __unused)
                 ip6_input(m, rcvif);                  ip6_input(m, rcvif);
                 m_put_rcvif_psref(rcvif, &psref);                  m_put_rcvif_psref(rcvif, &psref);
         }          }
 #ifndef NET_MPSAFE          SOFTNET_KERNEL_UNLOCK_UNLESS_NET_MPSAFE();
         mutex_exit(softnet_lock);  
 #endif  
 }  }
   
 void  void
Line 266  ip6_input(struct mbuf *m, struct ifnet *
Line 258  ip6_input(struct mbuf *m, struct ifnet *
         int hit, off = sizeof(struct ip6_hdr), nest;          int hit, off = sizeof(struct ip6_hdr), nest;
         u_int32_t plen;          u_int32_t plen;
         u_int32_t rtalert = ~0;          u_int32_t rtalert = ~0;
         int nxt, ours = 0, rh_present = 0;          int nxt, ours = 0, rh_present = 0, frg_present;
         struct ifnet *deliverifp = NULL;          struct ifnet *deliverifp = NULL;
         int srcrt = 0;          int srcrt = 0;
         struct rtentry *rt = NULL;          struct rtentry *rt = NULL;
Line 366  ip6_input(struct mbuf *m, struct ifnet *
Line 358  ip6_input(struct mbuf *m, struct ifnet *
                         return;                          return;
                 if (m == NULL)                  if (m == NULL)
                         return;                          return;
                   if (__predict_false(m->m_len < sizeof(struct ip6_hdr))) {
                           if ((m = m_pullup(m, sizeof(struct ip6_hdr))) == NULL) {
                                   IP6_STATINC(IP6_STAT_TOOSMALL);
                                   in6_ifstat_inc(rcvif, ifs6_in_hdrerr);
                                   return;
                           }
                   }
                 ip6 = mtod(m, struct ip6_hdr *);                  ip6 = mtod(m, struct ip6_hdr *);
                 srcrt = !IN6_ARE_ADDR_EQUAL(&odst, &ip6->ip6_dst);                  srcrt = !IN6_ARE_ADDR_EQUAL(&odst, &ip6->ip6_dst);
         }          }
Line 438  ip6_input(struct mbuf *m, struct ifnet *
Line 437  ip6_input(struct mbuf *m, struct ifnet *
          * to the usage conflict.           * to the usage conflict.
          * in6_setscope() then also checks and rejects the cases where src or           * in6_setscope() then also checks and rejects the cases where src or
          * dst are the loopback address and the receiving interface           * dst are the loopback address and the receiving interface
          * is not loopback.           * is not loopback.
          */           */
         if (__predict_false(          if (__predict_false(
             m_makewritable(&m, 0, sizeof(struct ip6_hdr), M_DONTWAIT)))              m_makewritable(&m, 0, sizeof(struct ip6_hdr), M_DONTWAIT)))
Line 459  ip6_input(struct mbuf *m, struct ifnet *
Line 458  ip6_input(struct mbuf *m, struct ifnet *
          * Multicast check           * Multicast check
          */           */
         if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {          if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
                 struct  in6_multi *in6m = 0;                  bool ingroup;
   
                 in6_ifstat_inc(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, rcvif, in6m);                  ingroup = in6_multi_group(&ip6->ip6_dst, rcvif);
                 if (in6m)                  if (ingroup)
                         ours = 1;                          ours = 1;
                 else if (!ip6_mrouter) {                  else if (!ip6_mrouter) {
                         uint64_t *ip6s = IP6_STAT_GETREF();                          uint64_t *ip6s = IP6_STAT_GETREF();
Line 515  ip6_input(struct mbuf *m, struct ifnet *
Line 514  ip6_input(struct mbuf *m, struct ifnet *
 #endif  #endif
             rt->rt_ifp->if_type == IFT_LOOP) {              rt->rt_ifp->if_type == IFT_LOOP) {
                 struct in6_ifaddr *ia6 = (struct in6_ifaddr *)rt->rt_ifa;                  struct in6_ifaddr *ia6 = (struct in6_ifaddr *)rt->rt_ifa;
                   int addrok;
   
                 if (ia6->ia6_flags & IN6_IFF_ANYCAST)                  if (ia6->ia6_flags & IN6_IFF_ANYCAST)
                         m->m_flags |= M_ANYCAST6;                          m->m_flags |= M_ANYCAST6;
                 /*                  /*
                  * 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 | IN6_IFF_DETACHED))) {                  if (ia6->ia6_flags & IN6_IFF_NOTREADY)
                           addrok = 0;
                   else if (ia6->ia6_flags & IN6_IFF_DETACHED &&
                       !IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src))
                   {
                           /* Allow internal traffic to DETACHED addresses */
                           struct sockaddr_in6 sin6;
                           int s;
   
                           memset(&sin6, 0, sizeof(sin6));
                           sin6.sin6_family = AF_INET6;
                           sin6.sin6_len = sizeof(sin6);
                           sin6.sin6_addr = ip6->ip6_src;
                           s = pserialize_read_enter();
                           addrok = (ifa_ifwithaddr(sin6tosa(&sin6)) != NULL);
                           pserialize_read_exit(s);
                   } else
                           addrok = 1;
                   if (addrok) {
                         /* this address is ready */                          /* this address is ready */
                         ours = 1;                          ours = 1;
                         deliverifp = ia6->ia_ifp;       /* correct? */                          deliverifp = ia6->ia_ifp;       /* correct? */
Line 764  ip6_input(struct mbuf *m, struct ifnet *
Line 783  ip6_input(struct mbuf *m, struct ifnet *
         percpu_putref(ip6_forward_rt_percpu);          percpu_putref(ip6_forward_rt_percpu);
   
         rh_present = 0;          rh_present = 0;
           frg_present = 0;
         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);
Line 787  ip6_input(struct mbuf *m, struct ifnet *
Line 807  ip6_input(struct mbuf *m, struct ifnet *
                                 IP6_STATINC(IP6_STAT_BADOPTIONS);                                  IP6_STATINC(IP6_STAT_BADOPTIONS);
                                 goto bad;                                  goto bad;
                         }                          }
                   } else if (nxt == IPPROTO_FRAGMENT) {
                           if (frg_present++) {
                                   in6_ifstat_inc(rcvif, ifs6_in_hdrerr);
                                   IP6_STATINC(IP6_STAT_BADOPTIONS);
                                   goto bad;
                           }
                 }                  }
   
 #ifdef IPSEC  #ifdef IPSEC
Line 800  ip6_input(struct mbuf *m, struct ifnet *
Line 826  ip6_input(struct mbuf *m, struct ifnet *
                             & PR_LASTHDR) != 0) {                              & PR_LASTHDR) != 0) {
                                 int error;                                  int error;
   
                                 SOFTNET_LOCK();  
                                 error = ipsec6_input(m);                                  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;
   
Line 866  ip6_getdstifaddr(struct mbuf *m)
Line 888  ip6_getdstifaddr(struct mbuf *m)
  * rtalertp - XXX: should be stored more smart way   * rtalertp - XXX: should be stored more smart way
  */   */
 int  int
 ip6_hopopts_input(u_int32_t *plenp, u_int32_t *rtalertp,  ip6_hopopts_input(u_int32_t *plenp, u_int32_t *rtalertp,
         struct mbuf **mp, int *offp)          struct mbuf **mp, int *offp)
 {  {
         struct mbuf *m = *mp;          struct mbuf *m = *mp;
Line 911  ip6_hopopts_input(u_int32_t *plenp, u_in
Line 933  ip6_hopopts_input(u_int32_t *plenp, u_in
  * opthead + hbhlen is located in continuous memory region.   * opthead + hbhlen is located in continuous memory region.
  */   */
 static int  static int
 ip6_process_hopopts(struct mbuf *m, u_int8_t *opthead, int hbhlen,  ip6_process_hopopts(struct mbuf *m, u_int8_t *opthead, int hbhlen,
         u_int32_t *rtalertp, u_int32_t *plenp)          u_int32_t *rtalertp, u_int32_t *plenp)
 {  {
         struct ip6_hdr *ip6;          struct ip6_hdr *ip6;
Line 1086  ip6_unknown_opt(u_int8_t *optp, struct m
Line 1108  ip6_unknown_opt(u_int8_t *optp, struct m
  * you are using IP6_EXTHDR_CHECK() not m_pulldown())   * you are using IP6_EXTHDR_CHECK() not m_pulldown())
  */   */
 void  void
 ip6_savecontrol(struct in6pcb *in6p, struct mbuf **mp,  ip6_savecontrol(struct in6pcb *in6p, struct mbuf **mp,
         struct ip6_hdr *ip6, struct mbuf *m)          struct ip6_hdr *ip6, struct mbuf *m)
 {  {
 #ifdef RFC2292  #ifdef RFC2292
Line 1323  ip6_notify_pmtu(struct in6pcb *in6p, con
Line 1345  ip6_notify_pmtu(struct in6pcb *in6p, con
         if (mtu == NULL)          if (mtu == NULL)
                 return;                  return;
   
 #ifdef DIAGNOSTIC          KASSERT(so != NULL);
         if (so == NULL)         /* I believe this is impossible */  
                 panic("ip6_notify_pmtu: socket is NULL");  
 #endif  
   
         memset(&mtuctl, 0, sizeof(mtuctl));     /* zero-clear for safety */          memset(&mtuctl, 0, sizeof(mtuctl));     /* zero-clear for safety */
         mtuctl.ip6m_mtu = *mtu;          mtuctl.ip6m_mtu = *mtu;
Line 1340  ip6_notify_pmtu(struct in6pcb *in6p, con
Line 1359  ip6_notify_pmtu(struct in6pcb *in6p, con
   
         if (sbappendaddr(&so->so_rcv, (const struct sockaddr *)dst, NULL, m_mtu)          if (sbappendaddr(&so->so_rcv, (const struct sockaddr *)dst, NULL, m_mtu)
             == 0) {              == 0) {
                   soroverflow(so);
                 m_freem(m_mtu);                  m_freem(m_mtu);
                 /* XXX: should count statistics */  
         } else          } else
                 sorwakeup(so);                  sorwakeup(so);
   
Line 1400  ip6_pullexthdr(struct mbuf *m, size_t of
Line 1419  ip6_pullexthdr(struct mbuf *m, size_t of
 }  }
   
 /*  /*
  * Get pointer to the previous header followed by the header   * Get offset to the previous header followed by the header
  * currently processed.   * currently processed.
  * XXX: This function supposes that  
  *      M includes all headers,  
  *      the next header field and the header length field of each header  
  *      are valid, and  
  *      the sum of each header length equals to OFF.  
  * Because of these assumptions, this function must be called very  
  * carefully. Moreover, it will not be used in the near future when  
  * we develop `neater' mechanism to process extension headers.  
  */   */
 u_int8_t *  int
 ip6_get_prevhdr(struct mbuf *m, int off)  ip6_get_prevhdr(struct mbuf *m, int off)
 {  {
         struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);          struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
   
         if (off == sizeof(struct ip6_hdr))          if (off == sizeof(struct ip6_hdr)) {
                 return (&ip6->ip6_nxt);                  return offsetof(struct ip6_hdr, ip6_nxt);
         else {          } else if (off < sizeof(struct ip6_hdr)) {
                 int len, nxt;                  panic("%s: off < sizeof(struct ip6_hdr)", __func__);
                 struct ip6_ext *ip6e = NULL;          } else {
                   int len, nlen, nxt;
                   struct ip6_ext ip6e;
   
                 nxt = ip6->ip6_nxt;                  nxt = ip6->ip6_nxt;
                 len = sizeof(struct ip6_hdr);                  len = sizeof(struct ip6_hdr);
                   nlen = 0;
                 while (len < off) {                  while (len < off) {
                         ip6e = (struct ip6_ext *)(mtod(m, char *) + len);                          m_copydata(m, len, sizeof(ip6e), &ip6e);
   
                         switch (nxt) {                          switch (nxt) {
                         case IPPROTO_FRAGMENT:                          case IPPROTO_FRAGMENT:
                                 len += sizeof(struct ip6_frag);                                  nlen = sizeof(struct ip6_frag);
                                 break;                                  break;
                         case IPPROTO_AH:                          case IPPROTO_AH:
                                 len += (ip6e->ip6e_len + 2) << 2;                                  nlen = (ip6e.ip6e_len + 2) << 2;
                                 break;                                  break;
                         default:                          default:
                                 len += (ip6e->ip6e_len + 1) << 3;                                  nlen = (ip6e.ip6e_len + 1) << 3;
                                 break;                                  break;
                         }                          }
                         nxt = ip6e->ip6e_nxt;                          len += nlen;
                           nxt = ip6e.ip6e_nxt;
                 }                  }
                 if (ip6e)  
                         return (&ip6e->ip6e_nxt);                  return (len - nlen);
                 else  
                         return NULL;  
         }          }
 }  }
   

Legend:
Removed from v.1.149.4.10  
changed lines
  Added in v.1.178.2.8

CVSweb <webmaster@jp.NetBSD.org>