xref: /illumos-gate/usr/src/uts/common/inet/ip/ip_srcid.c (revision 62403833)
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
5f4b3ec61Sdh  * Common Development and Distribution License (the "License").
6f4b3ec61Sdh  * 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 
108f4b3ec61Sdh static uint_t		srcid_nextid(ip_stack_t *);
1097c478bd9Sstevel@tonic-gate static srcid_map_t	**srcid_lookup_addr(const in6_addr_t *addr,
110f4b3ec61Sdh     zoneid_t zoneid, ip_stack_t *);
111f4b3ec61Sdh 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
ip_srcid_insert(const in6_addr_t * addr,zoneid_t zoneid,ip_stack_t * ipst)119f4b3ec61Sdh 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 
129f4b3ec61Sdh 	rw_enter(&ipst->ips_srcid_lock, RW_WRITER);
130f4b3ec61Sdh 	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 */
135f4b3ec61Sdh 		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) {
141f4b3ec61Sdh 		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;
146f4b3ec61Sdh 	(*smpp)->sm_srcid = srcid_nextid(ipst);
1477c478bd9Sstevel@tonic-gate 	(*smpp)->sm_refcnt = 1;
1487c478bd9Sstevel@tonic-gate 	(*smpp)->sm_zoneid = zoneid;
1497c478bd9Sstevel@tonic-gate 
150f4b3ec61Sdh 	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
ip_srcid_remove(const in6_addr_t * addr,zoneid_t zoneid,ip_stack_t * ipst)159f4b3ec61Sdh 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 
170f4b3ec61Sdh 	rw_enter(&ipst->ips_srcid_lock, RW_WRITER);
171f4b3ec61Sdh 	smpp = srcid_lookup_addr(addr, zoneid, ipst);
1727c478bd9Sstevel@tonic-gate 	smp = *smpp;
1737c478bd9Sstevel@tonic-gate 	if (smp == NULL) {
1747c478bd9Sstevel@tonic-gate 		/* Not preset */
175f4b3ec61Sdh 		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) {
183f4b3ec61Sdh 		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;
188f4b3ec61Sdh 	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
ip_srcid_find_addr(const in6_addr_t * addr,zoneid_t zoneid,netstack_t * ns)199f4b3ec61Sdh ip_srcid_find_addr(const in6_addr_t *addr, zoneid_t zoneid,
200f4b3ec61Sdh     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;
205f4b3ec61Sdh 	ip_stack_t	*ipst = ns->netstack_ip;
2067c478bd9Sstevel@tonic-gate 
207f4b3ec61Sdh 	rw_enter(&ipst->ips_srcid_lock, RW_READER);
208f4b3ec61Sdh 	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 	}
221f4b3ec61Sdh 	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
ip_srcid_find_id(uint_t id,in6_addr_t * addr,zoneid_t zoneid,boolean_t v4mapped,netstack_t * ns)237f4b3ec61Sdh 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;
242f4b3ec61Sdh 	ip_stack_t	*ipst = ns->netstack_ip;
243a1ca8b43SDan McDonald 	boolean_t	rc;
2447c478bd9Sstevel@tonic-gate 
245f4b3ec61Sdh 	rw_enter(&ipst->ips_srcid_lock, RW_READER);
246f4b3ec61Sdh 	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)
265a1ca8b43SDan McDonald 			*addr = smp->sm_addr;
266a1ca8b43SDan McDonald 
2677c478bd9Sstevel@tonic-gate 	}
268f4b3ec61Sdh 	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
srcid_nextid(ip_stack_t * ipst)274f4b3ec61Sdh 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 
279f4b3ec61Sdh 	ASSERT(rw_owner(&ipst->ips_srcid_lock) == curthread);
2807c478bd9Sstevel@tonic-gate 
281f4b3ec61Sdh 	if (!ipst->ips_srcid_wrapped) {
282f4b3ec61Sdh 		id = ipst->ips_ip_src_id++;
283f4b3ec61Sdh 		if (ipst->ips_ip_src_id == 0)
284f4b3ec61Sdh 			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++) {
289f4b3ec61Sdh 		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 **
srcid_lookup_addr(const in6_addr_t * addr,zoneid_t zoneid,ip_stack_t * ipst)304f4b3ec61Sdh 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 
308f4b3ec61Sdh 	ASSERT(RW_LOCK_HELD(&ipst->ips_srcid_lock));
309f4b3ec61Sdh 	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 **
srcid_lookup_id(uint_t id,ip_stack_t * ipst)326f4b3ec61Sdh srcid_lookup_id(uint_t id, ip_stack_t *ipst)
3277c478bd9Sstevel@tonic-gate {
3287c478bd9Sstevel@tonic-gate 	srcid_map_t	**smpp;
3297c478bd9Sstevel@tonic-gate 
330f4b3ec61Sdh 	ASSERT(RW_LOCK_HELD(&ipst->ips_srcid_lock));
331f4b3ec61Sdh 	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