[BACK]Return to raw_ip6.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/raw_ip6.c between version 1.72 and 1.72.2.1

version 1.72, 2005/05/29 21:43:51 version 1.72.2.1, 2006/06/21 15:11:09
Line 76  __KERNEL_RCSID(0, "$NetBSD$");
Line 76  __KERNEL_RCSID(0, "$NetBSD$");
 #include <sys/errno.h>  #include <sys/errno.h>
 #include <sys/systm.h>  #include <sys/systm.h>
 #include <sys/proc.h>  #include <sys/proc.h>
   #include <sys/kauth.h>
   
 #include <net/if.h>  #include <net/if.h>
 #include <net/route.h>  #include <net/route.h>
Line 90  __KERNEL_RCSID(0, "$NetBSD$");
Line 91  __KERNEL_RCSID(0, "$NetBSD$");
 #include <netinet6/in6_pcb.h>  #include <netinet6/in6_pcb.h>
 #include <netinet6/nd6.h>  #include <netinet6/nd6.h>
 #include <netinet6/ip6protosw.h>  #include <netinet6/ip6protosw.h>
 #ifdef ENABLE_DEFAULT_SCOPE  
 #include <netinet6/scope6_var.h>  #include <netinet6/scope6_var.h>
 #endif  
 #include <netinet6/raw_ip6.h>  #include <netinet6/raw_ip6.h>
   
 #ifdef IPSEC  #ifdef IPSEC
Line 165  rip6_input(mp, offp, proto)
Line 164  rip6_input(mp, offp, proto)
         bzero(&rip6src, sizeof(rip6src));          bzero(&rip6src, sizeof(rip6src));
         rip6src.sin6_len = sizeof(struct sockaddr_in6);          rip6src.sin6_len = sizeof(struct sockaddr_in6);
         rip6src.sin6_family = AF_INET6;          rip6src.sin6_family = AF_INET6;
         /* KAME hack: recover scopeid */          rip6src.sin6_addr = ip6->ip6_src;
         (void)in6_recoverscope(&rip6src, &ip6->ip6_src, m->m_pkthdr.rcvif);          if (sa6_recoverscope(&rip6src) != 0) {
                   /* XXX: should be impossible. */
                   m_freem(m);
                   return IPPROTO_DONE;
           }
   
         CIRCLEQ_FOREACH(inph, &raw6cbtable.inpt_queue, inph_queue) {          CIRCLEQ_FOREACH(inph, &raw6cbtable.inpt_queue, inph_queue) {
                 in6p = (struct in6pcb *)inph;                  in6p = (struct in6pcb *)inph;
Line 329  rip6_ctlinput(cmd, sa, d)
Line 332  rip6_ctlinput(cmd, sa, d)
                          * address (= s) is really ours.                           * address (= s) is really ours.
                          */                           */
                         in6p = in6_pcblookup_bind(&raw6cbtable,                          in6p = in6_pcblookup_bind(&raw6cbtable,
                             &sa6->sin6_addr, 0, 0))                              &sa6->sin6_addr, 0, 0);
                 }                  }
 #endif  #endif
   
Line 348  rip6_ctlinput(cmd, sa, d)
Line 351  rip6_ctlinput(cmd, sa, d)
   
                 /*                  /*
                  * regardless of if we called icmp6_mtudisc_update(),                   * regardless of if we called icmp6_mtudisc_update(),
                  * we need to call in6_pcbnotify(), to notify path                   * we need to call in6_pcbnotify(), to notify path MTU
                  * MTU change to the userland (2292bis-02), because                   * change to the userland (RFC3542), because some
                  * some unconnected sockets may share the same                   * unconnected sockets may share the same destination
                  * destination and want to know the path MTU.                   * and want to know the path MTU.
                  */                   */
         }          }
   
Line 380  rip6_output(m, va_alist)
Line 383  rip6_output(m, va_alist)
         struct in6pcb *in6p;          struct in6pcb *in6p;
         u_int   plen = m->m_pkthdr.len;          u_int   plen = m->m_pkthdr.len;
         int error = 0;          int error = 0;
         struct ip6_pktopts opt, *optp = NULL, *origoptp;          struct ip6_pktopts opt, *optp = NULL;
         struct ifnet *oifp = NULL;          struct ifnet *oifp = NULL;
         int type, code;         /* for ICMPv6 output statistics only */          int type, code;         /* for ICMPv6 output statistics only */
         int priv = 0;          int priv = 0;
           int scope_ambiguous = 0;
           struct in6_addr *in6a;
         va_list ap;          va_list ap;
         int flags;  
   
         va_start(ap, m);          va_start(ap, m);
         so = va_arg(ap, struct socket *);          so = va_arg(ap, struct socket *);
