[BACK]Return to ip6_forward.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_forward.c between version 1.12 and 1.12.2.13

version 1.12, 2000/06/03 14:36:36 version 1.12.2.13, 2004/04/07 22:33:37
Line 1 
Line 1 
 /*      $NetBSD$        */  /*      $NetBSD$        */
 /*      $KAME: ip6_forward.c,v 1.37 2000/05/28 12:17:19 itojun Exp $    */  /*      $KAME: ip6_forward.c,v 1.56 2000/09/22 04:01:37 itojun Exp $    */
   
 /*  /*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.   * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
Line 30 
Line 30 
  * SUCH DAMAGE.   * SUCH DAMAGE.
  */   */
   
   #include "opt_ipsec.h"
   #include "opt_pfil_hooks.h"
   
 #include <sys/param.h>  #include <sys/param.h>
 #include <sys/systm.h>  #include <sys/systm.h>
 #include <sys/malloc.h>  #include <sys/malloc.h>
Line 44 
Line 47 
   
 #include <net/if.h>  #include <net/if.h>
 #include <net/route.h>  #include <net/route.h>
   #ifdef PFIL_HOOKS
   #include <net/pfil.h>
   #endif
   
 #include <netinet/in.h>  #include <netinet/in.h>
 #include <netinet/in_var.h>  #include <netinet/in_var.h>
Line 52 
Line 58 
 #include <netinet6/ip6_var.h>  #include <netinet6/ip6_var.h>
 #include <netinet/icmp6.h>  #include <netinet/icmp6.h>
 #include <netinet6/nd6.h>  #include <netinet6/nd6.h>
   #include <netinet6/ip6protosw.h>
   
 #ifdef IPSEC_IPV6FWD  #ifdef IPSEC
 #include <netinet6/ipsec.h>  #include <netinet6/ipsec.h>
 #include <netkey/key.h>  #include <netkey/key.h>
 #include <netkey/key_debug.h>  #endif /* IPSEC */
 #endif /* IPSEC_IPV6FWD */  
   
 #ifdef IPV6FIREWALL  #ifdef IPV6FIREWALL
 #include <netinet6/ip6_fw.h>  #include <netinet6/ip6_fw.h>
Line 91  ip6_forward(m, srcrt)
Line 97  ip6_forward(m, srcrt)
         int error, type = 0, code = 0;          int error, type = 0, code = 0;
         struct mbuf *mcopy = NULL;          struct mbuf *mcopy = NULL;
         struct ifnet *origifp;  /* maybe unnecessary */          struct ifnet *origifp;  /* maybe unnecessary */
 #ifdef IPSEC_IPV6FWD  #ifdef PFIL_HOOKS
           struct packet_filter_hook *pfh;
           struct mbuf *m1;
           int rv;
   #endif /* PFIL_HOOKS */
   #ifdef IPSEC
         struct secpolicy *sp = NULL;          struct secpolicy *sp = NULL;
           int ipsecrt = 0;
 #endif  #endif
         long time_second = time.tv_sec;          long time_second = time.tv_sec;
   
 #ifdef IPSEC_IPV6FWD  #ifdef IPSEC
         /*          /*
          * Check AH/ESP integrity.           * Check AH/ESP integrity.
          */           */
