[BACK]Return to ip6_output.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_output.c between version 1.159 and 1.160

version 1.159, 2014/10/11 20:53:16 version 1.160, 2014/10/12 19:00:21
Line 123  static int ip6_pcbopt(int, u_char *, int
Line 123  static int ip6_pcbopt(int, u_char *, int
 static int ip6_getpcbopt(struct ip6_pktopts *, int, struct sockopt *);  static int ip6_getpcbopt(struct ip6_pktopts *, int, struct sockopt *);
 static int ip6_setpktopt(int, u_char *, int, struct ip6_pktopts *, kauth_cred_t,  static int ip6_setpktopt(int, u_char *, int, struct ip6_pktopts *, kauth_cred_t,
         int, int, int);          int, int, int);
 static int ip6_setmoptions(const struct sockopt *, struct ip6_moptions **);  static int ip6_setmoptions(const struct sockopt *, struct in6pcb *);
 static int ip6_getmoptions(struct sockopt *, struct ip6_moptions *);  static int ip6_getmoptions(struct sockopt *, struct in6pcb *);
 static int ip6_copyexthdr(struct mbuf **, void *, int);  static int ip6_copyexthdr(struct mbuf **, void *, int);
 static int ip6_insertfraghdr(struct mbuf *, struct mbuf *, int,  static int ip6_insertfraghdr(struct mbuf *, struct mbuf *, int,
         struct ip6_frag **);          struct ip6_frag **);
Line 1636  else      \
Line 1636  else      \
                 case IPV6_MULTICAST_LOOP:                  case IPV6_MULTICAST_LOOP:
                 case IPV6_JOIN_GROUP:                  case IPV6_JOIN_GROUP:
                 case IPV6_LEAVE_GROUP:                  case IPV6_LEAVE_GROUP:
                         error = ip6_setmoptions(sopt, &in6p->in6p_moptions);                          error = ip6_setmoptions(sopt, in6p);
                         break;                          break;
   
                 case IPV6_PORTRANGE:                  case IPV6_PORTRANGE:
Line 1860  else      \
Line 1860  else      \
                 case IPV6_MULTICAST_LOOP:                  case IPV6_MULTICAST_LOOP:
                 case IPV6_JOIN_GROUP:                  case IPV6_JOIN_GROUP:
                 case IPV6_LEAVE_GROUP:                  case IPV6_LEAVE_GROUP:
                         error = ip6_getmoptions(sopt, in6p->in6p_moptions);                          error = ip6_getmoptions(sopt, in6p);
                         break;                          break;
   
                 case IPV6_PORTALGO:                  case IPV6_PORTALGO:
Line 2267  ip6_freepcbopts(struct ip6_pktopts *pkto
Line 2267  ip6_freepcbopts(struct ip6_pktopts *pkto
         free(pktopt, M_IP6OPT);          free(pktopt, M_IP6OPT);
 }  }
   
   int
   ip6_get_membership(const struct sockopt *sopt, struct ifnet **ifp, void *v,
       size_t l)
   {
           struct ipv6_mreq mreq;
           int error;
           struct in6_addr *ia = &mreq.ipv6mr_multiaddr;
           struct in_addr *ia4 = (void *)&ia->s6_addr32[3];
           error = sockopt_get(sopt, &mreq, sizeof(mreq));
           if (error != 0)
                   return error;
   
           if (IN6_IS_ADDR_UNSPECIFIED(ia)) {
                   /*
                    * We use the unspecified address to specify to accept
                    * all multicast addresses. Only super user is allowed
                    * to do this.
                    */
                   if (kauth_authorize_network(curlwp->l_cred, KAUTH_NETWORK_IPV6,
                       KAUTH_REQ_NETWORK_IPV6_JOIN_MULTICAST, NULL, NULL, NULL))
                           return EACCES;
           } else if (IN6_IS_ADDR_V4MAPPED(ia)) {
                   // Don't bother if we are not going to use ifp.
                   if (l == sizeof(*ia)) {
                           memcpy(v, ia, l);
                           return 0;
                   }
           } else if (!IN6_IS_ADDR_MULTICAST(ia)) {
                   return EINVAL;
           }
   
           /*
            * If no interface was explicitly specified, choose an
            * appropriate one according to the given multicast address.
            */
           if (mreq.ipv6mr_interface == 0) {
                   struct rtentry *rt;
                   union {
                           struct sockaddr         dst;
                           struct sockaddr_in      dst4;
                           struct sockaddr_in6     dst6;
                   } u;
                   struct route ro;
   
                   /*
                    * Look up the routing table for the
                    * address, and choose the outgoing interface.
                    *   XXX: is it a good approach?
                    */
                   memset(&ro, 0, sizeof(ro));
                   if (IN6_IS_ADDR_V4MAPPED(ia))
                           sockaddr_in_init(&u.dst4, ia4, 0);
                   else
                           sockaddr_in6_init(&u.dst6, ia, 0, 0, 0);
                   rtcache_setdst(&ro, &u.dst);
                   *ifp = (rt = rtcache_init(&ro)) != NULL ? rt->rt_ifp : NULL;
                   rtcache_free(&ro);
           } else {
                   /*
                    * If the interface is specified, validate it.
                    */
                   if ((*ifp = if_byindex(mreq.ipv6mr_interface)) == NULL)
                           return ENXIO;   /* XXX EINVAL? */
           }
           if (sizeof(*ia) == l)
                   memcpy(v, ia, l);
           else
                   memcpy(v, ia4, l);
           return 0;
   }
   
 /*  /*
  * Set the IP6 multicast options in response to user setsockopt().   * Set the IP6 multicast options in response to user setsockopt().
  */   */
 static int  static int
 ip6_setmoptions(const struct sockopt *sopt, struct ip6_moptions **im6op)  ip6_setmoptions(const struct sockopt *sopt, struct in6pcb *in6p)
 {  {
         int error = 0;          int error = 0;
         u_int loop, ifindex;          u_int loop, ifindex;
         struct ipv6_mreq mreq;          struct ipv6_mreq mreq;
           struct in6_addr ia;
         struct ifnet *ifp;          struct ifnet *ifp;
         struct ip6_moptions *im6o = *im6op;          struct ip6_moptions *im6o = in6p->in6p_moptions;
         struct route ro;  
         struct in6_multi_mship *imm;          struct in6_multi_mship *imm;
         struct lwp *l = curlwp; /* XXX */  
   
         if (im6o == NULL) {          if (im6o == NULL) {
                 /*                  /*
Line 2290  ip6_setmoptions(const struct sockopt *so
Line 2360  ip6_setmoptions(const struct sockopt *so
                 im6o = malloc(sizeof(*im6o), M_IPMOPTS, M_NOWAIT);                  im6o = malloc(sizeof(*im6o), M_IPMOPTS, M_NOWAIT);
                 if (im6o == NULL)                  if (im6o == NULL)
                         return (ENOBUFS);                          return (ENOBUFS);
                   in6p->in6p_moptions = im6o;
                 *im6op = im6o;  
                 im6o->im6o_multicast_ifp = NULL;                  im6o->im6o_multicast_ifp = NULL;
                 im6o->im6o_multicast_hlim = ip6_defmcasthlim;                  im6o->im6o_multicast_hlim = ip6_defmcasthlim;
                 im6o->im6o_multicast_loop = IPV6_DEFAULT_MULTICAST_LOOP;                  im6o->im6o_multicast_loop = IPV6_DEFAULT_MULTICAST_LOOP;
Line 2362  ip6_setmoptions(const struct sockopt *so
Line 2431  ip6_setmoptions(const struct sockopt *so
                  * Add a multicast group membership.                   * Add a multicast group membership.
                  * Group must be a valid IP6 multicast address.                   * Group must be a valid IP6 multicast address.
                  */                   */
                 error = sockopt_get(sopt, &mreq, sizeof(mreq));                  if ((error = ip6_get_membership(sopt, &ifp, &ia, sizeof(ia))))
                 if (error != 0)                          return error;
                         break;  
   
                 if (IN6_IS_ADDR_UNSPECIFIED(&mreq.ipv6mr_multiaddr)) {                  if (IN6_IS_ADDR_V4MAPPED(&ia)) {
                         /*                          error = ip_setmoptions(&in6p->in6p_v4moptions, sopt);
                          * We use the unspecified address to specify to accept  
                          * all multicast addresses. Only super user is allowed  
                          * to do this.  
                          */  
                         if (kauth_authorize_network(l->l_cred, KAUTH_NETWORK_IPV6,  
                             KAUTH_REQ_NETWORK_IPV6_JOIN_MULTICAST, NULL, NULL, NULL))  
                         {  
                                 error = EACCES;  
                                 break;  
                         }  
                 } else if (!IN6_IS_ADDR_MULTICAST(&mreq.ipv6mr_multiaddr)) {  
                         error = EINVAL;  
                         break;                          break;
                 }                  }
   
                 /*  
                  * If no interface was explicitly specified, choose an  
                  * appropriate one according to the given multicast address.  
                  */  
                 if (mreq.ipv6mr_interface == 0) {  
                         struct rtentry *rt;  
                         union {  
                                 struct sockaddr         dst;  
                                 struct sockaddr_in6     dst6;  
                         } u;  
   
                         /*  
                          * Look up the routing table for the  
                          * address, and choose the outgoing interface.  
                          *   XXX: is it a good approach?  
                          */  
                         memset(&ro, 0, sizeof(ro));  
                         sockaddr_in6_init(&u.dst6, &mreq.ipv6mr_multiaddr, 0,  
                             0, 0);  
                         rtcache_setdst(&ro, &u.dst);  
                         ifp = (rt = rtcache_init(&ro)) != NULL ? rt->rt_ifp  
                                                                 : NULL;  
                         rtcache_free(&ro);  
                 } else {  
                         /*  
                          * If the interface is specified, validate it.  
                          */  
                         if ((ifp = if_byindex(mreq.ipv6mr_interface)) == NULL) {  
                                 error = ENXIO;  /* XXX EINVAL? */  
                                 break;  
                         }  
                 }  
   
                 /*                  /*
                  * See if we found an interface, and confirm that it                   * See if we found an interface, and confirm that it
                  * supports multicast                   * supports multicast
Line 2425  ip6_setmoptions(const struct sockopt *so
Line 2447  ip6_setmoptions(const struct sockopt *so
                         break;                          break;
                 }                  }
   
                 if (in6_setscope(&mreq.ipv6mr_multiaddr, ifp, NULL)) {                  if (in6_setscope(&ia, ifp, NULL)) {
                         error = EADDRNOTAVAIL; /* XXX: should not happen */                          error = EADDRNOTAVAIL; /* XXX: should not happen */
                         break;                          break;
                 }                  }
Line 2437  ip6_setmoptions(const struct sockopt *so
Line 2459  ip6_setmoptions(const struct sockopt *so
                      imm != NULL; imm = imm->i6mm_chain.le_next)                       imm != NULL; imm = imm->i6mm_chain.le_next)
                         if (imm->i6mm_maddr->in6m_ifp == ifp &&                          if (imm->i6mm_maddr->in6m_ifp == ifp &&
                             IN6_ARE_ADDR_EQUAL(&imm->i6mm_maddr->in6m_addr,                              IN6_ARE_ADDR_EQUAL(&imm->i6mm_maddr->in6m_addr,
                             &mreq.ipv6mr_multiaddr))                              &ia))
                                 break;                                  break;
                 if (imm != NULL) {                  if (imm != NULL) {
                         error = EADDRINUSE;                          error = EADDRINUSE;
Line 2447  ip6_setmoptions(const struct sockopt *so
Line 2469  ip6_setmoptions(const struct sockopt *so
                  * Everything looks good; add a new record to the multicast                   * Everything looks good; add a new record to the multicast
                  * address list for the given interface.                   * address list for the given interface.
                  */                   */
                 imm = in6_joingroup(ifp, &mreq.ipv6mr_multiaddr, &error, 0);                  imm = in6_joingroup(ifp, &ia, &error, 0);
                 if (imm == NULL)                  if (imm == NULL)
                         break;                          break;
                 LIST_INSERT_HEAD(&im6o->im6o_memberships, imm, i6mm_chain);                  LIST_INSERT_HEAD(&im6o->im6o_memberships, imm, i6mm_chain);
Line 2462  ip6_setmoptions(const struct sockopt *so
Line 2484  ip6_setmoptions(const struct sockopt *so
                 if (error != 0)                  if (error != 0)
                         break;                          break;
   
                   if (IN6_IS_ADDR_V4MAPPED(&mreq.ipv6mr_multiaddr)) {
                           error = ip_setmoptions(&in6p->in6p_v4moptions, sopt);
                           break;
                   }
                 /*                  /*
                  * If an interface address was specified, get a pointer                   * If an interface address was specified, get a pointer
                  * to its ifnet structure.                   * to its ifnet structure.
Line 2547  ip6_setmoptions(const struct sockopt *so
Line 2573  ip6_setmoptions(const struct sockopt *so
             im6o->im6o_multicast_hlim == ip6_defmcasthlim &&              im6o->im6o_multicast_hlim == ip6_defmcasthlim &&
             im6o->im6o_multicast_loop == IPV6_DEFAULT_MULTICAST_LOOP &&              im6o->im6o_multicast_loop == IPV6_DEFAULT_MULTICAST_LOOP &&
             im6o->im6o_memberships.lh_first == NULL) {              im6o->im6o_memberships.lh_first == NULL) {
                 free(*im6op, M_IPMOPTS);                  free(in6p->in6p_moptions, M_IPMOPTS);
                 *im6op = NULL;                  in6p->in6p_moptions = NULL;
         }          }
   
         return (error);          return (error);
Line 2558  ip6_setmoptions(const struct sockopt *so
Line 2584  ip6_setmoptions(const struct sockopt *so
  * Return the IP6 multicast options in response to user getsockopt().   * Return the IP6 multicast options in response to user getsockopt().
  */   */
 static int  static int
 ip6_getmoptions(struct sockopt *sopt, struct ip6_moptions *im6o)  ip6_getmoptions(struct sockopt *sopt, struct in6pcb *in6p)
 {  {
         u_int optval;          u_int optval;
         int error;          int error;
           struct ip6_moptions *im6o = in6p->in6p_moptions;
   
         switch (sopt->sopt_name) {          switch (sopt->sopt_name) {
         case IPV6_MULTICAST_IF:          case IPV6_MULTICAST_IF:

Legend:
Removed from v.1.159  
changed lines
  Added in v.1.160

CVSweb <webmaster@jp.NetBSD.org>