Line 396  rip6_output(m, va_alist)
Line 400  rip6_output(m, va_alist)
         in6p = sotoin6pcb(so);          in6p = sotoin6pcb(so);
   
         priv = 0;          priv = 0;
     {          if (curproc && !kauth_authorize_generic(curproc->p_cred,
         struct proc *p = curproc;       /* XXX */                                            KAUTH_GENERIC_ISSUSER,
                                             &curproc->p_acflag))
         if (p && !suser(p->p_ucred, &p->p_acflag))  
                 priv = 1;                  priv = 1;
     }  
         dst = &dstsock->sin6_addr;          dst = &dstsock->sin6_addr;
         if (control) {          if (control) {
                 if ((error = ip6_setpktoptions(control, &opt, priv)) != 0)                  if ((error = ip6_setpktopts(control, &opt,
                       in6p->in6p_outputopts,
                       priv, so->so_proto->pr_protocol)) != 0) {
                         goto bad;                          goto bad;
                   }
                 optp = &opt;                  optp = &opt;
         } else          } else
                 optp = in6p->in6p_outputopts;                  optp = in6p->in6p_outputopts;
   
         /*          /*
            * Check and convert scope zone ID into internal form.
            * XXX: we may still need to determine the zone later.
            */
           if (!(so->so_state & SS_ISCONNECTED)) {
                   if (dstsock->sin6_scope_id == 0 && !ip6_use_defzone)
                           scope_ambiguous = 1;
                   if ((error = sa6_embedscope(dstsock, ip6_use_defzone)) != 0)
                           goto bad;
           }
   
           /*
          * For an ICMPv6 packet, we should know its type and code           * For an ICMPv6 packet, we should know its type and code
          * to update statistics.           * to update statistics.
          */           */
Line 441  rip6_output(m, va_alist)
Line 458  rip6_output(m, va_alist)
          */           */
         ip6->ip6_dst = *dst;          ip6->ip6_dst = *dst;
   
         /* KAME hack: embed scopeid */  
         origoptp = in6p->in6p_outputopts;  
         in6p->in6p_outputopts = optp;  
         if (in6_embedscope(&ip6->ip6_dst, dstsock, in6p, &oifp) != 0) {  
                 error = EINVAL;  
                 goto bad;  
         }  
         in6p->in6p_outputopts = origoptp;  
   
         /*          /*
          * Source address selection.           * Source address selection.
          */           */
         {          if ((in6a = in6_selectsrc(dstsock, optp, in6p->in6p_moptions,
                 struct in6_addr *in6a;              &in6p->in6p_route, &in6p->in6p_laddr, &oifp, &error)) == 0) {
                   if (error == 0)
                           error = EADDRNOTAVAIL;
                   goto bad;
           }
           ip6->ip6_src = *in6a;
   
                 if ((in6a = in6_selectsrc(dstsock, optp, in6p->in6p_moptions,          if (oifp && scope_ambiguous) {
                     &in6p->in6p_route, &in6p->in6p_laddr, &error)) == 0) {                  /*
                         if (error == 0)                   * Application should provide a proper zone ID or the use of
                                 error = EADDRNOTAVAIL;                   * default zone IDs should be enabled.  Unfortunately, some
                    * applications do not behave as it should, so we need a
                    * workaround.  Even if an appropriate ID is not determined
                    * (when it's required), if we can determine the outgoing
                    * interface. determine the zone ID based on the interface.
                    */
                   error = in6_setscope(&dstsock->sin6_addr, oifp, NULL);
                   if (error != 0)
                         goto bad;                          goto bad;
                 }  
                 ip6->ip6_src = *in6a;  
                 if (in6p->in6p_route.ro_rt) {  
                         /* what if oifp contradicts ? */  
                         oifp = ifindex2ifnet[in6p->in6p_route.ro_rt->rt_ifp->if_index];  
                 }  
         }          }
           ip6->ip6_dst = dstsock->sin6_addr;
   
           /* fill in the rest of the IPv6 header fields */
         ip6->ip6_flow = in6p->in6p_flowinfo & IPV6_FLOWINFO_MASK;          ip6->ip6_flow = in6p->in6p_flowinfo & IPV6_FLOWINFO_MASK;
         ip6->ip6_vfc  &= ~IPV6_VERSION_MASK;          ip6->ip6_vfc  &= ~IPV6_VERSION_MASK;
         ip6->ip6_vfc  |= IPV6_VERSION;          ip6->ip6_vfc  |= IPV6_VERSION;
 #if 0                           /* ip6_plen will be filled in ip6_output. */          /* ip6_plen will be filled in ip6_output, so not fill it here. */
         ip6->ip6_plen  = htons((u_int16_t)plen);  
 #endif  
         ip6->ip6_nxt   = in6p->in6p_ip6.ip6_nxt;          ip6->ip6_nxt   = in6p->in6p_ip6.ip6_nxt;
         ip6->ip6_hlim = in6_selecthlim(in6p, oifp);          ip6->ip6_hlim = in6_selecthlim(in6p, oifp);
   
