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

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

Diff for /src/sys/netinet/in_gif.c between version 1.87 and 1.87.8.6

version 1.87, 2017/01/06 03:25:13 version 1.87.8.6, 2019/09/24 18:27:10
Line 67  __KERNEL_RCSID(0, "$NetBSD$");
Line 67  __KERNEL_RCSID(0, "$NetBSD$");
   
 #include <net/net_osdep.h>  #include <net/net_osdep.h>
   
 static int gif_validate4(const struct ip *, struct gif_softc *,  static int gif_validate4(const struct ip *, struct gif_variant *,
         struct ifnet *);          struct ifnet *);
   
 int ip_gif_ttl = GIF_TTL;  int ip_gif_ttl = GIF_TTL;
Line 79  static const struct encapsw in_gif_encap
Line 79  static const struct encapsw in_gif_encap
         }          }
 };  };
   
 int  static int
 in_gif_output(struct ifnet *ifp, int family, struct mbuf *m)  in_gif_output(struct gif_variant *var, int family, struct mbuf *m)
 {  {
         struct rtentry *rt;          struct rtentry *rt;
         struct route *ro;          struct gif_softc *sc;
         struct gif_softc *sc = ifp->if_softc;          struct sockaddr_in *sin_src;
         struct sockaddr_in *sin_src = satosin(sc->gif_psrc);          struct sockaddr_in *sin_dst;
         struct sockaddr_in *sin_dst = satosin(sc->gif_pdst);          struct ifnet *ifp;
           struct route *ro_pc;
           kmutex_t *lock_pc;
         struct ip iphdr;        /* capsule IP header, host byte ordered */          struct ip iphdr;        /* capsule IP header, host byte ordered */
         int proto, error;          int proto, error;
         u_int8_t tos;          u_int8_t tos;
   
           KASSERT(gif_heldref_variant(var));
   
           sin_src = satosin(var->gv_psrc);
           sin_dst = satosin(var->gv_pdst);
           ifp = &var->gv_softc->gif_if;
   
         if (sin_src == NULL || sin_dst == NULL ||          if (sin_src == NULL || sin_dst == NULL ||
             sin_src->sin_family != AF_INET ||              sin_src->sin_family != AF_INET ||
             sin_dst->sin_family != AF_INET) {              sin_dst->sin_family != AF_INET) {
Line 166  in_gif_output(struct ifnet *ifp, int fam
Line 174  in_gif_output(struct ifnet *ifp, int fam
                 return ENOBUFS;                  return ENOBUFS;
         bcopy(&iphdr, mtod(m, struct ip *), sizeof(struct ip));          bcopy(&iphdr, mtod(m, struct ip *), sizeof(struct ip));
   
         ro = percpu_getref(sc->gif_ro_percpu);          sc = var->gv_softc;
         if ((rt = rtcache_lookup(ro, sc->gif_pdst)) == NULL) {          if_tunnel_get_ro(sc->gif_ro_percpu, &ro_pc, &lock_pc);
                 percpu_putref(sc->gif_ro_percpu);          if ((rt = rtcache_lookup(ro_pc, var->gv_pdst)) == NULL) {
                   if_tunnel_put_ro(sc->gif_ro_percpu, lock_pc);
                 m_freem(m);                  m_freem(m);
                 return ENETUNREACH;                  return ENETUNREACH;
         }          }
   
         /* If the route constitutes infinite encapsulation, punt. */          /* If the route constitutes infinite encapsulation, punt. */
         if (rt->rt_ifp == ifp) {          if (rt->rt_ifp == ifp) {
                 rtcache_unref(rt, ro);                  rtcache_unref(rt, ro_pc);
                 rtcache_free(ro);                  rtcache_free(ro_pc);
                 percpu_putref(sc->gif_ro_percpu);                  if_tunnel_put_ro(sc->gif_ro_percpu, lock_pc);
                 m_freem(m);                  m_freem(m);
                 return ENETUNREACH;     /*XXX*/                  return ENETUNREACH;     /*XXX*/
         }          }
         rtcache_unref(rt, ro);          rtcache_unref(rt, ro_pc);
   
         error = ip_output(m, NULL, ro, 0, NULL, NULL);          error = ip_output(m, NULL, ro_pc, 0, NULL, NULL);
         percpu_putref(sc->gif_ro_percpu);          if_tunnel_put_ro(sc->gif_ro_percpu, lock_pc);
         return (error);          return (error);
 }  }
   
 void  void
 in_gif_input(struct mbuf *m, int off, int proto)  in_gif_input(struct mbuf *m, int off, int proto, void *eparg)
 {  {
         struct ifnet *gifp = NULL;          struct gif_softc *sc = eparg;
           struct ifnet *gifp = &sc->gif_if;
         const struct ip *ip;          const struct ip *ip;
         int af;          int af;
         u_int8_t otos;          u_int8_t otos;
   
         ip = mtod(m, const struct ip *);          KASSERT(sc != NULL);
   
         gifp = (struct ifnet *)encap_getarg(m);          ip = mtod(m, const struct ip *);
   
         if (gifp == NULL || (gifp->if_flags & (IFF_UP|IFF_RUNNING))          gifp = &sc->gif_if;
                 != (IFF_UP|IFF_RUNNING)) {          if ((gifp->if_flags & IFF_UP) == 0) {
                 m_freem(m);                  m_freem(m);
                 ip_statinc(IP_STAT_NOGIF);                  ip_statinc(IP_STAT_NOGIF);
                 return;                  return;
         }          }
 #ifndef GIF_ENCAPCHECK  #ifndef GIF_ENCAPCHECK
         struct gif_softc *sc = (struct gif_softc *)gifp->if_softc;          struct psref psref_var;
           struct gif_variant *var = gif_getref_variant(sc, &psref_var);
         /* other CPU do delete_tunnel */          /* other CPU do delete_tunnel */
         if (sc->gif_psrc == NULL || sc->gif_pdst == NULL) {          if (var->gv_psrc == NULL || var->gv_pdst == NULL) {
                   gif_putref_variant(var, &psref_var);
                 m_freem(m);                  m_freem(m);
                 ip_statinc(IP_STAT_NOGIF);                  ip_statinc(IP_STAT_NOGIF);
                 return;                  return;
         }          }
   
         struct ifnet *rcvif;          struct ifnet *rcvif;
         struct psref psref;          struct psref psref_rcvif;
         rcvif = m_get_rcvif_psref(m, &psref);          rcvif = m_get_rcvif_psref(m, &psref_rcvif);
         if (!gif_validate4(ip, sc, rcvif)) {          if (!gif_validate4(ip, var, rcvif)) {
                 m_put_rcvif_psref(rcvif, &psref);                  m_put_rcvif_psref(rcvif, &psref_rcvif);
                   gif_putref_variant(var, &psref_var);
                 m_freem(m);                  m_freem(m);
                 ip_statinc(IP_STAT_NOGIF);                  ip_statinc(IP_STAT_NOGIF);
                 return;                  return;
         }          }
         m_put_rcvif_psref(rcvif, &psref);          m_put_rcvif_psref(rcvif, &psref_rcvif);
           gif_putref_variant(var, &psref_var);
 #endif  #endif
         otos = ip->ip_tos;          otos = ip->ip_tos;
         m_adj(m, off);          m_adj(m, off);
Line 281  in_gif_input(struct mbuf *m, int off, in
Line 295  in_gif_input(struct mbuf *m, int off, in
  * validate outer address.   * validate outer address.
  */   */
 static int  static int
 gif_validate4(const struct ip *ip, struct gif_softc *sc, struct ifnet *ifp)  gif_validate4(const struct ip *ip, struct gif_variant *var, struct ifnet *ifp)
 {  {
         struct sockaddr_in *src, *dst;          struct sockaddr_in *src, *dst;
         struct in_ifaddr *ia4;          int ret;
         int s;  
   
         src = satosin(sc->gif_psrc);          src = satosin(var->gv_psrc);
         dst = satosin(sc->gif_pdst);          dst = satosin(var->gv_pdst);
   
         /* check for address match */          ret = in_tunnel_validate(ip, src->sin_addr, dst->sin_addr);
         if (src->sin_addr.s_addr != ip->ip_dst.s_addr ||          if (ret == 0)
             dst->sin_addr.s_addr != ip->ip_src.s_addr)  
                 return 0;                  return 0;
   
         /* martian filters on outer source - NOT done in ip_input! */  
         if (IN_MULTICAST(ip->ip_src.s_addr))  
                 return 0;  
         switch ((ntohl(ip->ip_src.s_addr) & 0xff000000) >> 24) {  
         case 0: case 127: case 255:  
                 return 0;  
         }  
         /* reject packets with broadcast on source */  
         s = pserialize_read_enter();  
         IN_ADDRLIST_READER_FOREACH(ia4) {  
                 if ((ia4->ia_ifa.ifa_ifp->if_flags & IFF_BROADCAST) == 0)  
                         continue;  
                 if (ip->ip_src.s_addr == ia4->ia_broadaddr.sin_addr.s_addr) {  
                         pserialize_read_exit(s);  
                         return 0;  
                 }  
         }  
         pserialize_read_exit(s);  
   
         /* ingress filters on outer source */          /* ingress filters on outer source */
         if ((sc->gif_if.if_flags & IFF_LINK2) == 0 && ifp) {          if ((var->gv_softc->gif_if.if_flags & IFF_LINK2) == 0 && ifp) {
                 union {                  union {
                         struct sockaddr sa;                          struct sockaddr sa;
                         struct sockaddr_in sin;                          struct sockaddr_in sin;
Line 327  gif_validate4(const struct ip *ip, struc
Line 320  gif_validate4(const struct ip *ip, struc
                 if (rt == NULL || rt->rt_ifp != ifp) {                  if (rt == NULL || rt->rt_ifp != ifp) {
 #if 0  #if 0
                         log(LOG_WARNING, "%s: packet from 0x%x dropped "                          log(LOG_WARNING, "%s: packet from 0x%x dropped "
                             "due to ingress filter\n", if_name(&sc->gif_if),                              "due to ingress filter\n",
                               if_name(&var->gv_softc->gif_if),
                             (u_int32_t)ntohl(u.sin.sin_addr.s_addr));                              (u_int32_t)ntohl(u.sin.sin_addr.s_addr));
 #endif  #endif
                         if (rt != NULL)                          if (rt != NULL)
Line 337  gif_validate4(const struct ip *ip, struc
Line 331  gif_validate4(const struct ip *ip, struc
                 rt_unref(rt);                  rt_unref(rt);
         }          }
   
         return 32 * 2;          return ret;
 }  }
   
 #ifdef GIF_ENCAPCHECK  #ifdef GIF_ENCAPCHECK
Line 346  gif_validate4(const struct ip *ip, struc
Line 340  gif_validate4(const struct ip *ip, struc
  * matched the physical addr family.  see gif_encapcheck().   * matched the physical addr family.  see gif_encapcheck().
  */   */
 int  int
 gif_encapcheck4(struct mbuf *m, int off, int proto, void *arg)  gif_encapcheck4(struct mbuf *m, int off, int proto, struct gif_variant *var)
 {  {
         struct ip ip;          struct ip ip;
         struct gif_softc *sc;  
         struct ifnet *ifp = NULL;          struct ifnet *ifp = NULL;
         int r;          int r;
         struct psref psref;          struct psref psref;
   
         /* sanity check done in caller */  
         sc = arg;  
   
         m_copydata(m, 0, sizeof(ip), &ip);          m_copydata(m, 0, sizeof(ip), &ip);
         if ((m->m_flags & M_PKTHDR) != 0)          if ((m->m_flags & M_PKTHDR) != 0)
                 ifp = m_get_rcvif_psref(m, &psref);                  ifp = m_get_rcvif_psref(m, &psref);
   
         r = gif_validate4(&ip, sc, ifp);          r = gif_validate4(&ip, var, ifp);
   
         m_put_rcvif_psref(ifp, &psref);          m_put_rcvif_psref(ifp, &psref);
         return r;          return r;
Line 369  gif_encapcheck4(struct mbuf *m, int off,
Line 360  gif_encapcheck4(struct mbuf *m, int off,
 #endif  #endif
   
 int  int
 in_gif_attach(struct gif_softc *sc)  in_gif_attach(struct gif_variant *var)
 {  {
 #ifndef GIF_ENCAPCHECK  #ifndef GIF_ENCAPCHECK
         struct sockaddr_in mask4;          struct sockaddr_in mask4;
Line 378  in_gif_attach(struct gif_softc *sc)
Line 369  in_gif_attach(struct gif_softc *sc)
         mask4.sin_len = sizeof(struct sockaddr_in);          mask4.sin_len = sizeof(struct sockaddr_in);
         mask4.sin_addr.s_addr = ~0;          mask4.sin_addr.s_addr = ~0;
   
         if (!sc->gif_psrc || !sc->gif_pdst)          if (!var->gv_psrc || !var->gv_pdst)
                 return EINVAL;                  return EINVAL;
         sc->encap_cookie4 = encap_attach(AF_INET, -1, sc->gif_psrc,          var->gv_encap_cookie4 = encap_attach(AF_INET, -1, var->gv_psrc,
             (struct sockaddr *)&mask4, sc->gif_pdst, (struct sockaddr *)&mask4,              (struct sockaddr *)&mask4, var->gv_pdst, (struct sockaddr *)&mask4,
             &in_gif_encapsw, sc);              &in_gif_encapsw, var->gv_softc);
 #else  #else
         sc->encap_cookie4 = encap_attach_func(AF_INET, -1, gif_encapcheck,          var->gv_encap_cookie4 = encap_attach_func(AF_INET, -1, gif_encapcheck,
             &in_gif_encapsw, sc);              &in_gif_encapsw, var->gv_softc);
 #endif  #endif
         if (sc->encap_cookie4 == NULL)          if (var->gv_encap_cookie4 == NULL)
                 return EEXIST;                  return EEXIST;
         return 0;  
 }  
   
 int  
 in_gif_detach(struct gif_softc *sc)  
 {  
         int error;  
   
         error = in_gif_pause(sc);  
   
         percpu_foreach(sc->gif_ro_percpu, gif_rtcache_free_pc, NULL);  
   
         return error;          var->gv_output = in_gif_output;
           return 0;
 }  }
   
 int  int
 in_gif_pause(struct gif_softc *sc)  in_gif_detach(struct gif_variant *var)
 {  {
         int error;          int error;
           struct gif_softc *sc = var->gv_softc;
   
         error = encap_detach(sc->encap_cookie4);          error = encap_detach(var->gv_encap_cookie4);
         if (error == 0)          if (error == 0)
                 sc->encap_cookie4 = NULL;                  var->gv_encap_cookie4 = NULL;
   
           if_tunnel_ro_percpu_rtcache_free(sc->gif_ro_percpu);
   
         return error;          return error;
 }  }

Legend:
Removed from v.1.87  
changed lines
  Added in v.1.87.8.6

CVSweb <webmaster@jp.NetBSD.org>