Print this page
4596 Callers of ip_srcid_find_id() need to be more careful


   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.


  24  */
  25 
  26 /*
  27  * This is used to support the hidden __sin6_src_id in the sockaddr_in6
  28  * structure which is there to ensure that applications (such as UDP apps)
  29  * which get an address from recvfrom and use that address in a sendto
  30  * or connect will by default use the same source address in the "response"
  31  * as the destination address in the "request" they received.
  32  *
  33  * This is built using some new functions (in IP - doing their own locking
  34  * so they can be called from the transports) to map between integer IDs
  35  * and in6_addr_t.
  36  * The use applies to sockaddr_in6 - whether or not mapped addresses are used.
  37  *
  38  * This file contains the functions used by both IP and the transports
  39  * to implement __sin6_src_id.
  40  * The routines do their own locking since they are called from
  41  * the transports (to map between a source id and an address)
  42  * and from IP proper when IP addresses are added and removed.
  43  *


 206         smpp = srcid_lookup_addr(addr, zoneid, ipst);
 207         smp = *smpp;
 208         if (smp == NULL) {
 209                 char            abuf[INET6_ADDRSTRLEN];
 210 
 211                 /* Not present - could be broadcast or multicast address */
 212                 ip1dbg(("ip_srcid_find_addr: unknown %s in zone %d\n",
 213                     inet_ntop(AF_INET6, addr, abuf, sizeof (abuf)), zoneid));
 214                 id = 0;
 215         } else {
 216                 ASSERT(smp->sm_refcnt != 0);
 217                 id = smp->sm_srcid;
 218         }
 219         rw_exit(&ipst->ips_srcid_lock);
 220         return (id);
 221 }
 222 
 223 /*
 224  * Map from a source id to an address.
 225  * If the id is unknown return the unspecified address.







 226  */
 227 void
 228 ip_srcid_find_id(uint_t id, in6_addr_t *addr, zoneid_t zoneid,
 229     netstack_t *ns)
 230 {
 231         srcid_map_t     **smpp;
 232         srcid_map_t     *smp;
 233         ip_stack_t      *ipst = ns->netstack_ip;

 234 
 235         rw_enter(&ipst->ips_srcid_lock, RW_READER);
 236         smpp = srcid_lookup_id(id, ipst);
 237         smp = *smpp;
 238         if (smp == NULL || (smp->sm_zoneid != zoneid && zoneid != ALL_ZONES)) {
 239                 /* Not preset */
 240                 ip1dbg(("ip_srcid_find_id: unknown %u or in wrong zone\n", id));
 241                 *addr = ipv6_all_zeros;

 242         } else {
 243                 ASSERT(smp->sm_refcnt != 0);










 244                 *addr = smp->sm_addr;

 245         }
 246         rw_exit(&ipst->ips_srcid_lock);

 247 }
 248 
 249 /* Assign the next available ID */
 250 static uint_t
 251 srcid_nextid(ip_stack_t *ipst)
 252 {
 253         uint_t id;
 254         srcid_map_t     **smpp;
 255 
 256         ASSERT(rw_owner(&ipst->ips_srcid_lock) == curthread);
 257 
 258         if (!ipst->ips_srcid_wrapped) {
 259                 id = ipst->ips_ip_src_id++;
 260                 if (ipst->ips_ip_src_id == 0)
 261                         ipst->ips_srcid_wrapped = B_TRUE;
 262                 return (id);
 263         }
 264         /* Once it wraps we search for an unused ID. */
 265         for (id = 0; id < 0xffffffff; id++) {
 266                 smpp = srcid_lookup_id(id, ipst);




   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  *
  25  * Copyright 2014, OmniTI Computer Consulting, Inc. All rights reserved.
  26  */
  27 
  28 /*
  29  * This is used to support the hidden __sin6_src_id in the sockaddr_in6
  30  * structure which is there to ensure that applications (such as UDP apps)
  31  * which get an address from recvfrom and use that address in a sendto
  32  * or connect will by default use the same source address in the "response"
  33  * as the destination address in the "request" they received.
  34  *
  35  * This is built using some new functions (in IP - doing their own locking
  36  * so they can be called from the transports) to map between integer IDs
  37  * and in6_addr_t.
  38  * The use applies to sockaddr_in6 - whether or not mapped addresses are used.
  39  *
  40  * This file contains the functions used by both IP and the transports
  41  * to implement __sin6_src_id.
  42  * The routines do their own locking since they are called from
  43  * the transports (to map between a source id and an address)
  44  * and from IP proper when IP addresses are added and removed.
  45  *


 208         smpp = srcid_lookup_addr(addr, zoneid, ipst);
 209         smp = *smpp;
 210         if (smp == NULL) {
 211                 char            abuf[INET6_ADDRSTRLEN];
 212 
 213                 /* Not present - could be broadcast or multicast address */
 214                 ip1dbg(("ip_srcid_find_addr: unknown %s in zone %d\n",
 215                     inet_ntop(AF_INET6, addr, abuf, sizeof (abuf)), zoneid));
 216                 id = 0;
 217         } else {
 218                 ASSERT(smp->sm_refcnt != 0);
 219                 id = smp->sm_srcid;
 220         }
 221         rw_exit(&ipst->ips_srcid_lock);
 222         return (id);
 223 }
 224 
 225 /*
 226  * Map from a source id to an address.
 227  * If the id is unknown return the unspecified address.
 228  *
 229  * For known IDs, check if the returned address is v4mapped or not, and
 230  * return B_TRUE if it matches the desired v4mapped state or not.  This
 231  * prevents a broken app from requesting (via __sin6_src_id) a v4mapped
 232  * address for a v6 destination, or vice versa.
 233  *
 234  * "addr" will not be set if we return B_FALSE.
 235  */
 236 boolean_t
 237 ip_srcid_find_id(uint_t id, in6_addr_t *addr, zoneid_t zoneid,
 238     boolean_t v4mapped, netstack_t *ns)
 239 {
 240         srcid_map_t     **smpp;
 241         srcid_map_t     *smp;
 242         ip_stack_t      *ipst = ns->netstack_ip;
 243         boolean_t       rc;
 244 
 245         rw_enter(&ipst->ips_srcid_lock, RW_READER);
 246         smpp = srcid_lookup_id(id, ipst);
 247         smp = *smpp;
 248         if (smp == NULL || (smp->sm_zoneid != zoneid && zoneid != ALL_ZONES)) {
 249                 /* Not preset */
 250                 ip1dbg(("ip_srcid_find_id: unknown %u or in wrong zone\n", id));
 251                 *addr = ipv6_all_zeros;
 252                 rc = B_TRUE;
 253         } else {
 254                 ASSERT(smp->sm_refcnt != 0);
 255                 /*
 256                  * The caller tells us if it expects a v4mapped address.
 257                  * Use it, along with the property of "addr" to set the rc.
 258                  */
 259                 if (IN6_IS_ADDR_V4MAPPED(&smp->sm_addr))
 260                         rc = v4mapped;  /* We want a v4mapped address. */
 261                 else
 262                         rc = !v4mapped; /* We don't want a v4mapped address. */
 263 
 264                 if (rc)
 265                         *addr = smp->sm_addr;
 266 
 267         }
 268         rw_exit(&ipst->ips_srcid_lock);
 269         return (rc);
 270 }
 271 
 272 /* Assign the next available ID */
 273 static uint_t
 274 srcid_nextid(ip_stack_t *ipst)
 275 {
 276         uint_t id;
 277         srcid_map_t     **smpp;
 278 
 279         ASSERT(rw_owner(&ipst->ips_srcid_lock) == curthread);
 280 
 281         if (!ipst->ips_srcid_wrapped) {
 282                 id = ipst->ips_ip_src_id++;
 283                 if (ipst->ips_ip_src_id == 0)
 284                         ipst->ips_srcid_wrapped = B_TRUE;
 285                 return (id);
 286         }
 287         /* Once it wraps we search for an unused ID. */
 288         for (id = 0; id < 0xffffffff; id++) {
 289                 smpp = srcid_lookup_id(id, ipst);