Line 109  ip6_forward(m, srcrt)
Line 121  ip6_forward(m, srcrt)
                 m_freem(m);                  m_freem(m);
                 return;                  return;
         }          }
 #endif /*IPSEC_IPV6FWD*/  #endif /*IPSEC*/
   
           /*
            * Do not forward packets to multicast destination (should be handled
            * by ip6_mforward().
            * Do not forward packets with unspecified source.  It was discussed
            * in July 2000, on ipngwg mailing list.
            */
         if ((m->m_flags & (M_BCAST|M_MCAST)) != 0 ||          if ((m->m_flags & (M_BCAST|M_MCAST)) != 0 ||
             IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {              IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) ||
               IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src)) {
                 ip6stat.ip6s_cantforward++;                  ip6stat.ip6s_cantforward++;
                 /* XXX in6_ifstat_inc(rt->rt_ifp, ifs6_in_discard) */                  /* XXX in6_ifstat_inc(rt->rt_ifp, ifs6_in_discard) */
                 if (ip6_log_time + ip6_log_interval < time_second) {                  if (ip6_log_time + ip6_log_interval < time_second) {
Line 148  ip6_forward(m, srcrt)
Line 167  ip6_forward(m, srcrt)
          */           */
         mcopy = m_copy(m, 0, imin(m->m_pkthdr.len, ICMPV6_PLD_MAXLEN));          mcopy = m_copy(m, 0, imin(m->m_pkthdr.len, ICMPV6_PLD_MAXLEN));
   
 #ifdef IPSEC_IPV6FWD  #ifdef IPSEC
         /* get a security policy for this packet */          /* get a security policy for this packet */
         sp = ipsec6_getpolicybyaddr(m, IPSEC_DIR_OUTBOUND, 0, &error);          sp = ipsec6_getpolicybyaddr(m, IPSEC_DIR_OUTBOUND, IP_FORWARDING,
               &error);
         if (sp == NULL) {          if (sp == NULL) {
                 ipsec6stat.out_inval++;                  ipsec6stat.out_inval++;
                 ip6stat.ip6s_cantforward++;                  ip6stat.ip6s_cantforward++;
Line 191  ip6_forward(m, srcrt)
Line 211  ip6_forward(m, srcrt)
                 /* no need to do IPsec. */                  /* no need to do IPsec. */
                 key_freesp(sp);                  key_freesp(sp);
                 goto skip_ipsec;                  goto skip_ipsec;
   
         case IPSEC_POLICY_IPSEC:          case IPSEC_POLICY_IPSEC:
                 if (sp->req == NULL) {                  if (sp->req == NULL) {
                         /* XXX should be panic ? */                          /* XXX should be panic ? */
Line 238  ip6_forward(m, srcrt)
Line 258  ip6_forward(m, srcrt)
         error = ipsec6_output_tunnel(&state, sp, 0);          error = ipsec6_output_tunnel(&state, sp, 0);
   
         m = state.m;          m = state.m;
 #if 0   /* XXX allocate a route (ro, dst) again later */  
         ro = (struct route_in6 *)state.ro;  
         dst = (struct sockaddr_in6 *)state.dst;  
 #endif  
         key_freesp(sp);          key_freesp(sp);
   
         if (error) {          if (error) {
Line 271  ip6_forward(m, srcrt)
Line 287  ip6_forward(m, srcrt)
                 m_freem(m);                  m_freem(m);
                 return;                  return;
         }          }
   
           /* adjust pointer */
           ip6 = mtod(m, struct ip6_hdr *);
           rt = state.ro ? state.ro->ro_rt : NULL;
           dst = (struct sockaddr_in6 *)state.dst;
           if (dst != NULL && rt != NULL)
                   ipsecrt = 1;
     }      }
     skip_ipsec:      skip_ipsec:
 #endif /* IPSEC_IPV6FWD */  
           if (ipsecrt)
                   goto skip_routing;
   #endif /* IPSEC */
   
         dst = &ip6_forward_rt.ro_dst;          dst = &ip6_forward_rt.ro_dst;
         if (!srcrt) {          if (!srcrt) {
Line 289  ip6_forward(m, srcrt)
Line 315  ip6_forward(m, srcrt)
                         /* this probably fails but give it a try again */                          /* this probably fails but give it a try again */
                         rtalloc((struct route *)&ip6_forward_rt);                          rtalloc((struct route *)&ip6_forward_rt);
                 }                  }
   
                 if (ip6_forward_rt.ro_rt == 0) {                  if (ip6_forward_rt.ro_rt == 0) {
                         ip6stat.ip6s_noroute++;                          ip6stat.ip6s_noroute++;
                         /* XXX in6_ifstat_inc(rt->rt_ifp, ifs6_in_noroute) */                          /* XXX in6_ifstat_inc(rt->rt_ifp, ifs6_in_noroute) */
Line 324  ip6_forward(m, srcrt)
Line 350  ip6_forward(m, srcrt)
                 }                  }
         }          }
         rt = ip6_forward_rt.ro_rt;          rt = ip6_forward_rt.ro_rt;
   #ifdef IPSEC
       skip_routing:;
   #endif /* IPSEC */
   
         /*          /*
          * Scope check: if a packet can't be delivered to its destination           * Scope check: if a packet can't be delivered to its destination
Line 333  ip6_forward(m, srcrt)
Line 362  ip6_forward(m, srcrt)
          * [draft-ietf-ipngwg-icmp-v3-00.txt, Section 3.1]           * [draft-ietf-ipngwg-icmp-v3-00.txt, Section 3.1]
          */           */
         if (in6_addr2scopeid(m->m_pkthdr.rcvif, &ip6->ip6_src) !=          if (in6_addr2scopeid(m->m_pkthdr.rcvif, &ip6->ip6_src) !=
             in6_addr2scopeid(rt->rt_ifp, &ip6->ip6_src)) {              in6_addr2scopeid(rt->rt_ifp, &ip6->ip6_src)
   #ifdef IPSEC
               && !ipsecrt
   #endif
               ) {
                 ip6stat.ip6s_cantforward++;                  ip6stat.ip6s_cantforward++;
                 ip6stat.ip6s_badscope++;                  ip6stat.ip6s_badscope++;
                 in6_ifstat_inc(rt->rt_ifp, ifs6_in_discard);                  in6_ifstat_inc(rt->rt_ifp, ifs6_in_discard);
Line 359  ip6_forward(m, srcrt)
Line 392  ip6_forward(m, srcrt)
                 in6_ifstat_inc(rt->rt_ifp, ifs6_in_toobig);                  in6_ifstat_inc(rt->rt_ifp, ifs6_in_toobig);
                 if (mcopy) {                  if (mcopy) {
                         u_long mtu;                          u_long mtu;
 #ifdef IPSEC_IPV6FWD  #ifdef IPSEC
                         struct secpolicy *sp;                          struct secpolicy *sp;
                         int ipsecerror;                          int ipsecerror;
                         size_t ipsechdrsiz;                          size_t ipsechdrsiz;
 #endif  #endif
   
                         mtu = rt->rt_ifp->if_mtu;                          mtu = rt->rt_ifp->if_mtu;
 #ifdef IPSEC_IPV6FWD  #ifdef IPSEC
                         /*                          /*
                          * When we do IPsec tunnel ingress, we need to play                           * When we do IPsec tunnel ingress, we need to play
                          * with if_mtu value (decrement IPsec header size                           * with if_mtu value (decrement IPsec header size
Line 409  ip6_forward(m, srcrt)
Line 442  ip6_forward(m, srcrt)
          * modified by a redirect.           * modified by a redirect.
          */           */
         if (rt->rt_ifp == m->m_pkthdr.rcvif && !srcrt &&          if (rt->rt_ifp == m->m_pkthdr.rcvif && !srcrt &&
             (rt->rt_flags & (RTF_DYNAMIC|RTF_MODIFIED)) == 0)  #ifdef IPSEC
               !ipsecrt &&
   #endif
               (rt->rt_flags & (RTF_DYNAMIC|RTF_MODIFIED)) == 0) {
                   if ((rt->rt_ifp->if_flags & IFF_POINTOPOINT) != 0) {
                           /*
                            * If the incoming interface is equal to the outgoing
                            * one, and the link attached to the interface is
                            * point-to-point, then it will be highly probable
                            * that a routing loop occurs. Thus, we immediately
                            * drop the packet and send an ICMPv6 error message.
                            *
                            * type/code is based on suggestion by Rich Draves.
                            * not sure if it is the best pick.
                            */
                           icmp6_error(mcopy, ICMP6_DST_UNREACH,
                                       ICMP6_DST_UNREACH_ADDR, 0);
                           m_freem(m);
                           return;
                   }
                 type = ND_REDIRECT;                  type = ND_REDIRECT;
           }
   
 #ifdef IPV6FIREWALL  #ifdef IPV6FIREWALL
         /*          /*
Line 443  ip6_forward(m, srcrt)
Line 496  ip6_forward(m, srcrt)
                  *      to a loopback interface? I don't think so, and thus                   *      to a loopback interface? I don't think so, and thus
                  *      I bark here. (jinmei@kame.net)                   *      I bark here. (jinmei@kame.net)
                  * XXX: it is common to route invalid packets to loopback.                   * XXX: it is common to route invalid packets to loopback.
                  *      (itojun)                   *      also, the codepath will be visited on use of ::1 in
                    *      rthdr. (itojun)
                  */                   */
   #if 1
                 if ((rt->rt_flags & (RTF_BLACKHOLE|RTF_REJECT)) == 0) {                  if (0)
   #else
                   if ((rt->rt_flags & (RTF_BLACKHOLE|RTF_REJECT)) == 0)
   #endif
                   {
                         printf("ip6_forward: outgoing interface is loopback. "                          printf("ip6_forward: outgoing interface is loopback. "
                                "src %s, dst %s, nxt %d, rcvif %s, outif %s\n",                                 "src %s, dst %s, nxt %d, rcvif %s, outif %s\n",
                                ip6_sprintf(&ip6->ip6_src),                                 ip6_sprintf(&ip6->ip6_src),
Line 454  ip6_forward(m, srcrt)
Line 512  ip6_forward(m, srcrt)
                                ip6->ip6_nxt, if_name(m->m_pkthdr.rcvif),                                 ip6->ip6_nxt, if_name(m->m_pkthdr.rcvif),
                                if_name(rt->rt_ifp));                                 if_name(rt->rt_ifp));
                 }                  }
   
                 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src))                  if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src))
                         origifp = ifindex2ifnet[ntohs(ip6->ip6_src.s6_addr16[1])];                          origifp = ifindex2ifnet[ntohs(ip6->ip6_src.s6_addr16[1])];
                 else if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst))                  else if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst))