Line 510  rip6_output(m, va_alist)
Line 524  rip6_output(m, va_alist)
                 }                  }
         }          }
   
         flags = 0;          error = ip6_output(m, optp, &in6p->in6p_route, 0,
         if (in6p->in6p_flags & IN6P_MINMTU)  
                 flags |= IPV6_MINMTU;  
   
         error = ip6_output(m, optp, &in6p->in6p_route, flags,  
             in6p->in6p_moptions, so, &oifp);              in6p->in6p_moptions, so, &oifp);
         if (so->so_proto->pr_protocol == IPPROTO_ICMPV6) {          if (so->so_proto->pr_protocol == IPPROTO_ICMPV6) {
                 if (oifp)                  if (oifp)
Line 530  rip6_output(m, va_alist)
Line 540  rip6_output(m, va_alist)
                 m_freem(m);                  m_freem(m);
   
  freectl:   freectl:
         if (optp == &opt && optp->ip6po_rthdr && optp->ip6po_route.ro_rt)          if (control) {
                 RTFREE(optp->ip6po_route.ro_rt);                  ip6_clearpktopts(&opt, -1);
         if (control)  
                 m_freem(control);                  m_freem(control);
           }
         return (error);          return (error);
 }  }
   
Line 592  extern u_long rip6_sendspace;
Line 602  extern u_long rip6_sendspace;
 extern  u_long rip6_recvspace;  extern  u_long rip6_recvspace;
   
 int  int
 rip6_usrreq(so, req, m, nam, control, p)  rip6_usrreq(so, req, m, nam, control, l)
         struct socket *so;          struct socket *so;
         int req;          int req;
         struct mbuf *m, *nam, *control;          struct mbuf *m, *nam, *control;
         struct proc *p;          struct lwp *l;
 {  {
         struct in6pcb *in6p = sotoin6pcb(so);          struct in6pcb *in6p = sotoin6pcb(so);
           struct proc *p;
         int s;          int s;
         int error = 0;          int error = 0;
         int priv;          int priv;
   
         priv = 0;          priv = 0;
         if (p && !suser(p->p_ucred, &p->p_acflag))          p = l ? l->l_proc : NULL;
           if (p && !kauth_authorize_generic(p->p_cred, KAUTH_GENERIC_ISSUSER, &p->p_acflag))
                 priv++;                  priv++;
   
         if (req == PRU_CONTROL)          if (req == PRU_CONTROL)
Line 689  rip6_usrreq(so, req, m, nam, control, p)
Line 701  rip6_usrreq(so, req, m, nam, control, p)
                         error = EADDRNOTAVAIL;                          error = EADDRNOTAVAIL;
                         break;                          break;
                 }                  }
 #ifdef ENABLE_DEFAULT_SCOPE                  if ((error = sa6_embedscope(addr, ip6_use_defzone)) != 0)
                 if (addr->sin6_scope_id == 0)   /* not change if specified  */                          break;
                         addr->sin6_scope_id =  
                             scope6_addr2default(&addr->sin6_addr);  
 #endif  
                 /* KAME hack: embed scopeid */  
                 if (in6_embedscope(&addr->sin6_addr, addr, in6p, NULL) != 0)  
                         return EINVAL;  
 #ifndef SCOPEDROUTING  
                 addr->sin6_scope_id = 0; /* for ifa_ifwithaddr */  
 #endif  
   
                 /*                  /*
                  * we don't support mapped address here, it would confuse                   * we don't support mapped address here, it would confuse
Line 728  rip6_usrreq(so, req, m, nam, control, p)
Line 731  rip6_usrreq(so, req, m, nam, control, p)
         {          {
                 struct sockaddr_in6 *addr = mtod(nam, struct sockaddr_in6 *);                  struct sockaddr_in6 *addr = mtod(nam, struct sockaddr_in6 *);
                 struct in6_addr *in6a = NULL;                  struct in6_addr *in6a = NULL;
 #ifdef ENABLE_DEFAULT_SCOPE                  struct ifnet *ifp = NULL;
                 struct sockaddr_in6 sin6;                  int scope_ambiguous = 0;
 #endif  
   
                 if (nam->m_len != sizeof(*addr)) {                  if (nam->m_len != sizeof(*addr)) {
                         error = EINVAL;                          error = EINVAL;
Line 746  rip6_usrreq(so, req, m, nam, control, p)
Line 748  rip6_usrreq(so, req, m, nam, control, p)
                         break;                          break;
                 }                  }
   
 #ifdef ENABLE_DEFAULT_SCOPE                  /*
                 if (addr->sin6_scope_id == 0) {                   * Application should provide a proper zone ID or the use of
                         /* protect *addr */                   * default zone IDs should be enabled.  Unfortunately, some
                         sin6 = *addr;                   * applications do not behave as it should, so we need a
                         addr = &sin6;                   * workaround.  Even if an appropriate ID is not determined,
                         addr->sin6_scope_id =                   * we'll see if we can determine the outgoing interface.  If we
                             scope6_addr2default(&addr->sin6_addr);                   * can, determine the zone ID based on the interface below.
                 }                   */
 #endif                  if (addr->sin6_scope_id == 0 && !ip6_use_defzone)
                           scope_ambiguous = 1;
                   if ((error = sa6_embedscope(addr, ip6_use_defzone)) != 0)
                           return(error);
   
                 /* Source address selection. XXX: need pcblookup? */                  /* Source address selection. XXX: need pcblookup? */
                 in6a = in6_selectsrc(addr, in6p->in6p_outputopts,                  in6a = in6_selectsrc(addr, in6p->in6p_outputopts,
                     in6p->in6p_moptions, &in6p->in6p_route,                      in6p->in6p_moptions, &in6p->in6p_route,
                     &in6p->in6p_laddr, &error);                      &in6p->in6p_laddr, &ifp, &error);
                 if (in6a == NULL) {                  if (in6a == NULL) {
                         if (error == 0)                          if (error == 0)
                                 error = EADDRNOTAVAIL;                                  error = EADDRNOTAVAIL;
                         break;                          break;
                 }                  }
                   /* XXX: see above */
                   if (ifp && scope_ambiguous &&
                       (error = in6_setscope(&addr->sin6_addr, ifp, NULL)) != 0) {
                           break;
                   }
                 in6p->in6p_laddr = *in6a;                  in6p->in6p_laddr = *in6a;
                 in6p->in6p_faddr = addr->sin6_addr;                  in6p->in6p_faddr = addr->sin6_addr;
                 soisconnected(so);                  soisconnected(so);
