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

*** 19,28 **** --- 19,30 ---- * CDDL HEADER END */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * + * Copyright 2014, OmniTI Computer Consulting, Inc. All rights reserved. */ /* * This is used to support the hidden __sin6_src_id in the sockaddr_in6 * structure which is there to ensure that applications (such as UDP apps)
*** 221,251 **** } /* * Map from a source id to an address. * If the id is unknown return the unspecified address. */ ! void ip_srcid_find_id(uint_t id, in6_addr_t *addr, zoneid_t zoneid, ! netstack_t *ns) { srcid_map_t **smpp; srcid_map_t *smp; ip_stack_t *ipst = ns->netstack_ip; rw_enter(&ipst->ips_srcid_lock, RW_READER); smpp = srcid_lookup_id(id, ipst); smp = *smpp; if (smp == NULL || (smp->sm_zoneid != zoneid && zoneid != ALL_ZONES)) { /* Not preset */ ip1dbg(("ip_srcid_find_id: unknown %u or in wrong zone\n", id)); *addr = ipv6_all_zeros; } else { ASSERT(smp->sm_refcnt != 0); *addr = smp->sm_addr; } rw_exit(&ipst->ips_srcid_lock); } /* Assign the next available ID */ static uint_t srcid_nextid(ip_stack_t *ipst) --- 223,274 ---- } /* * Map from a source id to an address. * If the id is unknown return the unspecified address. + * + * For known IDs, check if the returned address is v4mapped or not, and + * return B_TRUE if it matches the desired v4mapped state or not. This + * prevents a broken app from requesting (via __sin6_src_id) a v4mapped + * address for a v6 destination, or vice versa. + * + * "addr" will not be set if we return B_FALSE. */ ! boolean_t ip_srcid_find_id(uint_t id, in6_addr_t *addr, zoneid_t zoneid, ! boolean_t v4mapped, netstack_t *ns) { srcid_map_t **smpp; srcid_map_t *smp; ip_stack_t *ipst = ns->netstack_ip; + boolean_t rc; rw_enter(&ipst->ips_srcid_lock, RW_READER); smpp = srcid_lookup_id(id, ipst); smp = *smpp; if (smp == NULL || (smp->sm_zoneid != zoneid && zoneid != ALL_ZONES)) { /* Not preset */ ip1dbg(("ip_srcid_find_id: unknown %u or in wrong zone\n", id)); *addr = ipv6_all_zeros; + rc = B_TRUE; } else { ASSERT(smp->sm_refcnt != 0); + /* + * The caller tells us if it expects a v4mapped address. + * Use it, along with the property of "addr" to set the rc. + */ + if (IN6_IS_ADDR_V4MAPPED(&smp->sm_addr)) + rc = v4mapped; /* We want a v4mapped address. */ + else + rc = !v4mapped; /* We don't want a v4mapped address. */ + + if (rc) *addr = smp->sm_addr; + } rw_exit(&ipst->ips_srcid_lock); + return (rc); } /* Assign the next available ID */ static uint_t srcid_nextid(ip_stack_t *ipst)