17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5f4b3ec61Sdh155122 * Common Development and Distribution License (the "License"). 6f4b3ec61Sdh155122 * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22d5b6ed4bSVasumathi Sundaram - Sun Microsystems * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 24a1ca8b43SDan McDonald * 25a1ca8b43SDan McDonald * Copyright 2014, OmniTI Computer Consulting, Inc. All rights reserved. 267c478bd9Sstevel@tonic-gate */ 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate /* 297c478bd9Sstevel@tonic-gate * This is used to support the hidden __sin6_src_id in the sockaddr_in6 307c478bd9Sstevel@tonic-gate * structure which is there to ensure that applications (such as UDP apps) 317c478bd9Sstevel@tonic-gate * which get an address from recvfrom and use that address in a sendto 327c478bd9Sstevel@tonic-gate * or connect will by default use the same source address in the "response" 337c478bd9Sstevel@tonic-gate * as the destination address in the "request" they received. 347c478bd9Sstevel@tonic-gate * 357c478bd9Sstevel@tonic-gate * This is built using some new functions (in IP - doing their own locking 367c478bd9Sstevel@tonic-gate * so they can be called from the transports) to map between integer IDs 377c478bd9Sstevel@tonic-gate * and in6_addr_t. 387c478bd9Sstevel@tonic-gate * The use applies to sockaddr_in6 - whether or not mapped addresses are used. 397c478bd9Sstevel@tonic-gate * 407c478bd9Sstevel@tonic-gate * This file contains the functions used by both IP and the transports 417c478bd9Sstevel@tonic-gate * to implement __sin6_src_id. 427c478bd9Sstevel@tonic-gate * The routines do their own locking since they are called from 437c478bd9Sstevel@tonic-gate * the transports (to map between a source id and an address) 447c478bd9Sstevel@tonic-gate * and from IP proper when IP addresses are added and removed. 457c478bd9Sstevel@tonic-gate * 467c478bd9Sstevel@tonic-gate * The routines handle both IPv4 and IPv6 with the IPv4 addresses represented 477c478bd9Sstevel@tonic-gate * as IPv4-mapped addresses. 487c478bd9Sstevel@tonic-gate */ 497c478bd9Sstevel@tonic-gate 507c478bd9Sstevel@tonic-gate #include <sys/types.h> 517c478bd9Sstevel@tonic-gate #include <sys/stream.h> 527c478bd9Sstevel@tonic-gate #include <sys/dlpi.h> 537c478bd9Sstevel@tonic-gate #include <sys/stropts.h> 547c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 557c478bd9Sstevel@tonic-gate #include <sys/strsubr.h> 567c478bd9Sstevel@tonic-gate #include <sys/strlog.h> 577c478bd9Sstevel@tonic-gate #define _SUN_TPI_VERSION 2 587c478bd9Sstevel@tonic-gate #include <sys/tihdr.h> 597c478bd9Sstevel@tonic-gate #include <sys/xti_inet.h> 607c478bd9Sstevel@tonic-gate #include <sys/ddi.h> 617c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 627c478bd9Sstevel@tonic-gate #include <sys/debug.h> 637c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 647c478bd9Sstevel@tonic-gate #include <sys/atomic.h> 657c478bd9Sstevel@tonic-gate #include <sys/zone.h> 667c478bd9Sstevel@tonic-gate 677c478bd9Sstevel@tonic-gate #include <sys/systm.h> 687c478bd9Sstevel@tonic-gate #include <sys/param.h> 697c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 707c478bd9Sstevel@tonic-gate #include <sys/callb.h> 717c478bd9Sstevel@tonic-gate #include <sys/socket.h> 727c478bd9Sstevel@tonic-gate #include <sys/vtrace.h> 737c478bd9Sstevel@tonic-gate #include <sys/isa_defs.h> 747c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 757c478bd9Sstevel@tonic-gate #include <net/if.h> 767c478bd9Sstevel@tonic-gate #include <net/if_arp.h> 777c478bd9Sstevel@tonic-gate #include <net/route.h> 787c478bd9Sstevel@tonic-gate #include <sys/sockio.h> 797c478bd9Sstevel@tonic-gate #include <netinet/in.h> 807c478bd9Sstevel@tonic-gate #include <net/if_dl.h> 817c478bd9Sstevel@tonic-gate 827c478bd9Sstevel@tonic-gate #include <inet/common.h> 837c478bd9Sstevel@tonic-gate #include <inet/mi.h> 847c478bd9Sstevel@tonic-gate #include <inet/mib2.h> 857c478bd9Sstevel@tonic-gate #include <inet/nd.h> 867c478bd9Sstevel@tonic-gate #include <inet/arp.h> 877c478bd9Sstevel@tonic-gate #include <inet/snmpcom.h> 887c478bd9Sstevel@tonic-gate 897c478bd9Sstevel@tonic-gate #include <netinet/igmp_var.h> 907c478bd9Sstevel@tonic-gate #include <netinet/ip6.h> 917c478bd9Sstevel@tonic-gate #include <netinet/icmp6.h> 927c478bd9Sstevel@tonic-gate 937c478bd9Sstevel@tonic-gate #include <inet/ip.h> 947c478bd9Sstevel@tonic-gate #include <inet/ip6.h> 957c478bd9Sstevel@tonic-gate #include <inet/tcp.h> 967c478bd9Sstevel@tonic-gate #include <inet/ip_multi.h> 977c478bd9Sstevel@tonic-gate #include <inet/ip_if.h> 987c478bd9Sstevel@tonic-gate #include <inet/ip_ire.h> 997c478bd9Sstevel@tonic-gate #include <inet/ip_rts.h> 1007c478bd9Sstevel@tonic-gate #include <inet/optcom.h> 1017c478bd9Sstevel@tonic-gate #include <inet/ip_ndp.h> 1027c478bd9Sstevel@tonic-gate #include <netinet/igmp.h> 1037c478bd9Sstevel@tonic-gate #include <netinet/ip_mroute.h> 1047c478bd9Sstevel@tonic-gate #include <inet/ipclassifier.h> 1057c478bd9Sstevel@tonic-gate 1067c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 1077c478bd9Sstevel@tonic-gate 108f4b3ec61Sdh155122 static uint_t srcid_nextid(ip_stack_t *); 1097c478bd9Sstevel@tonic-gate static srcid_map_t **srcid_lookup_addr(const in6_addr_t *addr, 110f4b3ec61Sdh155122 zoneid_t zoneid, ip_stack_t *); 111f4b3ec61Sdh155122 static srcid_map_t **srcid_lookup_id(uint_t id, ip_stack_t *); 1127c478bd9Sstevel@tonic-gate 1137c478bd9Sstevel@tonic-gate 1147c478bd9Sstevel@tonic-gate /* 1157c478bd9Sstevel@tonic-gate * Insert/add a new address to the map. 1167c478bd9Sstevel@tonic-gate * Returns zero if ok; otherwise errno (e.g. for memory allocation failure). 1177c478bd9Sstevel@tonic-gate */ 1187c478bd9Sstevel@tonic-gate int 119f4b3ec61Sdh155122 ip_srcid_insert(const in6_addr_t *addr, zoneid_t zoneid, ip_stack_t *ipst) 1207c478bd9Sstevel@tonic-gate { 1217c478bd9Sstevel@tonic-gate srcid_map_t **smpp; 1227c478bd9Sstevel@tonic-gate #ifdef DEBUG 1237c478bd9Sstevel@tonic-gate char abuf[INET6_ADDRSTRLEN]; 1247c478bd9Sstevel@tonic-gate 1257c478bd9Sstevel@tonic-gate ip1dbg(("ip_srcid_insert(%s, %d)\n", 1267c478bd9Sstevel@tonic-gate inet_ntop(AF_INET6, addr, abuf, sizeof (abuf)), zoneid)); 1277c478bd9Sstevel@tonic-gate #endif 1287c478bd9Sstevel@tonic-gate 129f4b3ec61Sdh155122 rw_enter(&ipst->ips_srcid_lock, RW_WRITER); 130f4b3ec61Sdh155122 smpp = srcid_lookup_addr(addr, zoneid, ipst); 1317c478bd9Sstevel@tonic-gate if (*smpp != NULL) { 1327c478bd9Sstevel@tonic-gate /* Already present - increment refcount */ 1337c478bd9Sstevel@tonic-gate (*smpp)->sm_refcnt++; 1347c478bd9Sstevel@tonic-gate ASSERT((*smpp)->sm_refcnt != 0); /* wraparound */ 135f4b3ec61Sdh155122 rw_exit(&ipst->ips_srcid_lock); 1367c478bd9Sstevel@tonic-gate return (0); 1377c478bd9Sstevel@tonic-gate } 1387c478bd9Sstevel@tonic-gate /* Insert new */ 1397c478bd9Sstevel@tonic-gate *smpp = kmem_alloc(sizeof (srcid_map_t), KM_NOSLEEP); 1407c478bd9Sstevel@tonic-gate if (*smpp == NULL) { 141f4b3ec61Sdh155122 rw_exit(&ipst->ips_srcid_lock); 1427c478bd9Sstevel@tonic-gate return (ENOMEM); 1437c478bd9Sstevel@tonic-gate } 1447c478bd9Sstevel@tonic-gate (*smpp)->sm_next = NULL; 1457c478bd9Sstevel@tonic-gate (*smpp)->sm_addr = *addr; 146f4b3ec61Sdh155122 (*smpp)->sm_srcid = srcid_nextid(ipst); 1477c478bd9Sstevel@tonic-gate (*smpp)->sm_refcnt = 1; 1487c478bd9Sstevel@tonic-gate (*smpp)->sm_zoneid = zoneid; 1497c478bd9Sstevel@tonic-gate 150f4b3ec61Sdh155122 rw_exit(&ipst->ips_srcid_lock); 1517c478bd9Sstevel@tonic-gate return (0); 1527c478bd9Sstevel@tonic-gate } 1537c478bd9Sstevel@tonic-gate 1547c478bd9Sstevel@tonic-gate /* 1557c478bd9Sstevel@tonic-gate * Remove an new address from the map. 1567c478bd9Sstevel@tonic-gate * Returns zero if ok; otherwise errno (e.g. for nonexistent address). 1577c478bd9Sstevel@tonic-gate */ 1587c478bd9Sstevel@tonic-gate int 159f4b3ec61Sdh155122 ip_srcid_remove(const in6_addr_t *addr, zoneid_t zoneid, ip_stack_t *ipst) 1607c478bd9Sstevel@tonic-gate { 1617c478bd9Sstevel@tonic-gate srcid_map_t **smpp; 1627c478bd9Sstevel@tonic-gate srcid_map_t *smp; 1637c478bd9Sstevel@tonic-gate #ifdef DEBUG 1647c478bd9Sstevel@tonic-gate char abuf[INET6_ADDRSTRLEN]; 1657c478bd9Sstevel@tonic-gate 1667c478bd9Sstevel@tonic-gate ip1dbg(("ip_srcid_remove(%s, %d)\n", 1677c478bd9Sstevel@tonic-gate inet_ntop(AF_INET6, addr, abuf, sizeof (abuf)), zoneid)); 1687c478bd9Sstevel@tonic-gate #endif 1697c478bd9Sstevel@tonic-gate 170f4b3ec61Sdh155122 rw_enter(&ipst->ips_srcid_lock, RW_WRITER); 171f4b3ec61Sdh155122 smpp = srcid_lookup_addr(addr, zoneid, ipst); 1727c478bd9Sstevel@tonic-gate smp = *smpp; 1737c478bd9Sstevel@tonic-gate if (smp == NULL) { 1747c478bd9Sstevel@tonic-gate /* Not preset */ 175f4b3ec61Sdh155122 rw_exit(&ipst->ips_srcid_lock); 1767c478bd9Sstevel@tonic-gate return (ENOENT); 1777c478bd9Sstevel@tonic-gate } 1787c478bd9Sstevel@tonic-gate 1797c478bd9Sstevel@tonic-gate /* Decrement refcount */ 1807c478bd9Sstevel@tonic-gate ASSERT(smp->sm_refcnt != 0); 1817c478bd9Sstevel@tonic-gate smp->sm_refcnt--; 1827c478bd9Sstevel@tonic-gate if (smp->sm_refcnt != 0) { 183f4b3ec61Sdh155122 rw_exit(&ipst->ips_srcid_lock); 1847c478bd9Sstevel@tonic-gate return (0); 1857c478bd9Sstevel@tonic-gate } 1867c478bd9Sstevel@tonic-gate /* Remove entry */ 1877c478bd9Sstevel@tonic-gate *smpp = smp->sm_next; 188f4b3ec61Sdh155122 rw_exit(&ipst->ips_srcid_lock); 1897c478bd9Sstevel@tonic-gate smp->sm_next = NULL; 1907c478bd9Sstevel@tonic-gate kmem_free(smp, sizeof (srcid_map_t)); 1917c478bd9Sstevel@tonic-gate return (0); 1927c478bd9Sstevel@tonic-gate } 1937c478bd9Sstevel@tonic-gate 1947c478bd9Sstevel@tonic-gate /* 1957c478bd9Sstevel@tonic-gate * Map from an address to a source id. 1967c478bd9Sstevel@tonic-gate * If the address is unknown return the unknown id (zero). 1977c478bd9Sstevel@tonic-gate */ 1987c478bd9Sstevel@tonic-gate uint_t 199f4b3ec61Sdh155122 ip_srcid_find_addr(const in6_addr_t *addr, zoneid_t zoneid, 200f4b3ec61Sdh155122 netstack_t *ns) 2017c478bd9Sstevel@tonic-gate { 2027c478bd9Sstevel@tonic-gate srcid_map_t **smpp; 2037c478bd9Sstevel@tonic-gate srcid_map_t *smp; 2047c478bd9Sstevel@tonic-gate uint_t id; 205f4b3ec61Sdh155122 ip_stack_t *ipst = ns->netstack_ip; 2067c478bd9Sstevel@tonic-gate 207f4b3ec61Sdh155122 rw_enter(&ipst->ips_srcid_lock, RW_READER); 208f4b3ec61Sdh155122 smpp = srcid_lookup_addr(addr, zoneid, ipst); 2097c478bd9Sstevel@tonic-gate smp = *smpp; 2107c478bd9Sstevel@tonic-gate if (smp == NULL) { 2117c478bd9Sstevel@tonic-gate char abuf[INET6_ADDRSTRLEN]; 2127c478bd9Sstevel@tonic-gate 2137c478bd9Sstevel@tonic-gate /* Not present - could be broadcast or multicast address */ 2147c478bd9Sstevel@tonic-gate ip1dbg(("ip_srcid_find_addr: unknown %s in zone %d\n", 2157c478bd9Sstevel@tonic-gate inet_ntop(AF_INET6, addr, abuf, sizeof (abuf)), zoneid)); 2167c478bd9Sstevel@tonic-gate id = 0; 2177c478bd9Sstevel@tonic-gate } else { 2187c478bd9Sstevel@tonic-gate ASSERT(smp->sm_refcnt != 0); 2197c478bd9Sstevel@tonic-gate id = smp->sm_srcid; 2207c478bd9Sstevel@tonic-gate } 221f4b3ec61Sdh155122 rw_exit(&ipst->ips_srcid_lock); 2227c478bd9Sstevel@tonic-gate return (id); 2237c478bd9Sstevel@tonic-gate } 2247c478bd9Sstevel@tonic-gate 2257c478bd9Sstevel@tonic-gate /* 2267c478bd9Sstevel@tonic-gate * Map from a source id to an address. 2277c478bd9Sstevel@tonic-gate * If the id is unknown return the unspecified address. 228a1ca8b43SDan McDonald * 229a1ca8b43SDan McDonald * For known IDs, check if the returned address is v4mapped or not, and 230a1ca8b43SDan McDonald * return B_TRUE if it matches the desired v4mapped state or not. This 231a1ca8b43SDan McDonald * prevents a broken app from requesting (via __sin6_src_id) a v4mapped 232a1ca8b43SDan McDonald * address for a v6 destination, or vice versa. 233a1ca8b43SDan McDonald * 234a1ca8b43SDan McDonald * "addr" will not be set if we return B_FALSE. 2357c478bd9Sstevel@tonic-gate */ 236a1ca8b43SDan McDonald boolean_t 237f4b3ec61Sdh155122 ip_srcid_find_id(uint_t id, in6_addr_t *addr, zoneid_t zoneid, 238a1ca8b43SDan McDonald boolean_t v4mapped, netstack_t *ns) 2397c478bd9Sstevel@tonic-gate { 2407c478bd9Sstevel@tonic-gate srcid_map_t **smpp; 2417c478bd9Sstevel@tonic-gate srcid_map_t *smp; 242f4b3ec61Sdh155122 ip_stack_t *ipst = ns->netstack_ip; 243a1ca8b43SDan McDonald boolean_t rc; 2447c478bd9Sstevel@tonic-gate 245f4b3ec61Sdh155122 rw_enter(&ipst->ips_srcid_lock, RW_READER); 246f4b3ec61Sdh155122 smpp = srcid_lookup_id(id, ipst); 2477c478bd9Sstevel@tonic-gate smp = *smpp; 248bd670b35SErik Nordmark if (smp == NULL || (smp->sm_zoneid != zoneid && zoneid != ALL_ZONES)) { 2497c478bd9Sstevel@tonic-gate /* Not preset */ 2507c478bd9Sstevel@tonic-gate ip1dbg(("ip_srcid_find_id: unknown %u or in wrong zone\n", id)); 2517c478bd9Sstevel@tonic-gate *addr = ipv6_all_zeros; 252a1ca8b43SDan McDonald rc = B_TRUE; 2537c478bd9Sstevel@tonic-gate } else { 2547c478bd9Sstevel@tonic-gate ASSERT(smp->sm_refcnt != 0); 255a1ca8b43SDan McDonald /* 256a1ca8b43SDan McDonald * The caller tells us if it expects a v4mapped address. 257a1ca8b43SDan McDonald * Use it, along with the property of "addr" to set the rc. 258a1ca8b43SDan McDonald */ 259*62403833SDan McDonald if (IN6_IS_ADDR_V4MAPPED(&smp->sm_addr)) 260a1ca8b43SDan McDonald rc = v4mapped; /* We want a v4mapped address. */ 261a1ca8b43SDan McDonald else 262a1ca8b43SDan McDonald rc = !v4mapped; /* We don't want a v4mapped address. */ 263a1ca8b43SDan McDonald 264a1ca8b43SDan McDonald if (rc) 2657c478bd9Sstevel@tonic-gate *addr = smp->sm_addr; 266a1ca8b43SDan McDonald 2677c478bd9Sstevel@tonic-gate } 268f4b3ec61Sdh155122 rw_exit(&ipst->ips_srcid_lock); 269a1ca8b43SDan McDonald return (rc); 2707c478bd9Sstevel@tonic-gate } 2717c478bd9Sstevel@tonic-gate 2727c478bd9Sstevel@tonic-gate /* Assign the next available ID */ 2737c478bd9Sstevel@tonic-gate static uint_t 274f4b3ec61Sdh155122 srcid_nextid(ip_stack_t *ipst) 2757c478bd9Sstevel@tonic-gate { 2767c478bd9Sstevel@tonic-gate uint_t id; 2777c478bd9Sstevel@tonic-gate srcid_map_t **smpp; 2787c478bd9Sstevel@tonic-gate 279f4b3ec61Sdh155122 ASSERT(rw_owner(&ipst->ips_srcid_lock) == curthread); 2807c478bd9Sstevel@tonic-gate 281f4b3ec61Sdh155122 if (!ipst->ips_srcid_wrapped) { 282f4b3ec61Sdh155122 id = ipst->ips_ip_src_id++; 283f4b3ec61Sdh155122 if (ipst->ips_ip_src_id == 0) 284f4b3ec61Sdh155122 ipst->ips_srcid_wrapped = B_TRUE; 2857c478bd9Sstevel@tonic-gate return (id); 2867c478bd9Sstevel@tonic-gate } 2877c478bd9Sstevel@tonic-gate /* Once it wraps we search for an unused ID. */ 2887c478bd9Sstevel@tonic-gate for (id = 0; id < 0xffffffff; id++) { 289f4b3ec61Sdh155122 smpp = srcid_lookup_id(id, ipst); 2907c478bd9Sstevel@tonic-gate if (*smpp == NULL) 2917c478bd9Sstevel@tonic-gate return (id); 2927c478bd9Sstevel@tonic-gate } 2937c478bd9Sstevel@tonic-gate panic("srcid_nextid: No free identifiers!"); 2947c478bd9Sstevel@tonic-gate /* NOTREACHED */ 2957c478bd9Sstevel@tonic-gate } 2967c478bd9Sstevel@tonic-gate 2977c478bd9Sstevel@tonic-gate /* 2987c478bd9Sstevel@tonic-gate * Lookup based on address. 2997c478bd9Sstevel@tonic-gate * Always returns a non-null pointer. 3007c478bd9Sstevel@tonic-gate * If found then *ptr will be the found object. 3017c478bd9Sstevel@tonic-gate * Otherwise *ptr will be NULL and can be used to insert a new object. 3027c478bd9Sstevel@tonic-gate */ 3037c478bd9Sstevel@tonic-gate static srcid_map_t ** 304f4b3ec61Sdh155122 srcid_lookup_addr(const in6_addr_t *addr, zoneid_t zoneid, ip_stack_t *ipst) 3057c478bd9Sstevel@tonic-gate { 3067c478bd9Sstevel@tonic-gate srcid_map_t **smpp; 3077c478bd9Sstevel@tonic-gate 308f4b3ec61Sdh155122 ASSERT(RW_LOCK_HELD(&ipst->ips_srcid_lock)); 309f4b3ec61Sdh155122 smpp = &ipst->ips_srcid_head; 3107c478bd9Sstevel@tonic-gate while (*smpp != NULL) { 3117c478bd9Sstevel@tonic-gate if (IN6_ARE_ADDR_EQUAL(&(*smpp)->sm_addr, addr) && 312bd670b35SErik Nordmark (zoneid == (*smpp)->sm_zoneid || zoneid == ALL_ZONES)) 3137c478bd9Sstevel@tonic-gate return (smpp); 3147c478bd9Sstevel@tonic-gate smpp = &(*smpp)->sm_next; 3157c478bd9Sstevel@tonic-gate } 3167c478bd9Sstevel@tonic-gate return (smpp); 3177c478bd9Sstevel@tonic-gate } 3187c478bd9Sstevel@tonic-gate 3197c478bd9Sstevel@tonic-gate /* 3207c478bd9Sstevel@tonic-gate * Lookup based on address. 3217c478bd9Sstevel@tonic-gate * Always returns a non-null pointer. 3227c478bd9Sstevel@tonic-gate * If found then *ptr will be the found object. 3237c478bd9Sstevel@tonic-gate * Otherwise *ptr will be NULL and can be used to insert a new object. 3247c478bd9Sstevel@tonic-gate */ 3257c478bd9Sstevel@tonic-gate static srcid_map_t ** 326f4b3ec61Sdh155122 srcid_lookup_id(uint_t id, ip_stack_t *ipst) 3277c478bd9Sstevel@tonic-gate { 3287c478bd9Sstevel@tonic-gate srcid_map_t **smpp; 3297c478bd9Sstevel@tonic-gate 330f4b3ec61Sdh155122 ASSERT(RW_LOCK_HELD(&ipst->ips_srcid_lock)); 331f4b3ec61Sdh155122 smpp = &ipst->ips_srcid_head; 3327c478bd9Sstevel@tonic-gate while (*smpp != NULL) { 3337c478bd9Sstevel@tonic-gate if ((*smpp)->sm_srcid == id) 3347c478bd9Sstevel@tonic-gate return (smpp); 3357c478bd9Sstevel@tonic-gate smpp = &(*smpp)->sm_next; 3367c478bd9Sstevel@tonic-gate } 3377c478bd9Sstevel@tonic-gate return (smpp); 3387c478bd9Sstevel@tonic-gate } 339