xref: /titanic_41/usr/src/uts/common/inet/ip/ipclassifier.c (revision e5ba14ff435beeefdaa2e6649e175c74afe02c76)
1 /*
2  * CDDL HEADER START
3  *
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 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 const char ipclassifier_version[] = "@(#)ipclassifier.c	%I%	%E% SMI";
29 
30 /*
31  * IP PACKET CLASSIFIER
32  *
33  * The IP packet classifier provides mapping between IP packets and persistent
34  * connection state for connection-oriented protocols. It also provides
35  * interface for managing connection states.
36  *
37  * The connection state is kept in conn_t data structure and contains, among
38  * other things:
39  *
40  *	o local/remote address and ports
41  *	o Transport protocol
42  *	o squeue for the connection (for TCP only)
43  *	o reference counter
44  *	o Connection state
45  *	o hash table linkage
46  *	o interface/ire information
47  *	o credentials
48  *	o ipsec policy
49  *	o send and receive functions.
50  *	o mutex lock.
51  *
52  * Connections use a reference counting scheme. They are freed when the
53  * reference counter drops to zero. A reference is incremented when connection
54  * is placed in a list or table, when incoming packet for the connection arrives
55  * and when connection is processed via squeue (squeue processing may be
56  * asynchronous and the reference protects the connection from being destroyed
57  * before its processing is finished).
58  *
59  * send and receive functions are currently used for TCP only. The send function
60  * determines the IP entry point for the packet once it leaves TCP to be sent to
61  * the destination address. The receive function is used by IP when the packet
62  * should be passed for TCP processing. When a new connection is created these
63  * are set to ip_output() and tcp_input() respectively. During the lifetime of
64  * the connection the send and receive functions may change depending on the
65  * changes in the connection state. For example, Once the connection is bound to
66  * an addresse, the receive function for this connection is set to
67  * tcp_conn_request().  This allows incoming SYNs to go directly into the
68  * listener SYN processing function without going to tcp_input() first.
69  *
70  * Classifier uses several hash tables:
71  *
72  * 	ipcl_conn_fanout:	contains all TCP connections in CONNECTED state
73  *	ipcl_bind_fanout:	contains all connections in BOUND state
74  *	ipcl_proto_fanout:	IPv4 protocol fanout
75  *	ipcl_proto_fanout_v6:	IPv6 protocol fanout
76  *	ipcl_udp_fanout:	contains all UDP connections
77  *	ipcl_globalhash_fanout:	contains all connections
78  *
79  * The ipcl_globalhash_fanout is used for any walkers (like snmp and Clustering)
80  * which need to view all existing connections.
81  *
82  * All tables are protected by per-bucket locks. When both per-bucket lock and
83  * connection lock need to be held, the per-bucket lock should be acquired
84  * first, followed by the connection lock.
85  *
86  * All functions doing search in one of these tables increment a reference
87  * counter on the connection found (if any). This reference should be dropped
88  * when the caller has finished processing the connection.
89  *
90  *
91  * INTERFACES:
92  * ===========
93  *
94  * Connection Lookup:
95  * ------------------
96  *
97  * conn_t *ipcl_classify_v4(mp, protocol, hdr_len, zoneid, ip_stack)
98  * conn_t *ipcl_classify_v6(mp, protocol, hdr_len, zoneid, ip_stack)
99  *
100  * Finds connection for an incoming IPv4 or IPv6 packet. Returns NULL if
101  * it can't find any associated connection. If the connection is found, its
102  * reference counter is incremented.
103  *
104  *	mp:	mblock, containing packet header. The full header should fit
105  *		into a single mblock. It should also contain at least full IP
106  *		and TCP or UDP header.
107  *
108  *	protocol: Either IPPROTO_TCP or IPPROTO_UDP.
109  *
110  *	hdr_len: The size of IP header. It is used to find TCP or UDP header in
111  *		 the packet.
112  *
113  * 	zoneid: The zone in which the returned connection must be; the zoneid
114  *		corresponding to the ire_zoneid on the IRE located for the
115  *		packet's destination address.
116  *
117  *	For TCP connections, the lookup order is as follows:
118  *		5-tuple {src, dst, protocol, local port, remote port}
119  *			lookup in ipcl_conn_fanout table.
120  *		3-tuple {dst, remote port, protocol} lookup in
121  *			ipcl_bind_fanout table.
122  *
123  *	For UDP connections, a 5-tuple {src, dst, protocol, local port,
124  *	remote port} lookup is done on ipcl_udp_fanout. Note that,
125  *	these interfaces do not handle cases where a packets belongs
126  *	to multiple UDP clients, which is handled in IP itself.
127  *
128  * If the destination IRE is ALL_ZONES (indicated by zoneid), then we must
129  * determine which actual zone gets the segment.  This is used only in a
130  * labeled environment.  The matching rules are:
131  *
132  *	- If it's not a multilevel port, then the label on the packet selects
133  *	  the zone.  Unlabeled packets are delivered to the global zone.
134  *
135  *	- If it's a multilevel port, then only the zone registered to receive
136  *	  packets on that port matches.
137  *
138  * Also, in a labeled environment, packet labels need to be checked.  For fully
139  * bound TCP connections, we can assume that the packet label was checked
140  * during connection establishment, and doesn't need to be checked on each
141  * packet.  For others, though, we need to check for strict equality or, for
142  * multilevel ports, membership in the range or set.  This part currently does
143  * a tnrh lookup on each packet, but could be optimized to use cached results
144  * if that were necessary.  (SCTP doesn't come through here, but if it did,
145  * we would apply the same rules as TCP.)
146  *
147  * An implication of the above is that fully-bound TCP sockets must always use
148  * distinct 4-tuples; they can't be discriminated by label alone.
149  *
150  * Note that we cannot trust labels on packets sent to fully-bound UDP sockets,
151  * as there's no connection set-up handshake and no shared state.
152  *
153  * Labels on looped-back packets within a single zone do not need to be
154  * checked, as all processes in the same zone have the same label.
155  *
156  * Finally, for unlabeled packets received by a labeled system, special rules
157  * apply.  We consider only the MLP if there is one.  Otherwise, we prefer a
158  * socket in the zone whose label matches the default label of the sender, if
159  * any.  In any event, the receiving socket must have SO_MAC_EXEMPT set and the
160  * receiver's label must dominate the sender's default label.
161  *
162  * conn_t *ipcl_tcp_lookup_reversed_ipv4(ipha_t *, tcph_t *, int, ip_stack);
163  * conn_t *ipcl_tcp_lookup_reversed_ipv6(ip6_t *, tcpha_t *, int, uint_t,
164  *					 ip_stack);
165  *
166  *	Lookup routine to find a exact match for {src, dst, local port,
167  *	remote port) for TCP connections in ipcl_conn_fanout. The address and
168  *	ports are read from the IP and TCP header respectively.
169  *
170  * conn_t	*ipcl_lookup_listener_v4(lport, laddr, protocol,
171  *					 zoneid, ip_stack);
172  * conn_t	*ipcl_lookup_listener_v6(lport, laddr, protocol, ifindex,
173  *					 zoneid, ip_stack);
174  *
175  * 	Lookup routine to find a listener with the tuple {lport, laddr,
176  * 	protocol} in the ipcl_bind_fanout table. For IPv6, an additional
177  * 	parameter interface index is also compared.
178  *
179  * void ipcl_walk(func, arg, ip_stack)
180  *
181  * 	Apply 'func' to every connection available. The 'func' is called as
182  *	(*func)(connp, arg). The walk is non-atomic so connections may be
183  *	created and destroyed during the walk. The CONN_CONDEMNED and
184  *	CONN_INCIPIENT flags ensure that connections which are newly created
185  *	or being destroyed are not selected by the walker.
186  *
187  * Table Updates
188  * -------------
189  *
190  * int ipcl_conn_insert(connp, protocol, src, dst, ports)
191  * int ipcl_conn_insert_v6(connp, protocol, src, dst, ports, ifindex)
192  *
193  *	Insert 'connp' in the ipcl_conn_fanout.
194  *	Arguements :
195  *		connp		conn_t to be inserted
196  *		protocol	connection protocol
197  *		src		source address
198  *		dst		destination address
199  *		ports		local and remote port
200  *		ifindex		interface index for IPv6 connections
201  *
202  *	Return value :
203  *		0		if connp was inserted
204  *		EADDRINUSE	if the connection with the same tuple
205  *				already exists.
206  *
207  * int ipcl_bind_insert(connp, protocol, src, lport);
208  * int ipcl_bind_insert_v6(connp, protocol, src, lport);
209  *
210  * 	Insert 'connp' in ipcl_bind_fanout.
211  * 	Arguements :
212  * 		connp		conn_t to be inserted
213  * 		protocol	connection protocol
214  * 		src		source address connection wants
215  * 				to bind to
216  * 		lport		local port connection wants to
217  * 				bind to
218  *
219  *
220  * void ipcl_hash_remove(connp);
221  *
222  * 	Removes the 'connp' from the connection fanout table.
223  *
224  * Connection Creation/Destruction
225  * -------------------------------
226  *
227  * conn_t *ipcl_conn_create(type, sleep, netstack_t *)
228  *
229  * 	Creates a new conn based on the type flag, inserts it into
230  * 	globalhash table.
231  *
232  *	type:	This flag determines the type of conn_t which needs to be
233  *		created.
234  *		IPCL_TCPCONN	indicates a TCP connection
235  *		IPCL_IPCONN	indicates all non-TCP connections.
236  *
237  * void ipcl_conn_destroy(connp)
238  *
239  * 	Destroys the connection state, removes it from the global
240  * 	connection hash table and frees its memory.
241  */
242 
243 #include <sys/types.h>
244 #include <sys/stream.h>
245 #include <sys/stropts.h>
246 #include <sys/sysmacros.h>
247 #include <sys/strsubr.h>
248 #include <sys/strsun.h>
249 #define	_SUN_TPI_VERSION 2
250 #include <sys/ddi.h>
251 #include <sys/cmn_err.h>
252 #include <sys/debug.h>
253 
254 #include <sys/systm.h>
255 #include <sys/param.h>
256 #include <sys/kmem.h>
257 #include <sys/isa_defs.h>
258 #include <inet/common.h>
259 #include <netinet/ip6.h>
260 #include <netinet/icmp6.h>
261 
262 #include <inet/ip.h>
263 #include <inet/ip6.h>
264 #include <inet/tcp.h>
265 #include <inet/ip_ndp.h>
266 #include <inet/udp_impl.h>
267 #include <inet/sctp_ip.h>
268 #include <inet/sctp/sctp_impl.h>
269 
270 #include <sys/cpuvar.h>
271 
272 #include <inet/ipclassifier.h>
273 #include <inet/ipsec_impl.h>
274 
275 #include <sys/tsol/tnet.h>
276 
277 #ifdef DEBUG
278 #define	IPCL_DEBUG
279 #else
280 #undef	IPCL_DEBUG
281 #endif
282 
283 #ifdef	IPCL_DEBUG
284 int	ipcl_debug_level = 0;
285 #define	IPCL_DEBUG_LVL(level, args)	\
286 	if (ipcl_debug_level  & level) { printf args; }
287 #else
288 #define	IPCL_DEBUG_LVL(level, args) {; }
289 #endif
290 /* Old value for compatibility. Setable in /etc/system */
291 uint_t tcp_conn_hash_size = 0;
292 
293 /* New value. Zero means choose automatically.  Setable in /etc/system */
294 uint_t ipcl_conn_hash_size = 0;
295 uint_t ipcl_conn_hash_memfactor = 8192;
296 uint_t ipcl_conn_hash_maxsize = 82500;
297 
298 /* bind/udp fanout table size */
299 uint_t ipcl_bind_fanout_size = 512;
300 uint_t ipcl_udp_fanout_size = 16384;
301 
302 /* Raw socket fanout size.  Must be a power of 2. */
303 uint_t ipcl_raw_fanout_size = 256;
304 
305 /*
306  * Power of 2^N Primes useful for hashing for N of 0-28,
307  * these primes are the nearest prime <= 2^N - 2^(N-2).
308  */
309 
310 #define	P2Ps() {0, 0, 0, 5, 11, 23, 47, 89, 191, 383, 761, 1531, 3067,	\
311 		6143, 12281, 24571, 49139, 98299, 196597, 393209,	\
312 		786431, 1572853, 3145721, 6291449, 12582893, 25165813,	\
313 		50331599, 100663291, 201326557, 0}
314 
315 /*
316  * wrapper structure to ensure that conn+tcpb are aligned
317  * on cache lines.
318  */
319 typedef struct itc_s {
320 	union {
321 		conn_t	itcu_conn;
322 		char	itcu_filler[CACHE_ALIGN(conn_s)];
323 	}	itc_u;
324 	tcp_t	itc_tcp;
325 } itc_t;
326 
327 #define	itc_conn	itc_u.itcu_conn
328 
329 struct kmem_cache  *ipcl_tcpconn_cache;
330 struct kmem_cache  *ipcl_conn_cache;
331 extern struct kmem_cache  *sctp_conn_cache;
332 extern struct kmem_cache  *tcp_sack_info_cache;
333 extern struct kmem_cache  *tcp_iphc_cache;
334 
335 extern void	tcp_timermp_free(tcp_t *);
336 extern mblk_t	*tcp_timermp_alloc(int);
337 
338 static int	ipcl_tcpconn_constructor(void *, void *, int);
339 static void	ipcl_tcpconn_destructor(void *, void *);
340 
341 #ifdef	IPCL_DEBUG
342 #define	INET_NTOA_BUFSIZE	18
343 
344 static char *
345 inet_ntoa_r(uint32_t in, char *b)
346 {
347 	unsigned char	*p;
348 
349 	p = (unsigned char *)&in;
350 	(void) sprintf(b, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
351 	return (b);
352 }
353 #endif
354 
355 /*
356  * Global (for all stack instances) init routine
357  */
358 void
359 ipcl_g_init(void)
360 {
361 	ipcl_conn_cache = kmem_cache_create("ipcl_conn_cache",
362 	    sizeof (conn_t), CACHE_ALIGN_SIZE,
363 	    NULL, NULL, NULL, NULL, NULL, 0);
364 
365 	ipcl_tcpconn_cache = kmem_cache_create("ipcl_tcpconn_cache",
366 	    sizeof (itc_t), CACHE_ALIGN_SIZE,
367 	    ipcl_tcpconn_constructor, ipcl_tcpconn_destructor,
368 	    NULL, NULL, NULL, 0);
369 }
370 
371 /*
372  * ipclassifier intialization routine, sets up hash tables.
373  */
374 void
375 ipcl_init(ip_stack_t *ipst)
376 {
377 	int i;
378 	int sizes[] = P2Ps();
379 
380 	/*
381 	 * Calculate size of conn fanout table from /etc/system settings
382 	 */
383 	if (ipcl_conn_hash_size != 0) {
384 		ipst->ips_ipcl_conn_fanout_size = ipcl_conn_hash_size;
385 	} else if (tcp_conn_hash_size != 0) {
386 		ipst->ips_ipcl_conn_fanout_size = tcp_conn_hash_size;
387 	} else {
388 		extern pgcnt_t freemem;
389 
390 		ipst->ips_ipcl_conn_fanout_size =
391 		    (freemem * PAGESIZE) / ipcl_conn_hash_memfactor;
392 
393 		if (ipst->ips_ipcl_conn_fanout_size > ipcl_conn_hash_maxsize) {
394 			ipst->ips_ipcl_conn_fanout_size =
395 			    ipcl_conn_hash_maxsize;
396 		}
397 	}
398 
399 	for (i = 9; i < sizeof (sizes) / sizeof (*sizes) - 1; i++) {
400 		if (sizes[i] >= ipst->ips_ipcl_conn_fanout_size) {
401 			break;
402 		}
403 	}
404 	if ((ipst->ips_ipcl_conn_fanout_size = sizes[i]) == 0) {
405 		/* Out of range, use the 2^16 value */
406 		ipst->ips_ipcl_conn_fanout_size = sizes[16];
407 	}
408 
409 	/* Take values from /etc/system */
410 	ipst->ips_ipcl_bind_fanout_size = ipcl_bind_fanout_size;
411 	ipst->ips_ipcl_udp_fanout_size = ipcl_udp_fanout_size;
412 	ipst->ips_ipcl_raw_fanout_size = ipcl_raw_fanout_size;
413 
414 	ASSERT(ipst->ips_ipcl_conn_fanout == NULL);
415 
416 	ipst->ips_ipcl_conn_fanout = kmem_zalloc(
417 	    ipst->ips_ipcl_conn_fanout_size * sizeof (connf_t), KM_SLEEP);
418 
419 	for (i = 0; i < ipst->ips_ipcl_conn_fanout_size; i++) {
420 		mutex_init(&ipst->ips_ipcl_conn_fanout[i].connf_lock, NULL,
421 		    MUTEX_DEFAULT, NULL);
422 	}
423 
424 	ipst->ips_ipcl_bind_fanout = kmem_zalloc(
425 	    ipst->ips_ipcl_bind_fanout_size * sizeof (connf_t), KM_SLEEP);
426 
427 	for (i = 0; i < ipst->ips_ipcl_bind_fanout_size; i++) {
428 		mutex_init(&ipst->ips_ipcl_bind_fanout[i].connf_lock, NULL,
429 		    MUTEX_DEFAULT, NULL);
430 	}
431 
432 	ipst->ips_ipcl_proto_fanout = kmem_zalloc(IPPROTO_MAX *
433 	    sizeof (connf_t), KM_SLEEP);
434 	for (i = 0; i < IPPROTO_MAX; i++) {
435 		mutex_init(&ipst->ips_ipcl_proto_fanout[i].connf_lock, NULL,
436 		    MUTEX_DEFAULT, NULL);
437 	}
438 
439 	ipst->ips_ipcl_proto_fanout_v6 = kmem_zalloc(IPPROTO_MAX *
440 	    sizeof (connf_t), KM_SLEEP);
441 	for (i = 0; i < IPPROTO_MAX; i++) {
442 		mutex_init(&ipst->ips_ipcl_proto_fanout_v6[i].connf_lock, NULL,
443 		    MUTEX_DEFAULT, NULL);
444 	}
445 
446 	ipst->ips_rts_clients = kmem_zalloc(sizeof (connf_t), KM_SLEEP);
447 	mutex_init(&ipst->ips_rts_clients->connf_lock,
448 	    NULL, MUTEX_DEFAULT, NULL);
449 
450 	ipst->ips_ipcl_udp_fanout = kmem_zalloc(
451 	    ipst->ips_ipcl_udp_fanout_size * sizeof (connf_t), KM_SLEEP);
452 	for (i = 0; i < ipst->ips_ipcl_udp_fanout_size; i++) {
453 		mutex_init(&ipst->ips_ipcl_udp_fanout[i].connf_lock, NULL,
454 		    MUTEX_DEFAULT, NULL);
455 	}
456 
457 	ipst->ips_ipcl_raw_fanout = kmem_zalloc(
458 	    ipst->ips_ipcl_raw_fanout_size * sizeof (connf_t), KM_SLEEP);
459 	for (i = 0; i < ipst->ips_ipcl_raw_fanout_size; i++) {
460 		mutex_init(&ipst->ips_ipcl_raw_fanout[i].connf_lock, NULL,
461 		    MUTEX_DEFAULT, NULL);
462 	}
463 
464 	ipst->ips_ipcl_globalhash_fanout = kmem_zalloc(
465 	    sizeof (connf_t) * CONN_G_HASH_SIZE, KM_SLEEP);
466 	for (i = 0; i < CONN_G_HASH_SIZE; i++) {
467 		mutex_init(&ipst->ips_ipcl_globalhash_fanout[i].connf_lock,
468 		    NULL, MUTEX_DEFAULT, NULL);
469 	}
470 }
471 
472 void
473 ipcl_g_destroy(void)
474 {
475 	kmem_cache_destroy(ipcl_conn_cache);
476 	kmem_cache_destroy(ipcl_tcpconn_cache);
477 }
478 
479 /*
480  * All user-level and kernel use of the stack must be gone
481  * by now.
482  */
483 void
484 ipcl_destroy(ip_stack_t *ipst)
485 {
486 	int i;
487 
488 	for (i = 0; i < ipst->ips_ipcl_conn_fanout_size; i++) {
489 		ASSERT(ipst->ips_ipcl_conn_fanout[i].connf_head == NULL);
490 		mutex_destroy(&ipst->ips_ipcl_conn_fanout[i].connf_lock);
491 	}
492 	kmem_free(ipst->ips_ipcl_conn_fanout, ipst->ips_ipcl_conn_fanout_size *
493 	    sizeof (connf_t));
494 	ipst->ips_ipcl_conn_fanout = NULL;
495 
496 	for (i = 0; i < ipst->ips_ipcl_bind_fanout_size; i++) {
497 		ASSERT(ipst->ips_ipcl_bind_fanout[i].connf_head == NULL);
498 		mutex_destroy(&ipst->ips_ipcl_bind_fanout[i].connf_lock);
499 	}
500 	kmem_free(ipst->ips_ipcl_bind_fanout, ipst->ips_ipcl_bind_fanout_size *
501 	    sizeof (connf_t));
502 	ipst->ips_ipcl_bind_fanout = NULL;
503 
504 	for (i = 0; i < IPPROTO_MAX; i++) {
505 		ASSERT(ipst->ips_ipcl_proto_fanout[i].connf_head == NULL);
506 		mutex_destroy(&ipst->ips_ipcl_proto_fanout[i].connf_lock);
507 	}
508 	kmem_free(ipst->ips_ipcl_proto_fanout, IPPROTO_MAX * sizeof (connf_t));
509 	ipst->ips_ipcl_proto_fanout = NULL;
510 
511 	for (i = 0; i < IPPROTO_MAX; i++) {
512 		ASSERT(ipst->ips_ipcl_proto_fanout_v6[i].connf_head == NULL);
513 		mutex_destroy(&ipst->ips_ipcl_proto_fanout_v6[i].connf_lock);
514 	}
515 	kmem_free(ipst->ips_ipcl_proto_fanout_v6,
516 	    IPPROTO_MAX * sizeof (connf_t));
517 	ipst->ips_ipcl_proto_fanout_v6 = NULL;
518 
519 	for (i = 0; i < ipst->ips_ipcl_udp_fanout_size; i++) {
520 		ASSERT(ipst->ips_ipcl_udp_fanout[i].connf_head == NULL);
521 		mutex_destroy(&ipst->ips_ipcl_udp_fanout[i].connf_lock);
522 	}
523 	kmem_free(ipst->ips_ipcl_udp_fanout, ipst->ips_ipcl_udp_fanout_size *
524 	    sizeof (connf_t));
525 	ipst->ips_ipcl_udp_fanout = NULL;
526 
527 	for (i = 0; i < ipst->ips_ipcl_raw_fanout_size; i++) {
528 		ASSERT(ipst->ips_ipcl_raw_fanout[i].connf_head == NULL);
529 		mutex_destroy(&ipst->ips_ipcl_raw_fanout[i].connf_lock);
530 	}
531 	kmem_free(ipst->ips_ipcl_raw_fanout, ipst->ips_ipcl_raw_fanout_size *
532 	    sizeof (connf_t));
533 	ipst->ips_ipcl_raw_fanout = NULL;
534 
535 	for (i = 0; i < CONN_G_HASH_SIZE; i++) {
536 		ASSERT(ipst->ips_ipcl_globalhash_fanout[i].connf_head == NULL);
537 		mutex_destroy(&ipst->ips_ipcl_globalhash_fanout[i].connf_lock);
538 	}
539 	kmem_free(ipst->ips_ipcl_globalhash_fanout,
540 	    sizeof (connf_t) * CONN_G_HASH_SIZE);
541 	ipst->ips_ipcl_globalhash_fanout = NULL;
542 
543 	ASSERT(ipst->ips_rts_clients->connf_head == NULL);
544 	mutex_destroy(&ipst->ips_rts_clients->connf_lock);
545 	kmem_free(ipst->ips_rts_clients, sizeof (connf_t));
546 	ipst->ips_rts_clients = NULL;
547 }
548 
549 /*
550  * conn creation routine. initialize the conn, sets the reference
551  * and inserts it in the global hash table.
552  */
553 conn_t *
554 ipcl_conn_create(uint32_t type, int sleep, netstack_t *ns)
555 {
556 	itc_t	*itc;
557 	conn_t	*connp;
558 	sctp_stack_t *sctps;
559 
560 	switch (type) {
561 	case IPCL_TCPCONN:
562 		if ((itc = kmem_cache_alloc(ipcl_tcpconn_cache,
563 		    sleep)) == NULL)
564 			return (NULL);
565 		connp = &itc->itc_conn;
566 		connp->conn_ref = 1;
567 		netstack_hold(ns);
568 		connp->conn_netstack = ns;
569 		IPCL_DEBUG_LVL(1,
570 		    ("ipcl_conn_create: connp = %p tcp (%p)",
571 		    (void *)connp, (void *)connp->conn_tcp));
572 		ipcl_globalhash_insert(connp);
573 		break;
574 	case IPCL_SCTPCONN:
575 		if ((connp = kmem_cache_alloc(sctp_conn_cache, sleep)) == NULL)
576 			return (NULL);
577 		sctp_conn_init(connp);
578 		sctps = ns->netstack_sctp;
579 		SCTP_G_Q_REFHOLD(sctps);
580 		netstack_hold(ns);
581 		connp->conn_netstack = ns;
582 		break;
583 	case IPCL_IPCCONN:
584 		connp = kmem_cache_alloc(ipcl_conn_cache, sleep);
585 		if (connp == NULL)
586 			return (NULL);
587 		bzero(connp, sizeof (conn_t));
588 		mutex_init(&connp->conn_lock, NULL, MUTEX_DEFAULT, NULL);
589 		cv_init(&connp->conn_cv, NULL, CV_DEFAULT, NULL);
590 		connp->conn_flags = IPCL_IPCCONN;
591 		connp->conn_ref = 1;
592 		netstack_hold(ns);
593 		connp->conn_netstack = ns;
594 		IPCL_DEBUG_LVL(1,
595 		    ("ipcl_conn_create: connp = %p\n", (void *)connp));
596 		ipcl_globalhash_insert(connp);
597 		break;
598 	default:
599 		connp = NULL;
600 		ASSERT(0);
601 	}
602 
603 	return (connp);
604 }
605 
606 void
607 ipcl_conn_destroy(conn_t *connp)
608 {
609 	mblk_t	*mp;
610 	netstack_t	*ns = connp->conn_netstack;
611 
612 	ASSERT(!MUTEX_HELD(&connp->conn_lock));
613 	ASSERT(connp->conn_ref == 0);
614 	ASSERT(connp->conn_ire_cache == NULL);
615 
616 	if (connp->conn_peercred != NULL &&
617 	    connp->conn_peercred != connp->conn_cred)
618 		crfree(connp->conn_peercred);
619 	connp->conn_peercred = NULL;
620 
621 	if (connp->conn_cred != NULL) {
622 		crfree(connp->conn_cred);
623 		connp->conn_cred = NULL;
624 	}
625 
626 	ipcl_globalhash_remove(connp);
627 
628 	cv_destroy(&connp->conn_cv);
629 	if (connp->conn_flags & IPCL_TCPCONN) {
630 		tcp_t	*tcp = connp->conn_tcp;
631 		tcp_stack_t *tcps;
632 
633 		ASSERT(tcp != NULL);
634 		tcps = tcp->tcp_tcps;
635 		if (tcps != NULL) {
636 			if (connp->conn_latch != NULL) {
637 				IPLATCH_REFRELE(connp->conn_latch, ns);
638 				connp->conn_latch = NULL;
639 			}
640 			if (connp->conn_policy != NULL) {
641 				IPPH_REFRELE(connp->conn_policy, ns);
642 				connp->conn_policy = NULL;
643 			}
644 			tcp->tcp_tcps = NULL;
645 			TCPS_REFRELE(tcps);
646 		}
647 
648 		mutex_destroy(&connp->conn_lock);
649 		tcp_free(tcp);
650 		mp = tcp->tcp_timercache;
651 		tcp->tcp_cred = NULL;
652 
653 		if (tcp->tcp_sack_info != NULL) {
654 			bzero(tcp->tcp_sack_info, sizeof (tcp_sack_info_t));
655 			kmem_cache_free(tcp_sack_info_cache,
656 			    tcp->tcp_sack_info);
657 		}
658 		if (tcp->tcp_iphc != NULL) {
659 			if (tcp->tcp_hdr_grown) {
660 				kmem_free(tcp->tcp_iphc, tcp->tcp_iphc_len);
661 			} else {
662 				bzero(tcp->tcp_iphc, tcp->tcp_iphc_len);
663 				kmem_cache_free(tcp_iphc_cache, tcp->tcp_iphc);
664 			}
665 			tcp->tcp_iphc_len = 0;
666 		}
667 		ASSERT(tcp->tcp_iphc_len == 0);
668 
669 		ASSERT(connp->conn_latch == NULL);
670 		ASSERT(connp->conn_policy == NULL);
671 
672 		bzero(connp, sizeof (itc_t));
673 
674 		tcp->tcp_timercache = mp;
675 		connp->conn_tcp = tcp;
676 		connp->conn_flags = IPCL_TCPCONN;
677 		connp->conn_ulp = IPPROTO_TCP;
678 		tcp->tcp_connp = connp;
679 		if (ns != NULL) {
680 			ASSERT(tcp->tcp_tcps == NULL);
681 			connp->conn_netstack = NULL;
682 			netstack_rele(ns);
683 		}
684 		kmem_cache_free(ipcl_tcpconn_cache, connp);
685 	} else if (connp->conn_flags & IPCL_SCTPCONN) {
686 		ASSERT(ns != NULL);
687 		sctp_free(connp);
688 	} else {
689 		ASSERT(connp->conn_udp == NULL);
690 		mutex_destroy(&connp->conn_lock);
691 		if (ns != NULL) {
692 			connp->conn_netstack = NULL;
693 			netstack_rele(ns);
694 		}
695 		kmem_cache_free(ipcl_conn_cache, connp);
696 	}
697 }
698 
699 /*
700  * Running in cluster mode - deregister listener information
701  */
702 
703 static void
704 ipcl_conn_unlisten(conn_t *connp)
705 {
706 	ASSERT((connp->conn_flags & IPCL_CL_LISTENER) != 0);
707 	ASSERT(connp->conn_lport != 0);
708 
709 	if (cl_inet_unlisten != NULL) {
710 		sa_family_t	addr_family;
711 		uint8_t		*laddrp;
712 
713 		if (connp->conn_pkt_isv6) {
714 			addr_family = AF_INET6;
715 			laddrp = (uint8_t *)&connp->conn_bound_source_v6;
716 		} else {
717 			addr_family = AF_INET;
718 			laddrp = (uint8_t *)&connp->conn_bound_source;
719 		}
720 		(*cl_inet_unlisten)(IPPROTO_TCP, addr_family, laddrp,
721 		    connp->conn_lport);
722 	}
723 	connp->conn_flags &= ~IPCL_CL_LISTENER;
724 }
725 
726 /*
727  * We set the IPCL_REMOVED flag (instead of clearing the flag indicating
728  * which table the conn belonged to). So for debugging we can see which hash
729  * table this connection was in.
730  */
731 #define	IPCL_HASH_REMOVE(connp)	{					\
732 	connf_t	*connfp = (connp)->conn_fanout;				\
733 	ASSERT(!MUTEX_HELD(&((connp)->conn_lock)));			\
734 	if (connfp != NULL) {						\
735 		IPCL_DEBUG_LVL(4, ("IPCL_HASH_REMOVE: connp %p",	\
736 		    (void *)(connp)));					\
737 		mutex_enter(&connfp->connf_lock);			\
738 		if ((connp)->conn_next != NULL)				\
739 			(connp)->conn_next->conn_prev =			\
740 			    (connp)->conn_prev;				\
741 		if ((connp)->conn_prev != NULL)				\
742 			(connp)->conn_prev->conn_next =			\
743 			    (connp)->conn_next;				\
744 		else							\
745 			connfp->connf_head = (connp)->conn_next;	\
746 		(connp)->conn_fanout = NULL;				\
747 		(connp)->conn_next = NULL;				\
748 		(connp)->conn_prev = NULL;				\
749 		(connp)->conn_flags |= IPCL_REMOVED;			\
750 		if (((connp)->conn_flags & IPCL_CL_LISTENER) != 0)	\
751 			ipcl_conn_unlisten((connp));			\
752 		CONN_DEC_REF((connp));					\
753 		mutex_exit(&connfp->connf_lock);			\
754 	}								\
755 }
756 
757 void
758 ipcl_hash_remove(conn_t *connp)
759 {
760 	IPCL_HASH_REMOVE(connp);
761 }
762 
763 /*
764  * The whole purpose of this function is allow removal of
765  * a conn_t from the connected hash for timewait reclaim.
766  * This is essentially a TW reclaim fastpath where timewait
767  * collector checks under fanout lock (so no one else can
768  * get access to the conn_t) that refcnt is 2 i.e. one for
769  * TCP and one for the classifier hash list. If ref count
770  * is indeed 2, we can just remove the conn under lock and
771  * avoid cleaning up the conn under squeue. This gives us
772  * improved performance.
773  */
774 void
775 ipcl_hash_remove_locked(conn_t *connp, connf_t	*connfp)
776 {
777 	ASSERT(MUTEX_HELD(&connfp->connf_lock));
778 	ASSERT(MUTEX_HELD(&connp->conn_lock));
779 	ASSERT((connp->conn_flags & IPCL_CL_LISTENER) == 0);
780 
781 	if ((connp)->conn_next != NULL) {
782 		(connp)->conn_next->conn_prev = (connp)->conn_prev;
783 	}
784 	if ((connp)->conn_prev != NULL) {
785 		(connp)->conn_prev->conn_next = (connp)->conn_next;
786 	} else {
787 		connfp->connf_head = (connp)->conn_next;
788 	}
789 	(connp)->conn_fanout = NULL;
790 	(connp)->conn_next = NULL;
791 	(connp)->conn_prev = NULL;
792 	(connp)->conn_flags |= IPCL_REMOVED;
793 	ASSERT((connp)->conn_ref == 2);
794 	(connp)->conn_ref--;
795 }
796 
797 #define	IPCL_HASH_INSERT_CONNECTED_LOCKED(connfp, connp) {		\
798 	ASSERT((connp)->conn_fanout == NULL);				\
799 	ASSERT((connp)->conn_next == NULL);				\
800 	ASSERT((connp)->conn_prev == NULL);				\
801 	if ((connfp)->connf_head != NULL) {				\
802 		(connfp)->connf_head->conn_prev = (connp);		\
803 		(connp)->conn_next = (connfp)->connf_head;		\
804 	}								\
805 	(connp)->conn_fanout = (connfp);				\
806 	(connfp)->connf_head = (connp);					\
807 	(connp)->conn_flags = ((connp)->conn_flags & ~IPCL_REMOVED) |	\
808 	    IPCL_CONNECTED;						\
809 	CONN_INC_REF(connp);						\
810 }
811 
812 #define	IPCL_HASH_INSERT_CONNECTED(connfp, connp) {			\
813 	IPCL_DEBUG_LVL(8, ("IPCL_HASH_INSERT_CONNECTED: connfp %p "	\
814 	    "connp %p", (void *)(connfp), (void *)(connp)));		\
815 	IPCL_HASH_REMOVE((connp));					\
816 	mutex_enter(&(connfp)->connf_lock);				\
817 	IPCL_HASH_INSERT_CONNECTED_LOCKED(connfp, connp);		\
818 	mutex_exit(&(connfp)->connf_lock);				\
819 }
820 
821 #define	IPCL_HASH_INSERT_BOUND(connfp, connp) {				\
822 	conn_t *pconnp = NULL, *nconnp;					\
823 	IPCL_DEBUG_LVL(32, ("IPCL_HASH_INSERT_BOUND: connfp %p "	\
824 	    "connp %p", (void *)connfp, (void *)(connp)));		\
825 	IPCL_HASH_REMOVE((connp));					\
826 	mutex_enter(&(connfp)->connf_lock);				\
827 	nconnp = (connfp)->connf_head;					\
828 	while (nconnp != NULL &&					\
829 	    !_IPCL_V4_MATCH_ANY(nconnp->conn_srcv6)) {			\
830 		pconnp = nconnp;					\
831 		nconnp = nconnp->conn_next;				\
832 	}								\
833 	if (pconnp != NULL) {						\
834 		pconnp->conn_next = (connp);				\
835 		(connp)->conn_prev = pconnp;				\
836 	} else {							\
837 		(connfp)->connf_head = (connp);				\
838 	}								\
839 	if (nconnp != NULL) {						\
840 		(connp)->conn_next = nconnp;				\
841 		nconnp->conn_prev = (connp);				\
842 	}								\
843 	(connp)->conn_fanout = (connfp);				\
844 	(connp)->conn_flags = ((connp)->conn_flags & ~IPCL_REMOVED) |	\
845 	    IPCL_BOUND;							\
846 	CONN_INC_REF(connp);						\
847 	mutex_exit(&(connfp)->connf_lock);				\
848 }
849 
850 #define	IPCL_HASH_INSERT_WILDCARD(connfp, connp) {			\
851 	conn_t **list, *prev, *next;					\
852 	boolean_t isv4mapped =						\
853 	    IN6_IS_ADDR_V4MAPPED(&(connp)->conn_srcv6);			\
854 	IPCL_DEBUG_LVL(32, ("IPCL_HASH_INSERT_WILDCARD: connfp %p "	\
855 	    "connp %p", (void *)(connfp), (void *)(connp)));		\
856 	IPCL_HASH_REMOVE((connp));					\
857 	mutex_enter(&(connfp)->connf_lock);				\
858 	list = &(connfp)->connf_head;					\
859 	prev = NULL;							\
860 	while ((next = *list) != NULL) {				\
861 		if (isv4mapped &&					\
862 		    IN6_IS_ADDR_UNSPECIFIED(&next->conn_srcv6) &&	\
863 		    connp->conn_zoneid == next->conn_zoneid) {		\
864 			(connp)->conn_next = next;			\
865 			if (prev != NULL)				\
866 				prev = next->conn_prev;			\
867 			next->conn_prev = (connp);			\
868 			break;						\
869 		}							\
870 		list = &next->conn_next;				\
871 		prev = next;						\
872 	}								\
873 	(connp)->conn_prev = prev;					\
874 	*list = (connp);						\
875 	(connp)->conn_fanout = (connfp);				\
876 	(connp)->conn_flags = ((connp)->conn_flags & ~IPCL_REMOVED) |	\
877 	    IPCL_BOUND;							\
878 	CONN_INC_REF((connp));						\
879 	mutex_exit(&(connfp)->connf_lock);				\
880 }
881 
882 void
883 ipcl_hash_insert_wildcard(connf_t *connfp, conn_t *connp)
884 {
885 	IPCL_HASH_INSERT_WILDCARD(connfp, connp);
886 }
887 
888 void
889 ipcl_proto_insert(conn_t *connp, uint8_t protocol)
890 {
891 	connf_t	*connfp;
892 	ip_stack_t	*ipst = connp->conn_netstack->netstack_ip;
893 
894 	ASSERT(connp != NULL);
895 	ASSERT(!connp->conn_mac_exempt || protocol == IPPROTO_AH ||
896 	    protocol == IPPROTO_ESP);
897 
898 	connp->conn_ulp = protocol;
899 
900 	/* Insert it in the protocol hash */
901 	connfp = &ipst->ips_ipcl_proto_fanout[protocol];
902 	IPCL_HASH_INSERT_WILDCARD(connfp, connp);
903 }
904 
905 void
906 ipcl_proto_insert_v6(conn_t *connp, uint8_t protocol)
907 {
908 	connf_t	*connfp;
909 	ip_stack_t	*ipst = connp->conn_netstack->netstack_ip;
910 
911 	ASSERT(connp != NULL);
912 	ASSERT(!connp->conn_mac_exempt || protocol == IPPROTO_AH ||
913 	    protocol == IPPROTO_ESP);
914 
915 	connp->conn_ulp = protocol;
916 
917 	/* Insert it in the Bind Hash */
918 	connfp = &ipst->ips_ipcl_proto_fanout_v6[protocol];
919 	IPCL_HASH_INSERT_WILDCARD(connfp, connp);
920 }
921 
922 /*
923  * This function is used only for inserting SCTP raw socket now.
924  * This may change later.
925  *
926  * Note that only one raw socket can be bound to a port.  The param
927  * lport is in network byte order.
928  */
929 static int
930 ipcl_sctp_hash_insert(conn_t *connp, in_port_t lport)
931 {
932 	connf_t	*connfp;
933 	conn_t	*oconnp;
934 	ip_stack_t	*ipst = connp->conn_netstack->netstack_ip;
935 
936 	connfp = &ipst->ips_ipcl_raw_fanout[IPCL_RAW_HASH(ntohs(lport), ipst)];
937 
938 	/* Check for existing raw socket already bound to the port. */
939 	mutex_enter(&connfp->connf_lock);
940 	for (oconnp = connfp->connf_head; oconnp != NULL;
941 	    oconnp = oconnp->conn_next) {
942 		if (oconnp->conn_lport == lport &&
943 		    oconnp->conn_zoneid == connp->conn_zoneid &&
944 		    oconnp->conn_af_isv6 == connp->conn_af_isv6 &&
945 		    ((IN6_IS_ADDR_UNSPECIFIED(&connp->conn_srcv6) ||
946 		    IN6_IS_ADDR_UNSPECIFIED(&oconnp->conn_srcv6) ||
947 		    IN6_IS_ADDR_V4MAPPED_ANY(&connp->conn_srcv6) ||
948 		    IN6_IS_ADDR_V4MAPPED_ANY(&oconnp->conn_srcv6)) ||
949 		    IN6_ARE_ADDR_EQUAL(&oconnp->conn_srcv6,
950 		    &connp->conn_srcv6))) {
951 			break;
952 		}
953 	}
954 	mutex_exit(&connfp->connf_lock);
955 	if (oconnp != NULL)
956 		return (EADDRNOTAVAIL);
957 
958 	if (IN6_IS_ADDR_UNSPECIFIED(&connp->conn_remv6) ||
959 	    IN6_IS_ADDR_V4MAPPED_ANY(&connp->conn_remv6)) {
960 		if (IN6_IS_ADDR_UNSPECIFIED(&connp->conn_srcv6) ||
961 		    IN6_IS_ADDR_V4MAPPED_ANY(&connp->conn_srcv6)) {
962 			IPCL_HASH_INSERT_WILDCARD(connfp, connp);
963 		} else {
964 			IPCL_HASH_INSERT_BOUND(connfp, connp);
965 		}
966 	} else {
967 		IPCL_HASH_INSERT_CONNECTED(connfp, connp);
968 	}
969 	return (0);
970 }
971 
972 /*
973  * Check for a MAC exemption conflict on a labeled system.  Note that for
974  * protocols that use port numbers (UDP, TCP, SCTP), we do this check up in the
975  * transport layer.  This check is for binding all other protocols.
976  *
977  * Returns true if there's a conflict.
978  */
979 static boolean_t
980 check_exempt_conflict_v4(conn_t *connp, ip_stack_t *ipst)
981 {
982 	connf_t	*connfp;
983 	conn_t *tconn;
984 
985 	connfp = &ipst->ips_ipcl_proto_fanout[connp->conn_ulp];
986 	mutex_enter(&connfp->connf_lock);
987 	for (tconn = connfp->connf_head; tconn != NULL;
988 	    tconn = tconn->conn_next) {
989 		/* We don't allow v4 fallback for v6 raw socket */
990 		if (connp->conn_af_isv6 != tconn->conn_af_isv6)
991 			continue;
992 		/* If neither is exempt, then there's no conflict */
993 		if (!connp->conn_mac_exempt && !tconn->conn_mac_exempt)
994 			continue;
995 		/* If both are bound to different specific addrs, ok */
996 		if (connp->conn_src != INADDR_ANY &&
997 		    tconn->conn_src != INADDR_ANY &&
998 		    connp->conn_src != tconn->conn_src)
999 			continue;
1000 		/* These two conflict; fail */
1001 		break;
1002 	}
1003 	mutex_exit(&connfp->connf_lock);
1004 	return (tconn != NULL);
1005 }
1006 
1007 static boolean_t
1008 check_exempt_conflict_v6(conn_t *connp, ip_stack_t *ipst)
1009 {
1010 	connf_t	*connfp;
1011 	conn_t *tconn;
1012 
1013 	connfp = &ipst->ips_ipcl_proto_fanout[connp->conn_ulp];
1014 	mutex_enter(&connfp->connf_lock);
1015 	for (tconn = connfp->connf_head; tconn != NULL;
1016 	    tconn = tconn->conn_next) {
1017 		/* We don't allow v4 fallback for v6 raw socket */
1018 		if (connp->conn_af_isv6 != tconn->conn_af_isv6)
1019 			continue;
1020 		/* If neither is exempt, then there's no conflict */
1021 		if (!connp->conn_mac_exempt && !tconn->conn_mac_exempt)
1022 			continue;
1023 		/* If both are bound to different addrs, ok */
1024 		if (!IN6_IS_ADDR_UNSPECIFIED(&connp->conn_srcv6) &&
1025 		    !IN6_IS_ADDR_UNSPECIFIED(&tconn->conn_srcv6) &&
1026 		    !IN6_ARE_ADDR_EQUAL(&connp->conn_srcv6, &tconn->conn_srcv6))
1027 			continue;
1028 		/* These two conflict; fail */
1029 		break;
1030 	}
1031 	mutex_exit(&connfp->connf_lock);
1032 	return (tconn != NULL);
1033 }
1034 
1035 /*
1036  * (v4, v6) bind hash insertion routines
1037  */
1038 int
1039 ipcl_bind_insert(conn_t *connp, uint8_t protocol, ipaddr_t src, uint16_t lport)
1040 {
1041 	connf_t	*connfp;
1042 #ifdef	IPCL_DEBUG
1043 	char	buf[INET_NTOA_BUFSIZE];
1044 #endif
1045 	int	ret = 0;
1046 	ip_stack_t	*ipst = connp->conn_netstack->netstack_ip;
1047 
1048 	ASSERT(connp);
1049 
1050 	IPCL_DEBUG_LVL(64, ("ipcl_bind_insert: connp %p, src = %s, "
1051 	    "port = %d\n", (void *)connp, inet_ntoa_r(src, buf), lport));
1052 
1053 	connp->conn_ulp = protocol;
1054 	IN6_IPADDR_TO_V4MAPPED(src, &connp->conn_srcv6);
1055 	connp->conn_lport = lport;
1056 
1057 	switch (protocol) {
1058 	default:
1059 		if (is_system_labeled() &&
1060 		    check_exempt_conflict_v4(connp, ipst))
1061 			return (EADDRINUSE);
1062 		/* FALLTHROUGH */
1063 	case IPPROTO_UDP:
1064 		if (protocol == IPPROTO_UDP) {
1065 			IPCL_DEBUG_LVL(64,
1066 			    ("ipcl_bind_insert: connp %p - udp\n",
1067 			    (void *)connp));
1068 			connfp = &ipst->ips_ipcl_udp_fanout[
1069 			    IPCL_UDP_HASH(lport, ipst)];
1070 		} else {
1071 			IPCL_DEBUG_LVL(64,
1072 			    ("ipcl_bind_insert: connp %p - protocol\n",
1073 			    (void *)connp));
1074 			connfp = &ipst->ips_ipcl_proto_fanout[protocol];
1075 		}
1076 
1077 		if (connp->conn_rem != INADDR_ANY) {
1078 			IPCL_HASH_INSERT_CONNECTED(connfp, connp);
1079 		} else if (connp->conn_src != INADDR_ANY) {
1080 			IPCL_HASH_INSERT_BOUND(connfp, connp);
1081 		} else {
1082 			IPCL_HASH_INSERT_WILDCARD(connfp, connp);
1083 		}
1084 		break;
1085 
1086 	case IPPROTO_TCP:
1087 
1088 		/* Insert it in the Bind Hash */
1089 		ASSERT(connp->conn_zoneid != ALL_ZONES);
1090 		connfp = &ipst->ips_ipcl_bind_fanout[
1091 		    IPCL_BIND_HASH(lport, ipst)];
1092 		if (connp->conn_src != INADDR_ANY) {
1093 			IPCL_HASH_INSERT_BOUND(connfp, connp);
1094 		} else {
1095 			IPCL_HASH_INSERT_WILDCARD(connfp, connp);
1096 		}
1097 		if (cl_inet_listen != NULL) {
1098 			ASSERT(!connp->conn_pkt_isv6);
1099 			connp->conn_flags |= IPCL_CL_LISTENER;
1100 			(*cl_inet_listen)(IPPROTO_TCP, AF_INET,
1101 			    (uint8_t *)&connp->conn_bound_source, lport);
1102 		}
1103 		break;
1104 
1105 	case IPPROTO_SCTP:
1106 		ret = ipcl_sctp_hash_insert(connp, lport);
1107 		break;
1108 	}
1109 
1110 	return (ret);
1111 }
1112 
1113 int
1114 ipcl_bind_insert_v6(conn_t *connp, uint8_t protocol, const in6_addr_t *src,
1115     uint16_t lport)
1116 {
1117 	connf_t	*connfp;
1118 	int	ret = 0;
1119 	ip_stack_t	*ipst = connp->conn_netstack->netstack_ip;
1120 
1121 	ASSERT(connp);
1122 
1123 	connp->conn_ulp = protocol;
1124 	connp->conn_srcv6 = *src;
1125 	connp->conn_lport = lport;
1126 
1127 	switch (protocol) {
1128 	default:
1129 		if (is_system_labeled() &&
1130 		    check_exempt_conflict_v6(connp, ipst))
1131 			return (EADDRINUSE);
1132 		/* FALLTHROUGH */
1133 	case IPPROTO_UDP:
1134 		if (protocol == IPPROTO_UDP) {
1135 			IPCL_DEBUG_LVL(128,
1136 			    ("ipcl_bind_insert_v6: connp %p - udp\n",
1137 			    (void *)connp));
1138 			connfp = &ipst->ips_ipcl_udp_fanout[
1139 			    IPCL_UDP_HASH(lport, ipst)];
1140 		} else {
1141 			IPCL_DEBUG_LVL(128,
1142 			    ("ipcl_bind_insert_v6: connp %p - protocol\n",
1143 			    (void *)connp));
1144 			connfp = &ipst->ips_ipcl_proto_fanout_v6[protocol];
1145 		}
1146 
1147 		if (!IN6_IS_ADDR_UNSPECIFIED(&connp->conn_remv6)) {
1148 			IPCL_HASH_INSERT_CONNECTED(connfp, connp);
1149 		} else if (!IN6_IS_ADDR_UNSPECIFIED(&connp->conn_srcv6)) {
1150 			IPCL_HASH_INSERT_BOUND(connfp, connp);
1151 		} else {
1152 			IPCL_HASH_INSERT_WILDCARD(connfp, connp);
1153 		}
1154 		break;
1155 
1156 	case IPPROTO_TCP:
1157 		/* XXX - Need a separate table for IN6_IS_ADDR_UNSPECIFIED? */
1158 
1159 		/* Insert it in the Bind Hash */
1160 		ASSERT(connp->conn_zoneid != ALL_ZONES);
1161 		connfp = &ipst->ips_ipcl_bind_fanout[
1162 		    IPCL_BIND_HASH(lport, ipst)];
1163 		if (!IN6_IS_ADDR_UNSPECIFIED(&connp->conn_srcv6)) {
1164 			IPCL_HASH_INSERT_BOUND(connfp, connp);
1165 		} else {
1166 			IPCL_HASH_INSERT_WILDCARD(connfp, connp);
1167 		}
1168 		if (cl_inet_listen != NULL) {
1169 			sa_family_t	addr_family;
1170 			uint8_t		*laddrp;
1171 
1172 			if (connp->conn_pkt_isv6) {
1173 				addr_family = AF_INET6;
1174 				laddrp =
1175 				    (uint8_t *)&connp->conn_bound_source_v6;
1176 			} else {
1177 				addr_family = AF_INET;
1178 				laddrp = (uint8_t *)&connp->conn_bound_source;
1179 			}
1180 			connp->conn_flags |= IPCL_CL_LISTENER;
1181 			(*cl_inet_listen)(IPPROTO_TCP, addr_family, laddrp,
1182 			    lport);
1183 		}
1184 		break;
1185 
1186 	case IPPROTO_SCTP:
1187 		ret = ipcl_sctp_hash_insert(connp, lport);
1188 		break;
1189 	}
1190 
1191 	return (ret);
1192 }
1193 
1194 /*
1195  * ipcl_conn_hash insertion routines.
1196  */
1197 int
1198 ipcl_conn_insert(conn_t *connp, uint8_t protocol, ipaddr_t src,
1199     ipaddr_t rem, uint32_t ports)
1200 {
1201 	connf_t		*connfp;
1202 	uint16_t	*up;
1203 	conn_t		*tconnp;
1204 #ifdef	IPCL_DEBUG
1205 	char	sbuf[INET_NTOA_BUFSIZE], rbuf[INET_NTOA_BUFSIZE];
1206 #endif
1207 	in_port_t	lport;
1208 	int		ret = 0;
1209 	ip_stack_t	*ipst = connp->conn_netstack->netstack_ip;
1210 
1211 	IPCL_DEBUG_LVL(256, ("ipcl_conn_insert: connp %p, src = %s, "
1212 	    "dst = %s, ports = %x, protocol = %x", (void *)connp,
1213 	    inet_ntoa_r(src, sbuf), inet_ntoa_r(rem, rbuf),
1214 	    ports, protocol));
1215 
1216 	switch (protocol) {
1217 	case IPPROTO_TCP:
1218 		if (!(connp->conn_flags & IPCL_EAGER)) {
1219 			/*
1220 			 * for a eager connection, i.e connections which
1221 			 * have just been created, the initialization is
1222 			 * already done in ip at conn_creation time, so
1223 			 * we can skip the checks here.
1224 			 */
1225 			IPCL_CONN_INIT(connp, protocol, src, rem, ports);
1226 		}
1227 		connfp = &ipst->ips_ipcl_conn_fanout[
1228 		    IPCL_CONN_HASH(connp->conn_rem,
1229 		    connp->conn_ports, ipst)];
1230 		mutex_enter(&connfp->connf_lock);
1231 		for (tconnp = connfp->connf_head; tconnp != NULL;
1232 		    tconnp = tconnp->conn_next) {
1233 			if (IPCL_CONN_MATCH(tconnp, connp->conn_ulp,
1234 			    connp->conn_rem, connp->conn_src,
1235 			    connp->conn_ports)) {
1236 
1237 				/* Already have a conn. bail out */
1238 				mutex_exit(&connfp->connf_lock);
1239 				return (EADDRINUSE);
1240 			}
1241 		}
1242 		if (connp->conn_fanout != NULL) {
1243 			/*
1244 			 * Probably a XTI/TLI application trying to do a
1245 			 * rebind. Let it happen.
1246 			 */
1247 			mutex_exit(&connfp->connf_lock);
1248 			IPCL_HASH_REMOVE(connp);
1249 			mutex_enter(&connfp->connf_lock);
1250 		}
1251 
1252 		ASSERT(connp->conn_recv != NULL);
1253 
1254 		IPCL_HASH_INSERT_CONNECTED_LOCKED(connfp, connp);
1255 		mutex_exit(&connfp->connf_lock);
1256 		break;
1257 
1258 	case IPPROTO_SCTP:
1259 		/*
1260 		 * The raw socket may have already been bound, remove it
1261 		 * from the hash first.
1262 		 */
1263 		IPCL_HASH_REMOVE(connp);
1264 		lport = htons((uint16_t)(ntohl(ports) & 0xFFFF));
1265 		ret = ipcl_sctp_hash_insert(connp, lport);
1266 		break;
1267 
1268 	default:
1269 		/*
1270 		 * Check for conflicts among MAC exempt bindings.  For
1271 		 * transports with port numbers, this is done by the upper
1272 		 * level per-transport binding logic.  For all others, it's
1273 		 * done here.
1274 		 */
1275 		if (is_system_labeled() &&
1276 		    check_exempt_conflict_v4(connp, ipst))
1277 			return (EADDRINUSE);
1278 		/* FALLTHROUGH */
1279 
1280 	case IPPROTO_UDP:
1281 		up = (uint16_t *)&ports;
1282 		IPCL_CONN_INIT(connp, protocol, src, rem, ports);
1283 		if (protocol == IPPROTO_UDP) {
1284 			connfp = &ipst->ips_ipcl_udp_fanout[
1285 			    IPCL_UDP_HASH(up[1], ipst)];
1286 		} else {
1287 			connfp = &ipst->ips_ipcl_proto_fanout[protocol];
1288 		}
1289 
1290 		if (connp->conn_rem != INADDR_ANY) {
1291 			IPCL_HASH_INSERT_CONNECTED(connfp, connp);
1292 		} else if (connp->conn_src != INADDR_ANY) {
1293 			IPCL_HASH_INSERT_BOUND(connfp, connp);
1294 		} else {
1295 			IPCL_HASH_INSERT_WILDCARD(connfp, connp);
1296 		}
1297 		break;
1298 	}
1299 
1300 	return (ret);
1301 }
1302 
1303 int
1304 ipcl_conn_insert_v6(conn_t *connp, uint8_t protocol, const in6_addr_t *src,
1305     const in6_addr_t *rem, uint32_t ports, uint_t ifindex)
1306 {
1307 	connf_t		*connfp;
1308 	uint16_t	*up;
1309 	conn_t		*tconnp;
1310 	in_port_t	lport;
1311 	int		ret = 0;
1312 	ip_stack_t	*ipst = connp->conn_netstack->netstack_ip;
1313 
1314 	switch (protocol) {
1315 	case IPPROTO_TCP:
1316 		/* Just need to insert a conn struct */
1317 		if (!(connp->conn_flags & IPCL_EAGER)) {
1318 			IPCL_CONN_INIT_V6(connp, protocol, *src, *rem, ports);
1319 		}
1320 		connfp = &ipst->ips_ipcl_conn_fanout[
1321 		    IPCL_CONN_HASH_V6(connp->conn_remv6, connp->conn_ports,
1322 		    ipst)];
1323 		mutex_enter(&connfp->connf_lock);
1324 		for (tconnp = connfp->connf_head; tconnp != NULL;
1325 		    tconnp = tconnp->conn_next) {
1326 			if (IPCL_CONN_MATCH_V6(tconnp, connp->conn_ulp,
1327 			    connp->conn_remv6, connp->conn_srcv6,
1328 			    connp->conn_ports) &&
1329 			    (tconnp->conn_tcp->tcp_bound_if == 0 ||
1330 			    tconnp->conn_tcp->tcp_bound_if == ifindex)) {
1331 				/* Already have a conn. bail out */
1332 				mutex_exit(&connfp->connf_lock);
1333 				return (EADDRINUSE);
1334 			}
1335 		}
1336 		if (connp->conn_fanout != NULL) {
1337 			/*
1338 			 * Probably a XTI/TLI application trying to do a
1339 			 * rebind. Let it happen.
1340 			 */
1341 			mutex_exit(&connfp->connf_lock);
1342 			IPCL_HASH_REMOVE(connp);
1343 			mutex_enter(&connfp->connf_lock);
1344 		}
1345 		IPCL_HASH_INSERT_CONNECTED_LOCKED(connfp, connp);
1346 		mutex_exit(&connfp->connf_lock);
1347 		break;
1348 
1349 	case IPPROTO_SCTP:
1350 		IPCL_HASH_REMOVE(connp);
1351 		lport = htons((uint16_t)(ntohl(ports) & 0xFFFF));
1352 		ret = ipcl_sctp_hash_insert(connp, lport);
1353 		break;
1354 
1355 	default:
1356 		if (is_system_labeled() &&
1357 		    check_exempt_conflict_v6(connp, ipst))
1358 			return (EADDRINUSE);
1359 		/* FALLTHROUGH */
1360 	case IPPROTO_UDP:
1361 		up = (uint16_t *)&ports;
1362 		IPCL_CONN_INIT_V6(connp, protocol, *src, *rem, ports);
1363 		if (protocol == IPPROTO_UDP) {
1364 			connfp = &ipst->ips_ipcl_udp_fanout[
1365 			    IPCL_UDP_HASH(up[1], ipst)];
1366 		} else {
1367 			connfp = &ipst->ips_ipcl_proto_fanout_v6[protocol];
1368 		}
1369 
1370 		if (!IN6_IS_ADDR_UNSPECIFIED(&connp->conn_remv6)) {
1371 			IPCL_HASH_INSERT_CONNECTED(connfp, connp);
1372 		} else if (!IN6_IS_ADDR_UNSPECIFIED(&connp->conn_srcv6)) {
1373 			IPCL_HASH_INSERT_BOUND(connfp, connp);
1374 		} else {
1375 			IPCL_HASH_INSERT_WILDCARD(connfp, connp);
1376 		}
1377 		break;
1378 	}
1379 
1380 	return (ret);
1381 }
1382 
1383 /*
1384  * v4 packet classifying function. looks up the fanout table to
1385  * find the conn, the packet belongs to. returns the conn with
1386  * the reference held, null otherwise.
1387  *
1388  * If zoneid is ALL_ZONES, then the search rules described in the "Connection
1389  * Lookup" comment block are applied.  Labels are also checked as described
1390  * above.  If the packet is from the inside (looped back), and is from the same
1391  * zone, then label checks are omitted.
1392  */
1393 conn_t *
1394 ipcl_classify_v4(mblk_t *mp, uint8_t protocol, uint_t hdr_len, zoneid_t zoneid,
1395     ip_stack_t *ipst)
1396 {
1397 	ipha_t	*ipha;
1398 	connf_t	*connfp, *bind_connfp;
1399 	uint16_t lport;
1400 	uint16_t fport;
1401 	uint32_t ports;
1402 	conn_t	*connp;
1403 	uint16_t  *up;
1404 	boolean_t shared_addr;
1405 	boolean_t unlabeled;
1406 
1407 	ipha = (ipha_t *)mp->b_rptr;
1408 	up = (uint16_t *)((uchar_t *)ipha + hdr_len + TCP_PORTS_OFFSET);
1409 
1410 	switch (protocol) {
1411 	case IPPROTO_TCP:
1412 		ports = *(uint32_t *)up;
1413 		connfp =
1414 		    &ipst->ips_ipcl_conn_fanout[IPCL_CONN_HASH(ipha->ipha_src,
1415 		    ports, ipst)];
1416 		mutex_enter(&connfp->connf_lock);
1417 		for (connp = connfp->connf_head; connp != NULL;
1418 		    connp = connp->conn_next) {
1419 			if (IPCL_CONN_MATCH(connp, protocol,
1420 			    ipha->ipha_src, ipha->ipha_dst, ports))
1421 				break;
1422 		}
1423 
1424 		if (connp != NULL) {
1425 			/*
1426 			 * We have a fully-bound TCP connection.
1427 			 *
1428 			 * For labeled systems, there's no need to check the
1429 			 * label here.  It's known to be good as we checked
1430 			 * before allowing the connection to become bound.
1431 			 */
1432 			CONN_INC_REF(connp);
1433 			mutex_exit(&connfp->connf_lock);
1434 			return (connp);
1435 		}
1436 
1437 		mutex_exit(&connfp->connf_lock);
1438 
1439 		lport = up[1];
1440 		unlabeled = B_FALSE;
1441 		/* Cred cannot be null on IPv4 */
1442 		if (is_system_labeled())
1443 			unlabeled = (crgetlabel(DB_CRED(mp))->tsl_flags &
1444 			    TSLF_UNLABELED) != 0;
1445 		shared_addr = (zoneid == ALL_ZONES);
1446 		if (shared_addr) {
1447 			/*
1448 			 * No need to handle exclusive-stack zones since
1449 			 * ALL_ZONES only applies to the shared stack.
1450 			 */
1451 			zoneid = tsol_mlp_findzone(protocol, lport);
1452 			/*
1453 			 * If no shared MLP is found, tsol_mlp_findzone returns
1454 			 * ALL_ZONES.  In that case, we assume it's SLP, and
1455 			 * search for the zone based on the packet label.
1456 			 *
1457 			 * If there is such a zone, we prefer to find a
1458 			 * connection in it.  Otherwise, we look for a
1459 			 * MAC-exempt connection in any zone whose label
1460 			 * dominates the default label on the packet.
1461 			 */
1462 			if (zoneid == ALL_ZONES)
1463 				zoneid = tsol_packet_to_zoneid(mp);
1464 			else
1465 				unlabeled = B_FALSE;
1466 		}
1467 
1468 		bind_connfp =
1469 		    &ipst->ips_ipcl_bind_fanout[IPCL_BIND_HASH(lport, ipst)];
1470 		mutex_enter(&bind_connfp->connf_lock);
1471 		for (connp = bind_connfp->connf_head; connp != NULL;
1472 		    connp = connp->conn_next) {
1473 			if (IPCL_BIND_MATCH(connp, protocol, ipha->ipha_dst,
1474 			    lport) && (IPCL_ZONE_MATCH(connp, zoneid) ||
1475 			    (unlabeled && connp->conn_mac_exempt)))
1476 				break;
1477 		}
1478 
1479 		/*
1480 		 * If the matching connection is SLP on a private address, then
1481 		 * the label on the packet must match the local zone's label.
1482 		 * Otherwise, it must be in the label range defined by tnrh.
1483 		 * This is ensured by tsol_receive_label.
1484 		 */
1485 		if (connp != NULL && is_system_labeled() &&
1486 		    !tsol_receive_local(mp, &ipha->ipha_dst, IPV4_VERSION,
1487 		    shared_addr, connp)) {
1488 				DTRACE_PROBE3(
1489 				    tx__ip__log__info__classify__tcp,
1490 				    char *,
1491 				    "connp(1) could not receive mp(2)",
1492 				    conn_t *, connp, mblk_t *, mp);
1493 			connp = NULL;
1494 		}
1495 
1496 		if (connp != NULL) {
1497 			/* Have a listener at least */
1498 			CONN_INC_REF(connp);
1499 			mutex_exit(&bind_connfp->connf_lock);
1500 			return (connp);
1501 		}
1502 
1503 		mutex_exit(&bind_connfp->connf_lock);
1504 
1505 		IPCL_DEBUG_LVL(512,
1506 		    ("ipcl_classify: couldn't classify mp = %p\n",
1507 		    (void *)mp));
1508 		break;
1509 
1510 	case IPPROTO_UDP:
1511 		lport = up[1];
1512 		unlabeled = B_FALSE;
1513 		/* Cred cannot be null on IPv4 */
1514 		if (is_system_labeled())
1515 			unlabeled = (crgetlabel(DB_CRED(mp))->tsl_flags &
1516 			    TSLF_UNLABELED) != 0;
1517 		shared_addr = (zoneid == ALL_ZONES);
1518 		if (shared_addr) {
1519 			/*
1520 			 * No need to handle exclusive-stack zones since
1521 			 * ALL_ZONES only applies to the shared stack.
1522 			 */
1523 			zoneid = tsol_mlp_findzone(protocol, lport);
1524 			/*
1525 			 * If no shared MLP is found, tsol_mlp_findzone returns
1526 			 * ALL_ZONES.  In that case, we assume it's SLP, and
1527 			 * search for the zone based on the packet label.
1528 			 *
1529 			 * If there is such a zone, we prefer to find a
1530 			 * connection in it.  Otherwise, we look for a
1531 			 * MAC-exempt connection in any zone whose label
1532 			 * dominates the default label on the packet.
1533 			 */
1534 			if (zoneid == ALL_ZONES)
1535 				zoneid = tsol_packet_to_zoneid(mp);
1536 			else
1537 				unlabeled = B_FALSE;
1538 		}
1539 		fport = up[0];
1540 		IPCL_DEBUG_LVL(512, ("ipcl_udp_classify %x %x", lport, fport));
1541 		connfp = &ipst->ips_ipcl_udp_fanout[IPCL_UDP_HASH(lport, ipst)];
1542 		mutex_enter(&connfp->connf_lock);
1543 		for (connp = connfp->connf_head; connp != NULL;
1544 		    connp = connp->conn_next) {
1545 			if (IPCL_UDP_MATCH(connp, lport, ipha->ipha_dst,
1546 			    fport, ipha->ipha_src) &&
1547 			    (IPCL_ZONE_MATCH(connp, zoneid) ||
1548 			    (unlabeled && connp->conn_mac_exempt)))
1549 				break;
1550 		}
1551 
1552 		if (connp != NULL && is_system_labeled() &&
1553 		    !tsol_receive_local(mp, &ipha->ipha_dst, IPV4_VERSION,
1554 		    shared_addr, connp)) {
1555 			DTRACE_PROBE3(tx__ip__log__info__classify__udp,
1556 			    char *, "connp(1) could not receive mp(2)",
1557 			    conn_t *, connp, mblk_t *, mp);
1558 			connp = NULL;
1559 		}
1560 
1561 		if (connp != NULL) {
1562 			CONN_INC_REF(connp);
1563 			mutex_exit(&connfp->connf_lock);
1564 			return (connp);
1565 		}
1566 
1567 		/*
1568 		 * We shouldn't come here for multicast/broadcast packets
1569 		 */
1570 		mutex_exit(&connfp->connf_lock);
1571 		IPCL_DEBUG_LVL(512,
1572 		    ("ipcl_classify: cant find udp conn_t for ports : %x %x",
1573 		    lport, fport));
1574 		break;
1575 	}
1576 
1577 	return (NULL);
1578 }
1579 
1580 conn_t *
1581 ipcl_classify_v6(mblk_t *mp, uint8_t protocol, uint_t hdr_len, zoneid_t zoneid,
1582     ip_stack_t *ipst)
1583 {
1584 	ip6_t		*ip6h;
1585 	connf_t		*connfp, *bind_connfp;
1586 	uint16_t	lport;
1587 	uint16_t	fport;
1588 	tcph_t		*tcph;
1589 	uint32_t	ports;
1590 	conn_t		*connp;
1591 	uint16_t	*up;
1592 	boolean_t	shared_addr;
1593 	boolean_t	unlabeled;
1594 
1595 	ip6h = (ip6_t *)mp->b_rptr;
1596 
1597 	switch (protocol) {
1598 	case IPPROTO_TCP:
1599 		tcph = (tcph_t *)&mp->b_rptr[hdr_len];
1600 		up = (uint16_t *)tcph->th_lport;
1601 		ports = *(uint32_t *)up;
1602 
1603 		connfp =
1604 		    &ipst->ips_ipcl_conn_fanout[IPCL_CONN_HASH_V6(ip6h->ip6_src,
1605 		    ports, ipst)];
1606 		mutex_enter(&connfp->connf_lock);
1607 		for (connp = connfp->connf_head; connp != NULL;
1608 		    connp = connp->conn_next) {
1609 			if (IPCL_CONN_MATCH_V6(connp, protocol,
1610 			    ip6h->ip6_src, ip6h->ip6_dst, ports))
1611 				break;
1612 		}
1613 
1614 		if (connp != NULL) {
1615 			/*
1616 			 * We have a fully-bound TCP connection.
1617 			 *
1618 			 * For labeled systems, there's no need to check the
1619 			 * label here.  It's known to be good as we checked
1620 			 * before allowing the connection to become bound.
1621 			 */
1622 			CONN_INC_REF(connp);
1623 			mutex_exit(&connfp->connf_lock);
1624 			return (connp);
1625 		}
1626 
1627 		mutex_exit(&connfp->connf_lock);
1628 
1629 		lport = up[1];
1630 		unlabeled = B_FALSE;
1631 		/* Cred can be null on IPv6 */
1632 		if (is_system_labeled()) {
1633 			cred_t *cr = DB_CRED(mp);
1634 
1635 			unlabeled = (cr != NULL &&
1636 			    crgetlabel(cr)->tsl_flags & TSLF_UNLABELED) != 0;
1637 		}
1638 		shared_addr = (zoneid == ALL_ZONES);
1639 		if (shared_addr) {
1640 			/*
1641 			 * No need to handle exclusive-stack zones since
1642 			 * ALL_ZONES only applies to the shared stack.
1643 			 */
1644 			zoneid = tsol_mlp_findzone(protocol, lport);
1645 			/*
1646 			 * If no shared MLP is found, tsol_mlp_findzone returns
1647 			 * ALL_ZONES.  In that case, we assume it's SLP, and
1648 			 * search for the zone based on the packet label.
1649 			 *
1650 			 * If there is such a zone, we prefer to find a
1651 			 * connection in it.  Otherwise, we look for a
1652 			 * MAC-exempt connection in any zone whose label
1653 			 * dominates the default label on the packet.
1654 			 */
1655 			if (zoneid == ALL_ZONES)
1656 				zoneid = tsol_packet_to_zoneid(mp);
1657 			else
1658 				unlabeled = B_FALSE;
1659 		}
1660 
1661 		bind_connfp =
1662 		    &ipst->ips_ipcl_bind_fanout[IPCL_BIND_HASH(lport, ipst)];
1663 		mutex_enter(&bind_connfp->connf_lock);
1664 		for (connp = bind_connfp->connf_head; connp != NULL;
1665 		    connp = connp->conn_next) {
1666 			if (IPCL_BIND_MATCH_V6(connp, protocol,
1667 			    ip6h->ip6_dst, lport) &&
1668 			    (IPCL_ZONE_MATCH(connp, zoneid) ||
1669 			    (unlabeled && connp->conn_mac_exempt)))
1670 				break;
1671 		}
1672 
1673 		if (connp != NULL && is_system_labeled() &&
1674 		    !tsol_receive_local(mp, &ip6h->ip6_dst, IPV6_VERSION,
1675 		    shared_addr, connp)) {
1676 			DTRACE_PROBE3(tx__ip__log__info__classify__tcp6,
1677 			    char *, "connp(1) could not receive mp(2)",
1678 			    conn_t *, connp, mblk_t *, mp);
1679 			connp = NULL;
1680 		}
1681 
1682 		if (connp != NULL) {
1683 			/* Have a listner at least */
1684 			CONN_INC_REF(connp);
1685 			mutex_exit(&bind_connfp->connf_lock);
1686 			IPCL_DEBUG_LVL(512,
1687 			    ("ipcl_classify_v6: found listner "
1688 			    "connp = %p\n", (void *)connp));
1689 
1690 			return (connp);
1691 		}
1692 
1693 		mutex_exit(&bind_connfp->connf_lock);
1694 
1695 		IPCL_DEBUG_LVL(512,
1696 		    ("ipcl_classify_v6: couldn't classify mp = %p\n",
1697 		    (void *)mp));
1698 		break;
1699 
1700 	case IPPROTO_UDP:
1701 		up = (uint16_t *)&mp->b_rptr[hdr_len];
1702 		lport = up[1];
1703 		unlabeled = B_FALSE;
1704 		/* Cred can be null on IPv6 */
1705 		if (is_system_labeled()) {
1706 			cred_t *cr = DB_CRED(mp);
1707 
1708 			unlabeled = (cr != NULL &&
1709 			    crgetlabel(cr)->tsl_flags & TSLF_UNLABELED) != 0;
1710 		}
1711 		shared_addr = (zoneid == ALL_ZONES);
1712 		if (shared_addr) {
1713 			/*
1714 			 * No need to handle exclusive-stack zones since
1715 			 * ALL_ZONES only applies to the shared stack.
1716 			 */
1717 			zoneid = tsol_mlp_findzone(protocol, lport);
1718 			/*
1719 			 * If no shared MLP is found, tsol_mlp_findzone returns
1720 			 * ALL_ZONES.  In that case, we assume it's SLP, and
1721 			 * search for the zone based on the packet label.
1722 			 *
1723 			 * If there is such a zone, we prefer to find a
1724 			 * connection in it.  Otherwise, we look for a
1725 			 * MAC-exempt connection in any zone whose label
1726 			 * dominates the default label on the packet.
1727 			 */
1728 			if (zoneid == ALL_ZONES)
1729 				zoneid = tsol_packet_to_zoneid(mp);
1730 			else
1731 				unlabeled = B_FALSE;
1732 		}
1733 
1734 		fport = up[0];
1735 		IPCL_DEBUG_LVL(512, ("ipcl_udp_classify_v6 %x %x", lport,
1736 		    fport));
1737 		connfp = &ipst->ips_ipcl_udp_fanout[IPCL_UDP_HASH(lport, ipst)];
1738 		mutex_enter(&connfp->connf_lock);
1739 		for (connp = connfp->connf_head; connp != NULL;
1740 		    connp = connp->conn_next) {
1741 			if (IPCL_UDP_MATCH_V6(connp, lport, ip6h->ip6_dst,
1742 			    fport, ip6h->ip6_src) &&
1743 			    (IPCL_ZONE_MATCH(connp, zoneid) ||
1744 			    (unlabeled && connp->conn_mac_exempt)))
1745 				break;
1746 		}
1747 
1748 		if (connp != NULL && is_system_labeled() &&
1749 		    !tsol_receive_local(mp, &ip6h->ip6_dst, IPV6_VERSION,
1750 		    shared_addr, connp)) {
1751 			DTRACE_PROBE3(tx__ip__log__info__classify__udp6,
1752 			    char *, "connp(1) could not receive mp(2)",
1753 			    conn_t *, connp, mblk_t *, mp);
1754 			connp = NULL;
1755 		}
1756 
1757 		if (connp != NULL) {
1758 			CONN_INC_REF(connp);
1759 			mutex_exit(&connfp->connf_lock);
1760 			return (connp);
1761 		}
1762 
1763 		/*
1764 		 * We shouldn't come here for multicast/broadcast packets
1765 		 */
1766 		mutex_exit(&connfp->connf_lock);
1767 		IPCL_DEBUG_LVL(512,
1768 		    ("ipcl_classify_v6: cant find udp conn_t for ports : %x %x",
1769 		    lport, fport));
1770 		break;
1771 	}
1772 
1773 	return (NULL);
1774 }
1775 
1776 /*
1777  * wrapper around ipcl_classify_(v4,v6) routines.
1778  */
1779 conn_t *
1780 ipcl_classify(mblk_t *mp, zoneid_t zoneid, ip_stack_t *ipst)
1781 {
1782 	uint16_t	hdr_len;
1783 	ipha_t		*ipha;
1784 	uint8_t		*nexthdrp;
1785 
1786 	if (MBLKL(mp) < sizeof (ipha_t))
1787 		return (NULL);
1788 
1789 	switch (IPH_HDR_VERSION(mp->b_rptr)) {
1790 	case IPV4_VERSION:
1791 		ipha = (ipha_t *)mp->b_rptr;
1792 		hdr_len = IPH_HDR_LENGTH(ipha);
1793 		return (ipcl_classify_v4(mp, ipha->ipha_protocol, hdr_len,
1794 		    zoneid, ipst));
1795 	case IPV6_VERSION:
1796 		if (!ip_hdr_length_nexthdr_v6(mp, (ip6_t *)mp->b_rptr,
1797 		    &hdr_len, &nexthdrp))
1798 			return (NULL);
1799 
1800 		return (ipcl_classify_v6(mp, *nexthdrp, hdr_len, zoneid, ipst));
1801 	}
1802 
1803 	return (NULL);
1804 }
1805 
1806 conn_t *
1807 ipcl_classify_raw(mblk_t *mp, uint8_t protocol, zoneid_t zoneid,
1808     uint32_t ports, ipha_t *hdr, ip_stack_t *ipst)
1809 {
1810 	connf_t		*connfp;
1811 	conn_t		*connp;
1812 	in_port_t	lport;
1813 	int		af;
1814 	boolean_t	shared_addr;
1815 	boolean_t	unlabeled;
1816 	const void	*dst;
1817 
1818 	lport = ((uint16_t *)&ports)[1];
1819 
1820 	unlabeled = B_FALSE;
1821 	/* Cred can be null on IPv6 */
1822 	if (is_system_labeled()) {
1823 		cred_t *cr = DB_CRED(mp);
1824 
1825 		unlabeled = (cr != NULL &&
1826 		    crgetlabel(cr)->tsl_flags & TSLF_UNLABELED) != 0;
1827 	}
1828 	shared_addr = (zoneid == ALL_ZONES);
1829 	if (shared_addr) {
1830 		/*
1831 		 * No need to handle exclusive-stack zones since ALL_ZONES
1832 		 * only applies to the shared stack.
1833 		 */
1834 		zoneid = tsol_mlp_findzone(protocol, lport);
1835 		/*
1836 		 * If no shared MLP is found, tsol_mlp_findzone returns
1837 		 * ALL_ZONES.  In that case, we assume it's SLP, and search for
1838 		 * the zone based on the packet label.
1839 		 *
1840 		 * If there is such a zone, we prefer to find a connection in
1841 		 * it.  Otherwise, we look for a MAC-exempt connection in any
1842 		 * zone whose label dominates the default label on the packet.
1843 		 */
1844 		if (zoneid == ALL_ZONES)
1845 			zoneid = tsol_packet_to_zoneid(mp);
1846 		else
1847 			unlabeled = B_FALSE;
1848 	}
1849 
1850 	af = IPH_HDR_VERSION(hdr);
1851 	dst = af == IPV4_VERSION ? (const void *)&hdr->ipha_dst :
1852 	    (const void *)&((ip6_t *)hdr)->ip6_dst;
1853 	connfp = &ipst->ips_ipcl_raw_fanout[IPCL_RAW_HASH(ntohs(lport), ipst)];
1854 
1855 	mutex_enter(&connfp->connf_lock);
1856 	for (connp = connfp->connf_head; connp != NULL;
1857 	    connp = connp->conn_next) {
1858 		/* We don't allow v4 fallback for v6 raw socket. */
1859 		if (af == (connp->conn_af_isv6 ? IPV4_VERSION :
1860 		    IPV6_VERSION))
1861 			continue;
1862 		if (connp->conn_fully_bound) {
1863 			if (af == IPV4_VERSION) {
1864 				if (!IPCL_CONN_MATCH(connp, protocol,
1865 				    hdr->ipha_src, hdr->ipha_dst, ports))
1866 					continue;
1867 			} else {
1868 				if (!IPCL_CONN_MATCH_V6(connp, protocol,
1869 				    ((ip6_t *)hdr)->ip6_src,
1870 				    ((ip6_t *)hdr)->ip6_dst, ports))
1871 					continue;
1872 			}
1873 		} else {
1874 			if (af == IPV4_VERSION) {
1875 				if (!IPCL_BIND_MATCH(connp, protocol,
1876 				    hdr->ipha_dst, lport))
1877 					continue;
1878 			} else {
1879 				if (!IPCL_BIND_MATCH_V6(connp, protocol,
1880 				    ((ip6_t *)hdr)->ip6_dst, lport))
1881 					continue;
1882 			}
1883 		}
1884 
1885 		if (IPCL_ZONE_MATCH(connp, zoneid) ||
1886 		    (unlabeled && connp->conn_mac_exempt))
1887 			break;
1888 	}
1889 	/*
1890 	 * If the connection is fully-bound and connection-oriented (TCP or
1891 	 * SCTP), then we've already validated the remote system's label.
1892 	 * There's no need to do it again for every packet.
1893 	 */
1894 	if (connp != NULL && is_system_labeled() && (!connp->conn_fully_bound ||
1895 	    !(connp->conn_flags & (IPCL_TCP|IPCL_SCTPCONN))) &&
1896 	    !tsol_receive_local(mp, dst, af, shared_addr, connp)) {
1897 		DTRACE_PROBE3(tx__ip__log__info__classify__rawip,
1898 		    char *, "connp(1) could not receive mp(2)",
1899 		    conn_t *, connp, mblk_t *, mp);
1900 		connp = NULL;
1901 	}
1902 
1903 	if (connp != NULL)
1904 		goto found;
1905 	mutex_exit(&connfp->connf_lock);
1906 
1907 	/* Try to look for a wildcard match. */
1908 	connfp = &ipst->ips_ipcl_raw_fanout[IPCL_RAW_HASH(0, ipst)];
1909 	mutex_enter(&connfp->connf_lock);
1910 	for (connp = connfp->connf_head; connp != NULL;
1911 	    connp = connp->conn_next) {
1912 		/* We don't allow v4 fallback for v6 raw socket. */
1913 		if ((af == (connp->conn_af_isv6 ? IPV4_VERSION :
1914 		    IPV6_VERSION)) || !IPCL_ZONE_MATCH(connp, zoneid)) {
1915 			continue;
1916 		}
1917 		if (af == IPV4_VERSION) {
1918 			if (IPCL_RAW_MATCH(connp, protocol, hdr->ipha_dst))
1919 				break;
1920 		} else {
1921 			if (IPCL_RAW_MATCH_V6(connp, protocol,
1922 			    ((ip6_t *)hdr)->ip6_dst)) {
1923 				break;
1924 			}
1925 		}
1926 	}
1927 
1928 	if (connp != NULL)
1929 		goto found;
1930 
1931 	mutex_exit(&connfp->connf_lock);
1932 	return (NULL);
1933 
1934 found:
1935 	ASSERT(connp != NULL);
1936 	CONN_INC_REF(connp);
1937 	mutex_exit(&connfp->connf_lock);
1938 	return (connp);
1939 }
1940 
1941 /* ARGSUSED */
1942 static int
1943 ipcl_tcpconn_constructor(void *buf, void *cdrarg, int kmflags)
1944 {
1945 	itc_t	*itc = (itc_t *)buf;
1946 	conn_t 	*connp = &itc->itc_conn;
1947 	tcp_t	*tcp = &itc->itc_tcp;
1948 	bzero(itc, sizeof (itc_t));
1949 	tcp->tcp_timercache = tcp_timermp_alloc(KM_NOSLEEP);
1950 	connp->conn_tcp = tcp;
1951 	connp->conn_flags = IPCL_TCPCONN;
1952 	connp->conn_ulp = IPPROTO_TCP;
1953 	tcp->tcp_connp = connp;
1954 	return (0);
1955 }
1956 
1957 /* ARGSUSED */
1958 static void
1959 ipcl_tcpconn_destructor(void *buf, void *cdrarg)
1960 {
1961 	tcp_timermp_free(((conn_t *)buf)->conn_tcp);
1962 }
1963 
1964 /*
1965  * All conns are inserted in a global multi-list for the benefit of
1966  * walkers. The walk is guaranteed to walk all open conns at the time
1967  * of the start of the walk exactly once. This property is needed to
1968  * achieve some cleanups during unplumb of interfaces. This is achieved
1969  * as follows.
1970  *
1971  * ipcl_conn_create and ipcl_conn_destroy are the only functions that
1972  * call the insert and delete functions below at creation and deletion
1973  * time respectively. The conn never moves or changes its position in this
1974  * multi-list during its lifetime. CONN_CONDEMNED ensures that the refcnt
1975  * won't increase due to walkers, once the conn deletion has started. Note
1976  * that we can't remove the conn from the global list and then wait for
1977  * the refcnt to drop to zero, since walkers would then see a truncated
1978  * list. CONN_INCIPIENT ensures that walkers don't start looking at
1979  * conns until ip_open is ready to make them globally visible.
1980  * The global round robin multi-list locks are held only to get the
1981  * next member/insertion/deletion and contention should be negligible
1982  * if the multi-list is much greater than the number of cpus.
1983  */
1984 void
1985 ipcl_globalhash_insert(conn_t *connp)
1986 {
1987 	int	index;
1988 	struct connf_s	*connfp;
1989 	ip_stack_t	*ipst = connp->conn_netstack->netstack_ip;
1990 
1991 	/*
1992 	 * No need for atomic here. Approximate even distribution
1993 	 * in the global lists is sufficient.
1994 	 */
1995 	ipst->ips_conn_g_index++;
1996 	index = ipst->ips_conn_g_index & (CONN_G_HASH_SIZE - 1);
1997 
1998 	connp->conn_g_prev = NULL;
1999 	/*
2000 	 * Mark as INCIPIENT, so that walkers will ignore this
2001 	 * for now, till ip_open is ready to make it visible globally.
2002 	 */
2003 	connp->conn_state_flags |= CONN_INCIPIENT;
2004 
2005 	connfp = &ipst->ips_ipcl_globalhash_fanout[index];
2006 	/* Insert at the head of the list */
2007 	mutex_enter(&connfp->connf_lock);
2008 	connp->conn_g_next = connfp->connf_head;
2009 	if (connp->conn_g_next != NULL)
2010 		connp->conn_g_next->conn_g_prev = connp;
2011 	connfp->connf_head = connp;
2012 
2013 	/* The fanout bucket this conn points to */
2014 	connp->conn_g_fanout = connfp;
2015 
2016 	mutex_exit(&connfp->connf_lock);
2017 }
2018 
2019 void
2020 ipcl_globalhash_remove(conn_t *connp)
2021 {
2022 	struct connf_s	*connfp;
2023 
2024 	/*
2025 	 * We were never inserted in the global multi list.
2026 	 * IPCL_NONE variety is never inserted in the global multilist
2027 	 * since it is presumed to not need any cleanup and is transient.
2028 	 */
2029 	if (connp->conn_g_fanout == NULL)
2030 		return;
2031 
2032 	connfp = connp->conn_g_fanout;
2033 	mutex_enter(&connfp->connf_lock);
2034 	if (connp->conn_g_prev != NULL)
2035 		connp->conn_g_prev->conn_g_next = connp->conn_g_next;
2036 	else
2037 		connfp->connf_head = connp->conn_g_next;
2038 	if (connp->conn_g_next != NULL)
2039 		connp->conn_g_next->conn_g_prev = connp->conn_g_prev;
2040 	mutex_exit(&connfp->connf_lock);
2041 
2042 	/* Better to stumble on a null pointer than to corrupt memory */
2043 	connp->conn_g_next = NULL;
2044 	connp->conn_g_prev = NULL;
2045 }
2046 
2047 /*
2048  * Walk the list of all conn_t's in the system, calling the function provided
2049  * with the specified argument for each.
2050  * Applies to both IPv4 and IPv6.
2051  *
2052  * IPCs may hold pointers to ipif/ill. To guard against stale pointers
2053  * ipcl_walk() is called to cleanup the conn_t's, typically when an interface is
2054  * unplumbed or removed. New conn_t's that are created while we are walking
2055  * may be missed by this walk, because they are not necessarily inserted
2056  * at the tail of the list. They are new conn_t's and thus don't have any
2057  * stale pointers. The CONN_CLOSING flag ensures that no new reference
2058  * is created to the struct that is going away.
2059  */
2060 void
2061 ipcl_walk(pfv_t func, void *arg, ip_stack_t *ipst)
2062 {
2063 	int	i;
2064 	conn_t	*connp;
2065 	conn_t	*prev_connp;
2066 
2067 	for (i = 0; i < CONN_G_HASH_SIZE; i++) {
2068 		mutex_enter(&ipst->ips_ipcl_globalhash_fanout[i].connf_lock);
2069 		prev_connp = NULL;
2070 		connp = ipst->ips_ipcl_globalhash_fanout[i].connf_head;
2071 		while (connp != NULL) {
2072 			mutex_enter(&connp->conn_lock);
2073 			if (connp->conn_state_flags &
2074 			    (CONN_CONDEMNED | CONN_INCIPIENT)) {
2075 				mutex_exit(&connp->conn_lock);
2076 				connp = connp->conn_g_next;
2077 				continue;
2078 			}
2079 			CONN_INC_REF_LOCKED(connp);
2080 			mutex_exit(&connp->conn_lock);
2081 			mutex_exit(
2082 			    &ipst->ips_ipcl_globalhash_fanout[i].connf_lock);
2083 			(*func)(connp, arg);
2084 			if (prev_connp != NULL)
2085 				CONN_DEC_REF(prev_connp);
2086 			mutex_enter(
2087 			    &ipst->ips_ipcl_globalhash_fanout[i].connf_lock);
2088 			prev_connp = connp;
2089 			connp = connp->conn_g_next;
2090 		}
2091 		mutex_exit(&ipst->ips_ipcl_globalhash_fanout[i].connf_lock);
2092 		if (prev_connp != NULL)
2093 			CONN_DEC_REF(prev_connp);
2094 	}
2095 }
2096 
2097 /*
2098  * Search for a peer TCP/IPv4 loopback conn by doing a reverse lookup on
2099  * the {src, dst, lport, fport} quadruplet.  Returns with conn reference
2100  * held; caller must call CONN_DEC_REF.  Only checks for connected entries
2101  * (peer tcp in ESTABLISHED state).
2102  */
2103 conn_t *
2104 ipcl_conn_tcp_lookup_reversed_ipv4(conn_t *connp, ipha_t *ipha, tcph_t *tcph,
2105     ip_stack_t *ipst)
2106 {
2107 	uint32_t ports;
2108 	uint16_t *pports = (uint16_t *)&ports;
2109 	connf_t	*connfp;
2110 	conn_t	*tconnp;
2111 	boolean_t zone_chk;
2112 
2113 	/*
2114 	 * If either the source of destination address is loopback, then
2115 	 * both endpoints must be in the same Zone.  Otherwise, both of
2116 	 * the addresses are system-wide unique (tcp is in ESTABLISHED
2117 	 * state) and the endpoints may reside in different Zones.
2118 	 */
2119 	zone_chk = (ipha->ipha_src == htonl(INADDR_LOOPBACK) ||
2120 	    ipha->ipha_dst == htonl(INADDR_LOOPBACK));
2121 
2122 	bcopy(tcph->th_fport, &pports[0], sizeof (uint16_t));
2123 	bcopy(tcph->th_lport, &pports[1], sizeof (uint16_t));
2124 
2125 	connfp = &ipst->ips_ipcl_conn_fanout[IPCL_CONN_HASH(ipha->ipha_dst,
2126 	    ports, ipst)];
2127 
2128 	mutex_enter(&connfp->connf_lock);
2129 	for (tconnp = connfp->connf_head; tconnp != NULL;
2130 	    tconnp = tconnp->conn_next) {
2131 
2132 		if (IPCL_CONN_MATCH(tconnp, IPPROTO_TCP,
2133 		    ipha->ipha_dst, ipha->ipha_src, ports) &&
2134 		    tconnp->conn_tcp->tcp_state == TCPS_ESTABLISHED &&
2135 		    (!zone_chk || tconnp->conn_zoneid == connp->conn_zoneid)) {
2136 
2137 			ASSERT(tconnp != connp);
2138 			CONN_INC_REF(tconnp);
2139 			mutex_exit(&connfp->connf_lock);
2140 			return (tconnp);
2141 		}
2142 	}
2143 	mutex_exit(&connfp->connf_lock);
2144 	return (NULL);
2145 }
2146 
2147 /*
2148  * Search for a peer TCP/IPv6 loopback conn by doing a reverse lookup on
2149  * the {src, dst, lport, fport} quadruplet.  Returns with conn reference
2150  * held; caller must call CONN_DEC_REF.  Only checks for connected entries
2151  * (peer tcp in ESTABLISHED state).
2152  */
2153 conn_t *
2154 ipcl_conn_tcp_lookup_reversed_ipv6(conn_t *connp, ip6_t *ip6h, tcph_t *tcph,
2155     ip_stack_t *ipst)
2156 {
2157 	uint32_t ports;
2158 	uint16_t *pports = (uint16_t *)&ports;
2159 	connf_t	*connfp;
2160 	conn_t	*tconnp;
2161 	boolean_t zone_chk;
2162 
2163 	/*
2164 	 * If either the source of destination address is loopback, then
2165 	 * both endpoints must be in the same Zone.  Otherwise, both of
2166 	 * the addresses are system-wide unique (tcp is in ESTABLISHED
2167 	 * state) and the endpoints may reside in different Zones.  We
2168 	 * don't do Zone check for link local address(es) because the
2169 	 * current Zone implementation treats each link local address as
2170 	 * being unique per system node, i.e. they belong to global Zone.
2171 	 */
2172 	zone_chk = (IN6_IS_ADDR_LOOPBACK(&ip6h->ip6_src) ||
2173 	    IN6_IS_ADDR_LOOPBACK(&ip6h->ip6_dst));
2174 
2175 	bcopy(tcph->th_fport, &pports[0], sizeof (uint16_t));
2176 	bcopy(tcph->th_lport, &pports[1], sizeof (uint16_t));
2177 
2178 	connfp = &ipst->ips_ipcl_conn_fanout[IPCL_CONN_HASH_V6(ip6h->ip6_dst,
2179 	    ports, ipst)];
2180 
2181 	mutex_enter(&connfp->connf_lock);
2182 	for (tconnp = connfp->connf_head; tconnp != NULL;
2183 	    tconnp = tconnp->conn_next) {
2184 
2185 		/* We skip tcp_bound_if check here as this is loopback tcp */
2186 		if (IPCL_CONN_MATCH_V6(tconnp, IPPROTO_TCP,
2187 		    ip6h->ip6_dst, ip6h->ip6_src, ports) &&
2188 		    tconnp->conn_tcp->tcp_state == TCPS_ESTABLISHED &&
2189 		    (!zone_chk || tconnp->conn_zoneid == connp->conn_zoneid)) {
2190 
2191 			ASSERT(tconnp != connp);
2192 			CONN_INC_REF(tconnp);
2193 			mutex_exit(&connfp->connf_lock);
2194 			return (tconnp);
2195 		}
2196 	}
2197 	mutex_exit(&connfp->connf_lock);
2198 	return (NULL);
2199 }
2200 
2201 /*
2202  * Find an exact {src, dst, lport, fport} match for a bounced datagram.
2203  * Returns with conn reference held. Caller must call CONN_DEC_REF.
2204  * Only checks for connected entries i.e. no INADDR_ANY checks.
2205  */
2206 conn_t *
2207 ipcl_tcp_lookup_reversed_ipv4(ipha_t *ipha, tcph_t *tcph, int min_state,
2208     ip_stack_t *ipst)
2209 {
2210 	uint32_t ports;
2211 	uint16_t *pports;
2212 	connf_t	*connfp;
2213 	conn_t	*tconnp;
2214 
2215 	pports = (uint16_t *)&ports;
2216 	bcopy(tcph->th_fport, &pports[0], sizeof (uint16_t));
2217 	bcopy(tcph->th_lport, &pports[1], sizeof (uint16_t));
2218 
2219 	connfp = &ipst->ips_ipcl_conn_fanout[IPCL_CONN_HASH(ipha->ipha_dst,
2220 	    ports, ipst)];
2221 
2222 	mutex_enter(&connfp->connf_lock);
2223 	for (tconnp = connfp->connf_head; tconnp != NULL;
2224 	    tconnp = tconnp->conn_next) {
2225 
2226 		if (IPCL_CONN_MATCH(tconnp, IPPROTO_TCP,
2227 		    ipha->ipha_dst, ipha->ipha_src, ports) &&
2228 		    tconnp->conn_tcp->tcp_state >= min_state) {
2229 
2230 			CONN_INC_REF(tconnp);
2231 			mutex_exit(&connfp->connf_lock);
2232 			return (tconnp);
2233 		}
2234 	}
2235 	mutex_exit(&connfp->connf_lock);
2236 	return (NULL);
2237 }
2238 
2239 /*
2240  * Find an exact {src, dst, lport, fport} match for a bounced datagram.
2241  * Returns with conn reference held. Caller must call CONN_DEC_REF.
2242  * Only checks for connected entries i.e. no INADDR_ANY checks.
2243  * Match on ifindex in addition to addresses.
2244  */
2245 conn_t *
2246 ipcl_tcp_lookup_reversed_ipv6(ip6_t *ip6h, tcpha_t *tcpha, int min_state,
2247     uint_t ifindex, ip_stack_t *ipst)
2248 {
2249 	tcp_t	*tcp;
2250 	uint32_t ports;
2251 	uint16_t *pports;
2252 	connf_t	*connfp;
2253 	conn_t	*tconnp;
2254 
2255 	pports = (uint16_t *)&ports;
2256 	pports[0] = tcpha->tha_fport;
2257 	pports[1] = tcpha->tha_lport;
2258 
2259 	connfp = &ipst->ips_ipcl_conn_fanout[IPCL_CONN_HASH_V6(ip6h->ip6_dst,
2260 	    ports, ipst)];
2261 
2262 	mutex_enter(&connfp->connf_lock);
2263 	for (tconnp = connfp->connf_head; tconnp != NULL;
2264 	    tconnp = tconnp->conn_next) {
2265 
2266 		tcp = tconnp->conn_tcp;
2267 		if (IPCL_CONN_MATCH_V6(tconnp, IPPROTO_TCP,
2268 		    ip6h->ip6_dst, ip6h->ip6_src, ports) &&
2269 		    tcp->tcp_state >= min_state &&
2270 		    (tcp->tcp_bound_if == 0 ||
2271 		    tcp->tcp_bound_if == ifindex)) {
2272 
2273 			CONN_INC_REF(tconnp);
2274 			mutex_exit(&connfp->connf_lock);
2275 			return (tconnp);
2276 		}
2277 	}
2278 	mutex_exit(&connfp->connf_lock);
2279 	return (NULL);
2280 }
2281 
2282 /*
2283  * Finds a TCP/IPv4 listening connection; called by tcp_disconnect to locate
2284  * a listener when changing state.
2285  */
2286 conn_t *
2287 ipcl_lookup_listener_v4(uint16_t lport, ipaddr_t laddr, zoneid_t zoneid,
2288     ip_stack_t *ipst)
2289 {
2290 	connf_t		*bind_connfp;
2291 	conn_t		*connp;
2292 	tcp_t		*tcp;
2293 
2294 	/*
2295 	 * Avoid false matches for packets sent to an IP destination of
2296 	 * all zeros.
2297 	 */
2298 	if (laddr == 0)
2299 		return (NULL);
2300 
2301 	ASSERT(zoneid != ALL_ZONES);
2302 
2303 	bind_connfp = &ipst->ips_ipcl_bind_fanout[IPCL_BIND_HASH(lport, ipst)];
2304 	mutex_enter(&bind_connfp->connf_lock);
2305 	for (connp = bind_connfp->connf_head; connp != NULL;
2306 	    connp = connp->conn_next) {
2307 		tcp = connp->conn_tcp;
2308 		if (IPCL_BIND_MATCH(connp, IPPROTO_TCP, laddr, lport) &&
2309 		    IPCL_ZONE_MATCH(connp, zoneid) &&
2310 		    (tcp->tcp_listener == NULL)) {
2311 			CONN_INC_REF(connp);
2312 			mutex_exit(&bind_connfp->connf_lock);
2313 			return (connp);
2314 		}
2315 	}
2316 	mutex_exit(&bind_connfp->connf_lock);
2317 	return (NULL);
2318 }
2319 
2320 /*
2321  * Finds a TCP/IPv6 listening connection; called by tcp_disconnect to locate
2322  * a listener when changing state.
2323  */
2324 conn_t *
2325 ipcl_lookup_listener_v6(uint16_t lport, in6_addr_t *laddr, uint_t ifindex,
2326     zoneid_t zoneid, ip_stack_t *ipst)
2327 {
2328 	connf_t		*bind_connfp;
2329 	conn_t		*connp = NULL;
2330 	tcp_t		*tcp;
2331 
2332 	/*
2333 	 * Avoid false matches for packets sent to an IP destination of
2334 	 * all zeros.
2335 	 */
2336 	if (IN6_IS_ADDR_UNSPECIFIED(laddr))
2337 		return (NULL);
2338 
2339 	ASSERT(zoneid != ALL_ZONES);
2340 
2341 	bind_connfp = &ipst->ips_ipcl_bind_fanout[IPCL_BIND_HASH(lport, ipst)];
2342 	mutex_enter(&bind_connfp->connf_lock);
2343 	for (connp = bind_connfp->connf_head; connp != NULL;
2344 	    connp = connp->conn_next) {
2345 		tcp = connp->conn_tcp;
2346 		if (IPCL_BIND_MATCH_V6(connp, IPPROTO_TCP, *laddr, lport) &&
2347 		    IPCL_ZONE_MATCH(connp, zoneid) &&
2348 		    (tcp->tcp_bound_if == 0 ||
2349 		    tcp->tcp_bound_if == ifindex) &&
2350 		    tcp->tcp_listener == NULL) {
2351 			CONN_INC_REF(connp);
2352 			mutex_exit(&bind_connfp->connf_lock);
2353 			return (connp);
2354 		}
2355 	}
2356 	mutex_exit(&bind_connfp->connf_lock);
2357 	return (NULL);
2358 }
2359 
2360 /*
2361  * ipcl_get_next_conn
2362  *	get the next entry in the conn global list
2363  *	and put a reference on the next_conn.
2364  *	decrement the reference on the current conn.
2365  *
2366  * This is an iterator based walker function that also provides for
2367  * some selection by the caller. It walks through the conn_hash bucket
2368  * searching for the next valid connp in the list, and selects connections
2369  * that are neither closed nor condemned. It also REFHOLDS the conn
2370  * thus ensuring that the conn exists when the caller uses the conn.
2371  */
2372 conn_t *
2373 ipcl_get_next_conn(connf_t *connfp, conn_t *connp, uint32_t conn_flags)
2374 {
2375 	conn_t	*next_connp;
2376 
2377 	if (connfp == NULL)
2378 		return (NULL);
2379 
2380 	mutex_enter(&connfp->connf_lock);
2381 
2382 	next_connp = (connp == NULL) ?
2383 	    connfp->connf_head : connp->conn_g_next;
2384 
2385 	while (next_connp != NULL) {
2386 		mutex_enter(&next_connp->conn_lock);
2387 		if (!(next_connp->conn_flags & conn_flags) ||
2388 		    (next_connp->conn_state_flags &
2389 		    (CONN_CONDEMNED | CONN_INCIPIENT))) {
2390 			/*
2391 			 * This conn has been condemned or
2392 			 * is closing, or the flags don't match
2393 			 */
2394 			mutex_exit(&next_connp->conn_lock);
2395 			next_connp = next_connp->conn_g_next;
2396 			continue;
2397 		}
2398 		CONN_INC_REF_LOCKED(next_connp);
2399 		mutex_exit(&next_connp->conn_lock);
2400 		break;
2401 	}
2402 
2403 	mutex_exit(&connfp->connf_lock);
2404 
2405 	if (connp != NULL)
2406 		CONN_DEC_REF(connp);
2407 
2408 	return (next_connp);
2409 }
2410 
2411 #ifdef CONN_DEBUG
2412 /*
2413  * Trace of the last NBUF refhold/refrele
2414  */
2415 int
2416 conn_trace_ref(conn_t *connp)
2417 {
2418 	int	last;
2419 	conn_trace_t	*ctb;
2420 
2421 	ASSERT(MUTEX_HELD(&connp->conn_lock));
2422 	last = connp->conn_trace_last;
2423 	last++;
2424 	if (last == CONN_TRACE_MAX)
2425 		last = 0;
2426 
2427 	ctb = &connp->conn_trace_buf[last];
2428 	ctb->ctb_depth = getpcstack(ctb->ctb_stack, CONN_STACK_DEPTH);
2429 	connp->conn_trace_last = last;
2430 	return (1);
2431 }
2432 
2433 int
2434 conn_untrace_ref(conn_t *connp)
2435 {
2436 	int	last;
2437 	conn_trace_t	*ctb;
2438 
2439 	ASSERT(MUTEX_HELD(&connp->conn_lock));
2440 	last = connp->conn_trace_last;
2441 	last++;
2442 	if (last == CONN_TRACE_MAX)
2443 		last = 0;
2444 
2445 	ctb = &connp->conn_trace_buf[last];
2446 	ctb->ctb_depth = getpcstack(ctb->ctb_stack, CONN_STACK_DEPTH);
2447 	connp->conn_trace_last = last;
2448 	return (1);
2449 }
2450 #endif
2451