Line 821  rip6_usrreq(so, req, m, nam, control, p)
Line 831  rip6_usrreq(so, req, m, nam, control, p)
                                 break;                                  break;
                         }                          }
                 }                  }
 #ifdef ENABLE_DEFAULT_SCOPE  
                 if (dst->sin6_scope_id == 0) {  
                         dst->sin6_scope_id =  
                             scope6_addr2default(&dst->sin6_addr);  
                 }  
 #endif  
                 error = rip6_output(m, so, dst, control);                  error = rip6_output(m, so, dst, control);
                 m = NULL;                  m = NULL;
                 break;                  break;
Line 891  SYSCTL_SETUP(sysctl_net_inet6_raw6_setup
Line 895  SYSCTL_SETUP(sysctl_net_inet6_raw6_setup
                        sysctl_inpcblist, 0, &raw6cbtable, 0,                         sysctl_inpcblist, 0, &raw6cbtable, 0,
                        CTL_NET, PF_INET6, IPPROTO_RAW,                         CTL_NET, PF_INET6, IPPROTO_RAW,
                        CTL_CREATE, CTL_EOL);                         CTL_CREATE, CTL_EOL);
           sysctl_createv(clog, 0, NULL, NULL,
                          CTLFLAG_PERMANENT,
                          CTLTYPE_STRUCT, "stats",
                          SYSCTL_DESCR("Raw IPv6 statistics"),
                          NULL, 0, &rip6stat, sizeof(rip6stat),
                          CTL_NET, PF_INET6, IPPROTO_RAW, RAW6CTL_STATS,
                          CTL_EOL);
 }  }

Legend:
Removed from v.1.72  
changed lines
  Added in v.1.72.2.1

CVSweb <webmaster@jp.NetBSD.org>