Line 476  ip6_forward(m, srcrt)
Line 534  ip6_forward(m, srcrt)
                         ip6->ip6_dst.s6_addr16[1] = 0;                          ip6->ip6_dst.s6_addr16[1] = 0;
         }          }
   
   #ifdef PFIL_HOOKS
           /*
            * Run through list of hooks for output packets.
            */
           m1 = m;
           pfh = pfil_hook_get(PFIL_OUT,
                   &inet6sw[ip6_protox[IPPROTO_IPV6]].pr_pfh);
           for (; pfh; pfh = pfh->pfil_link.tqe_next)
                   if (pfh->pfil_func) {
                           rv = pfh->pfil_func(ip6, sizeof(*ip6),
                                               rt->rt_ifp, 1, &m1);
                           m = m1;
                           if (m == NULL)
                                   goto freecopy;
                           if (rv) {
                                   error = EHOSTUNREACH;
                                   goto senderr;
                           }
                           ip6 = mtod(m, struct ip6_hdr *);
                   }
   #endif /* PFIL_HOOKS */
   
 #ifdef OLDIP6OUTPUT  #ifdef OLDIP6OUTPUT
         error = (*rt->rt_ifp->if_output)(rt->rt_ifp, m,          error = (*rt->rt_ifp->if_output)(rt->rt_ifp, m,
                                          (struct sockaddr *)dst,                                           (struct sockaddr *)dst,
Line 496  ip6_forward(m, srcrt)
Line 576  ip6_forward(m, srcrt)
                                 goto freecopy;                                  goto freecopy;
                 }                  }
         }          }
   
   #ifdef PFIL_HOOKS
    senderr:
   #endif
         if (mcopy == NULL)          if (mcopy == NULL)
                 return;                  return;
   

Legend:
Removed from v.1.12  
changed lines
  Added in v.1.12.2.13

CVSweb <webmaster@jp.NetBSD.org>