docs/how-to-build.md: use proper markup for directory names
[unleashed/tickless.git] / kernel / net / sctp / sctp_hash.c
blob652376cd4f1932397cd7e56b8a5cedf95494be5b
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
23 * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
26 #include <sys/sysmacros.h>
27 #include <sys/socket.h>
28 #include <sys/ddi.h>
29 #include <sys/sunddi.h>
31 #include <netinet/in.h>
32 #include <netinet/ip6.h>
34 #include <inet/common.h>
35 #include <inet/ip.h>
36 #include <inet/ip6.h>
37 #include <inet/ipclassifier.h>
38 #include <inet/ipsec_impl.h>
39 #include <inet/ipp_common.h>
40 #include <inet/sctp_ip.h>
42 #include <inet/sctp/sctp_impl.h>
43 #include <inet/sctp/sctp_addr.h>
45 /* Default association hash size. The size must be a power of 2. */
46 #define SCTP_CONN_HASH_SIZE 8192
48 uint_t sctp_conn_hash_size = SCTP_CONN_HASH_SIZE; /* /etc/system */
50 void
51 sctp_hash_init(sctp_stack_t *sctps)
53 int i;
55 /* Start with /etc/system value */
56 sctps->sctps_conn_hash_size = sctp_conn_hash_size;
58 if (!ISP2(sctps->sctps_conn_hash_size)) {
59 /* Not a power of two. Round up to nearest power of two */
60 for (i = 0; i < 31; i++) {
61 if (sctps->sctps_conn_hash_size < (1 << i))
62 break;
64 sctps->sctps_conn_hash_size = 1 << i;
66 if (sctps->sctps_conn_hash_size < SCTP_CONN_HASH_SIZE) {
67 sctps->sctps_conn_hash_size = SCTP_CONN_HASH_SIZE;
68 cmn_err(CE_CONT, "using sctp_conn_hash_size = %u\n",
69 sctps->sctps_conn_hash_size);
71 sctps->sctps_conn_fanout =
72 (sctp_tf_t *)kmem_zalloc(sctps->sctps_conn_hash_size *
73 sizeof (sctp_tf_t), KM_SLEEP);
74 for (i = 0; i < sctps->sctps_conn_hash_size; i++) {
75 mutex_init(&sctps->sctps_conn_fanout[i].tf_lock, NULL,
76 MUTEX_DEFAULT, NULL);
78 sctps->sctps_listen_fanout = kmem_zalloc(SCTP_LISTEN_FANOUT_SIZE *
79 sizeof (sctp_tf_t), KM_SLEEP);
80 for (i = 0; i < SCTP_LISTEN_FANOUT_SIZE; i++) {
81 mutex_init(&sctps->sctps_listen_fanout[i].tf_lock, NULL,
82 MUTEX_DEFAULT, NULL);
84 sctps->sctps_bind_fanout = kmem_zalloc(SCTP_BIND_FANOUT_SIZE *
85 sizeof (sctp_tf_t), KM_SLEEP);
86 for (i = 0; i < SCTP_BIND_FANOUT_SIZE; i++) {
87 mutex_init(&sctps->sctps_bind_fanout[i].tf_lock, NULL,
88 MUTEX_DEFAULT, NULL);
92 void
93 sctp_hash_destroy(sctp_stack_t *sctps)
95 int i;
97 for (i = 0; i < sctps->sctps_conn_hash_size; i++) {
98 mutex_destroy(&sctps->sctps_conn_fanout[i].tf_lock);
100 kmem_free(sctps->sctps_conn_fanout, sctps->sctps_conn_hash_size *
101 sizeof (sctp_tf_t));
102 sctps->sctps_conn_fanout = NULL;
104 for (i = 0; i < SCTP_LISTEN_FANOUT_SIZE; i++) {
105 mutex_destroy(&sctps->sctps_listen_fanout[i].tf_lock);
107 kmem_free(sctps->sctps_listen_fanout, SCTP_LISTEN_FANOUT_SIZE *
108 sizeof (sctp_tf_t));
109 sctps->sctps_listen_fanout = NULL;
111 for (i = 0; i < SCTP_BIND_FANOUT_SIZE; i++) {
112 mutex_destroy(&sctps->sctps_bind_fanout[i].tf_lock);
114 kmem_free(sctps->sctps_bind_fanout, SCTP_BIND_FANOUT_SIZE *
115 sizeof (sctp_tf_t));
116 sctps->sctps_bind_fanout = NULL;
119 sctp_t *
120 sctp_conn_match(in6_addr_t **faddrpp, uint32_t nfaddr, in6_addr_t *laddr,
121 uint32_t ports, zoneid_t zoneid, iaflags_t iraflags, sctp_stack_t *sctps)
123 sctp_tf_t *tf;
124 sctp_t *sctp;
125 sctp_faddr_t *fp;
126 conn_t *connp;
127 in6_addr_t **faddrs, **endaddrs = &faddrpp[nfaddr];
129 tf = &(sctps->sctps_conn_fanout[SCTP_CONN_HASH(sctps, ports)]);
130 mutex_enter(&tf->tf_lock);
132 for (sctp = tf->tf_sctp; sctp != NULL; sctp =
133 sctp->sctp_conn_hash_next) {
134 connp = sctp->sctp_connp;
135 if (ports != connp->conn_ports)
136 continue;
137 if (!(connp->conn_zoneid == zoneid ||
138 connp->conn_allzones))
139 continue;
141 /* check for faddr match */
142 for (fp = sctp->sctp_faddrs; fp != NULL; fp = fp->sf_next) {
143 for (faddrs = faddrpp; faddrs < endaddrs; faddrs++) {
144 if (IN6_ARE_ADDR_EQUAL(*faddrs,
145 &fp->sf_faddr)) {
146 /* check for laddr match */
147 if (sctp_saddr_lookup(sctp, laddr, 0)
148 != NULL) {
149 SCTP_REFHOLD(sctp);
150 mutex_exit(&tf->tf_lock);
151 return (sctp);
157 /* no match; continue to the next in the chain */
160 mutex_exit(&tf->tf_lock);
161 return (sctp);
164 static sctp_t *
165 listen_match(in6_addr_t *laddr, uint32_t ports, zoneid_t zoneid,
166 iaflags_t iraflags, sctp_stack_t *sctps)
168 sctp_t *sctp;
169 sctp_tf_t *tf;
170 uint16_t lport;
171 conn_t *connp;
173 lport = ((uint16_t *)&ports)[1];
175 tf = &(sctps->sctps_listen_fanout[SCTP_LISTEN_HASH(ntohs(lport))]);
176 mutex_enter(&tf->tf_lock);
178 for (sctp = tf->tf_sctp; sctp; sctp = sctp->sctp_listen_hash_next) {
179 connp = sctp->sctp_connp;
180 if (lport != connp->conn_lport)
181 continue;
183 if (!(connp->conn_zoneid == zoneid ||
184 connp->conn_allzones))
185 continue;
187 if (sctp_saddr_lookup(sctp, laddr, 0) != NULL) {
188 SCTP_REFHOLD(sctp);
189 goto done;
191 /* no match; continue to the next in the chain */
194 done:
195 mutex_exit(&tf->tf_lock);
196 return (sctp);
199 /* called by ipsec_sctp_pol */
200 conn_t *
201 sctp_find_conn(in6_addr_t *src, in6_addr_t *dst, uint32_t ports,
202 zoneid_t zoneid, iaflags_t iraflags, sctp_stack_t *sctps)
204 sctp_t *sctp;
206 sctp = sctp_conn_match(&src, 1, dst, ports, zoneid, iraflags, sctps);
207 if (sctp == NULL) {
208 /* Not in conn fanout; check listen fanout */
209 sctp = listen_match(dst, ports, zoneid, iraflags, sctps);
210 if (sctp == NULL)
211 return (NULL);
213 return (sctp->sctp_connp);
217 * This is called from sctp_fanout() with IP header src & dst addresses.
218 * First call sctp_conn_match() to get a match by passing in src & dst
219 * addresses from IP header.
220 * However sctp_conn_match() can return no match under condition such as :
221 * A host can send an INIT ACK from a different address than the INIT was sent
222 * to (in a multi-homed env).
223 * According to RFC4960, a host can send additional addresses in an INIT
224 * ACK chunk.
225 * Therefore extract all addresses from the INIT ACK chunk, pass to
226 * sctp_conn_match() to get a match.
228 static sctp_t *
229 sctp_lookup_by_faddrs(mblk_t *mp, sctp_hdr_t *sctph, in6_addr_t *srcp,
230 in6_addr_t *dstp, uint32_t ports, zoneid_t zoneid, sctp_stack_t *sctps,
231 iaflags_t iraflags)
233 sctp_t *sctp;
234 sctp_chunk_hdr_t *ich;
235 sctp_init_chunk_t *iack;
236 sctp_parm_hdr_t *ph;
237 ssize_t mlen, remaining;
238 uint16_t param_type, addr_len = PARM_ADDR4_LEN;
239 in6_addr_t src;
240 in6_addr_t **addrbuf = NULL, **faddrpp = NULL;
241 boolean_t isv4;
242 uint32_t totaddr, nfaddr = 0;
245 * If we get a match with the passed-in IP header src & dst addresses,
246 * quickly return the matched sctp.
248 if ((sctp = sctp_conn_match(&srcp, 1, dstp, ports, zoneid, iraflags,
249 sctps)) != NULL) {
250 return (sctp);
254 * Currently sctph is set to NULL in icmp error fanout case
255 * (ip_fanout_sctp()).
256 * The above sctp_conn_match() should handle that, otherwise
257 * return no match found.
259 if (sctph == NULL)
260 return (NULL);
263 * Do a pullup again in case the previous one was partially successful,
264 * so try to complete the pullup here and have a single contiguous
265 * chunk for processing of entire INIT ACK chunk below.
267 if (mp->b_cont != NULL) {
268 if (pullupmsg(mp, -1) == 0) {
269 return (NULL);
273 mlen = mp->b_wptr - (uchar_t *)(sctph + 1);
274 if ((ich = sctp_first_chunk((uchar_t *)(sctph + 1), mlen)) == NULL) {
275 return (NULL);
278 if (ich->sch_id == CHUNK_INIT_ACK) {
279 remaining = ntohs(ich->sch_len) - sizeof (*ich) -
280 sizeof (*iack);
281 if (remaining < sizeof (*ph)) {
282 return (NULL);
285 isv4 = (iraflags & IRAF_IS_IPV4) ? B_TRUE : B_FALSE;
286 if (!isv4)
287 addr_len = PARM_ADDR6_LEN;
288 totaddr = remaining/addr_len;
290 iack = (sctp_init_chunk_t *)(ich + 1);
291 ph = (sctp_parm_hdr_t *)(iack + 1);
293 addrbuf = (in6_addr_t **)
294 kmem_zalloc(totaddr * sizeof (in6_addr_t *), KM_NOSLEEP);
295 if (addrbuf == NULL)
296 return (NULL);
297 faddrpp = addrbuf;
299 while (ph != NULL) {
301 * According to RFC4960 :
302 * All integer fields in an SCTP packet MUST be
303 * transmitted in network byte order,
304 * unless otherwise stated.
305 * Therefore convert the param type to host byte order.
306 * Also do not add src address present in IP header
307 * as it has already been thru sctp_conn_match() above.
309 param_type = ntohs(ph->sph_type);
310 switch (param_type) {
311 case PARM_ADDR4:
312 IN6_INADDR_TO_V4MAPPED((struct in_addr *)
313 (ph + 1), &src);
314 if (IN6_ARE_ADDR_EQUAL(&src, srcp))
315 break;
316 *faddrpp = (in6_addr_t *)
317 kmem_zalloc(sizeof (in6_addr_t),
318 KM_NOSLEEP);
319 if (*faddrpp == NULL)
320 break;
321 IN6_INADDR_TO_V4MAPPED((struct in_addr *)
322 (ph + 1), *faddrpp);
323 nfaddr++;
324 faddrpp++;
325 break;
326 case PARM_ADDR6:
327 *faddrpp = (in6_addr_t *)(ph + 1);
328 if (IN6_ARE_ADDR_EQUAL(*faddrpp, srcp))
329 break;
330 nfaddr++;
331 faddrpp++;
332 break;
333 default:
334 break;
336 ph = sctp_next_parm(ph, &remaining);
339 ASSERT(nfaddr < totaddr);
341 if (nfaddr > 0) {
342 sctp = sctp_conn_match(addrbuf, nfaddr, dstp, ports,
343 zoneid, iraflags, sctps);
345 if (isv4) {
346 for (faddrpp = addrbuf; nfaddr > 0;
347 faddrpp++, nfaddr--) {
348 if (IN6_IS_ADDR_V4MAPPED(*faddrpp)) {
349 kmem_free(*faddrpp,
350 sizeof (in6_addr_t));
355 kmem_free(addrbuf, totaddr * sizeof (in6_addr_t *));
357 return (sctp);
361 * Fanout to a sctp instance.
363 conn_t *
364 sctp_fanout(in6_addr_t *src, in6_addr_t *dst, uint32_t ports,
365 ip_recv_attr_t *ira, mblk_t *mp, sctp_stack_t *sctps, sctp_hdr_t *sctph)
367 zoneid_t zoneid = ira->ira_zoneid;
368 iaflags_t iraflags = ira->ira_flags;
369 sctp_t *sctp;
371 sctp = sctp_lookup_by_faddrs(mp, sctph, src, dst, ports, zoneid,
372 sctps, iraflags);
373 if (sctp == NULL) {
374 /* Not in conn fanout; check listen fanout */
375 sctp = listen_match(dst, ports, zoneid, iraflags, sctps);
376 if (sctp == NULL)
377 return (NULL);
380 * For labeled systems, there's no need to check the
381 * label here. It's known to be good as we checked
382 * before allowing the connection to become bound.
384 return (sctp->sctp_connp);
388 * Fanout for ICMP errors for SCTP
389 * The caller puts <fport, lport> in the ports parameter.
391 void
392 ip_fanout_sctp(mblk_t *mp, ipha_t *ipha, ip6_t *ip6h, uint32_t ports,
393 ip_recv_attr_t *ira)
395 sctp_t *sctp;
396 conn_t *connp;
397 in6_addr_t map_src, map_dst;
398 in6_addr_t *src, *dst;
399 boolean_t secure;
400 ill_t *ill = ira->ira_ill;
401 ip_stack_t *ipst = ill->ill_ipst;
402 netstack_t *ns = ipst->ips_netstack;
403 ipsec_stack_t *ipss = ns->netstack_ipsec;
404 sctp_stack_t *sctps = ns->netstack_sctp;
405 iaflags_t iraflags = ira->ira_flags;
406 ill_t *rill = ira->ira_rill;
408 ASSERT(iraflags & IRAF_ICMP_ERROR);
410 secure = iraflags & IRAF_IPSEC_SECURE;
412 /* Assume IP provides aligned packets - otherwise toss */
413 if (!OK_32PTR(mp->b_rptr)) {
414 BUMP_MIB(ill->ill_ip_mib, ipIfStatsInDiscards);
415 ip_drop_input("ipIfStatsInDiscards", mp, ill);
416 freemsg(mp);
417 return;
420 if (!(iraflags & IRAF_IS_IPV4)) {
421 src = &ip6h->ip6_src;
422 dst = &ip6h->ip6_dst;
423 } else {
424 IN6_IPADDR_TO_V4MAPPED(ipha->ipha_src, &map_src);
425 IN6_IPADDR_TO_V4MAPPED(ipha->ipha_dst, &map_dst);
426 src = &map_src;
427 dst = &map_dst;
429 connp = sctp_fanout(src, dst, ports, ira, mp, sctps, NULL);
430 if (connp == NULL) {
431 ip_fanout_sctp_raw(mp, ipha, ip6h, ports, ira);
432 return;
434 sctp = CONN2SCTP(connp);
437 * We check some fields in conn_t without holding a lock.
438 * This should be fine.
440 if (((iraflags & IRAF_IS_IPV4) ?
441 CONN_INBOUND_POLICY_PRESENT(connp, ipss) :
442 CONN_INBOUND_POLICY_PRESENT_V6(connp, ipss)) ||
443 secure) {
444 mp = ipsec_check_inbound_policy(mp, connp, ipha,
445 ip6h, ira);
446 if (mp == NULL) {
447 SCTP_REFRELE(sctp);
448 return;
452 ira->ira_ill = ira->ira_rill = NULL;
454 mutex_enter(&sctp->sctp_lock);
455 if (sctp->sctp_running) {
456 sctp_add_recvq(sctp, mp, B_FALSE, ira);
457 mutex_exit(&sctp->sctp_lock);
458 } else {
459 sctp->sctp_running = B_TRUE;
460 mutex_exit(&sctp->sctp_lock);
462 mutex_enter(&sctp->sctp_recvq_lock);
463 if (sctp->sctp_recvq != NULL) {
464 sctp_add_recvq(sctp, mp, B_TRUE, ira);
465 mutex_exit(&sctp->sctp_recvq_lock);
466 WAKE_SCTP(sctp);
467 } else {
468 mutex_exit(&sctp->sctp_recvq_lock);
469 if (ira->ira_flags & IRAF_ICMP_ERROR) {
470 sctp_icmp_error(sctp, mp);
471 } else {
472 sctp_input_data(sctp, mp, ira);
474 WAKE_SCTP(sctp);
477 SCTP_REFRELE(sctp);
478 ira->ira_ill = ill;
479 ira->ira_rill = rill;
482 void
483 sctp_conn_hash_remove(sctp_t *sctp)
485 sctp_tf_t *tf = sctp->sctp_conn_tfp;
487 if (!tf) {
488 return;
491 mutex_enter(&tf->tf_lock);
492 ASSERT(tf->tf_sctp);
493 if (tf->tf_sctp == sctp) {
494 tf->tf_sctp = sctp->sctp_conn_hash_next;
495 if (sctp->sctp_conn_hash_next) {
496 ASSERT(tf->tf_sctp->sctp_conn_hash_prev == sctp);
497 tf->tf_sctp->sctp_conn_hash_prev = NULL;
499 } else {
500 ASSERT(sctp->sctp_conn_hash_prev);
501 ASSERT(sctp->sctp_conn_hash_prev->sctp_conn_hash_next == sctp);
502 sctp->sctp_conn_hash_prev->sctp_conn_hash_next =
503 sctp->sctp_conn_hash_next;
505 if (sctp->sctp_conn_hash_next) {
506 ASSERT(sctp->sctp_conn_hash_next->sctp_conn_hash_prev
507 == sctp);
508 sctp->sctp_conn_hash_next->sctp_conn_hash_prev =
509 sctp->sctp_conn_hash_prev;
512 sctp->sctp_conn_hash_next = NULL;
513 sctp->sctp_conn_hash_prev = NULL;
514 sctp->sctp_conn_tfp = NULL;
515 mutex_exit(&tf->tf_lock);
518 void
519 sctp_conn_hash_insert(sctp_tf_t *tf, sctp_t *sctp, int caller_holds_lock)
521 if (sctp->sctp_conn_tfp) {
522 sctp_conn_hash_remove(sctp);
525 if (!caller_holds_lock) {
526 mutex_enter(&tf->tf_lock);
527 } else {
528 ASSERT(MUTEX_HELD(&tf->tf_lock));
531 sctp->sctp_conn_hash_next = tf->tf_sctp;
532 if (tf->tf_sctp) {
533 tf->tf_sctp->sctp_conn_hash_prev = sctp;
535 sctp->sctp_conn_hash_prev = NULL;
536 tf->tf_sctp = sctp;
537 sctp->sctp_conn_tfp = tf;
538 if (!caller_holds_lock) {
539 mutex_exit(&tf->tf_lock);
543 void
544 sctp_listen_hash_remove(sctp_t *sctp)
546 sctp_tf_t *tf = sctp->sctp_listen_tfp;
548 if (!tf) {
549 return;
552 mutex_enter(&tf->tf_lock);
553 ASSERT(tf->tf_sctp);
554 if (tf->tf_sctp == sctp) {
555 tf->tf_sctp = sctp->sctp_listen_hash_next;
556 if (sctp->sctp_listen_hash_next != NULL) {
557 ASSERT(tf->tf_sctp->sctp_listen_hash_prev == sctp);
558 tf->tf_sctp->sctp_listen_hash_prev = NULL;
560 } else {
561 ASSERT(sctp->sctp_listen_hash_prev);
562 ASSERT(sctp->sctp_listen_hash_prev->sctp_listen_hash_next ==
563 sctp);
564 ASSERT(sctp->sctp_listen_hash_next == NULL ||
565 sctp->sctp_listen_hash_next->sctp_listen_hash_prev == sctp);
567 sctp->sctp_listen_hash_prev->sctp_listen_hash_next =
568 sctp->sctp_listen_hash_next;
570 if (sctp->sctp_listen_hash_next != NULL) {
571 sctp_t *next = sctp->sctp_listen_hash_next;
573 ASSERT(next->sctp_listen_hash_prev == sctp);
574 next->sctp_listen_hash_prev =
575 sctp->sctp_listen_hash_prev;
578 sctp->sctp_listen_hash_next = NULL;
579 sctp->sctp_listen_hash_prev = NULL;
580 sctp->sctp_listen_tfp = NULL;
581 mutex_exit(&tf->tf_lock);
584 void
585 sctp_listen_hash_insert(sctp_tf_t *tf, sctp_t *sctp)
587 if (sctp->sctp_listen_tfp) {
588 sctp_listen_hash_remove(sctp);
591 mutex_enter(&tf->tf_lock);
592 sctp->sctp_listen_hash_next = tf->tf_sctp;
593 if (tf->tf_sctp) {
594 tf->tf_sctp->sctp_listen_hash_prev = sctp;
596 sctp->sctp_listen_hash_prev = NULL;
597 tf->tf_sctp = sctp;
598 sctp->sctp_listen_tfp = tf;
599 mutex_exit(&tf->tf_lock);
603 * Hash list insertion routine for sctp_t structures.
604 * Inserts entries with the ones bound to a specific IP address first
605 * followed by those bound to INADDR_ANY.
607 void
608 sctp_bind_hash_insert(sctp_tf_t *tbf, sctp_t *sctp, int caller_holds_lock)
610 sctp_t **sctpp;
611 sctp_t *sctpnext;
613 if (sctp->sctp_ptpbhn != NULL) {
614 ASSERT(!caller_holds_lock);
615 sctp_bind_hash_remove(sctp);
617 sctpp = &tbf->tf_sctp;
618 if (!caller_holds_lock) {
619 mutex_enter(&tbf->tf_lock);
620 } else {
621 ASSERT(MUTEX_HELD(&tbf->tf_lock));
623 sctpnext = sctpp[0];
624 if (sctpnext) {
625 sctpnext->sctp_ptpbhn = &sctp->sctp_bind_hash;
627 sctp->sctp_bind_hash = sctpnext;
628 sctp->sctp_ptpbhn = sctpp;
629 sctpp[0] = sctp;
630 /* For sctp_*_hash_remove */
631 sctp->sctp_bind_lockp = &tbf->tf_lock;
632 if (!caller_holds_lock)
633 mutex_exit(&tbf->tf_lock);
637 * Hash list removal routine for sctp_t structures.
639 void
640 sctp_bind_hash_remove(sctp_t *sctp)
642 sctp_t *sctpnext;
643 kmutex_t *lockp;
645 lockp = sctp->sctp_bind_lockp;
647 if (sctp->sctp_ptpbhn == NULL)
648 return;
650 ASSERT(lockp != NULL);
651 mutex_enter(lockp);
652 if (sctp->sctp_ptpbhn) {
653 sctpnext = sctp->sctp_bind_hash;
654 if (sctpnext) {
655 sctpnext->sctp_ptpbhn = sctp->sctp_ptpbhn;
656 sctp->sctp_bind_hash = NULL;
658 *sctp->sctp_ptpbhn = sctpnext;
659 sctp->sctp_ptpbhn = NULL;
661 mutex_exit(lockp);
662 sctp->sctp_bind_lockp = NULL;
666 * Similar to but different from sctp_conn_match().
668 * Matches sets of addresses as follows: if the argument addr set is
669 * a complete subset of the corresponding addr set in the sctp_t, it
670 * is a match.
672 * Caller must hold tf->tf_lock.
674 * Returns with a SCTP_REFHOLD sctp structure. Caller must do a SCTP_REFRELE.
676 sctp_t *
677 sctp_lookup(sctp_t *sctp1, in6_addr_t *faddr, sctp_tf_t *tf, uint32_t *ports,
678 int min_state)
680 sctp_t *sctp;
681 sctp_faddr_t *fp;
683 ASSERT(MUTEX_HELD(&tf->tf_lock));
685 for (sctp = tf->tf_sctp; sctp != NULL;
686 sctp = sctp->sctp_conn_hash_next) {
687 if (*ports != sctp->sctp_connp->conn_ports ||
688 sctp->sctp_state < min_state) {
689 continue;
692 /* check for faddr match */
693 for (fp = sctp->sctp_faddrs; fp != NULL; fp = fp->sf_next) {
694 if (IN6_ARE_ADDR_EQUAL(faddr, &fp->sf_faddr)) {
695 break;
699 if (fp == NULL) {
700 /* no faddr match; keep looking */
701 continue;
705 * There is an existing association with the same peer
706 * address. So now we need to check if our local address
707 * set overlaps with the one of the existing association.
708 * If they overlap, we should return it.
710 if (sctp_compare_saddrs(sctp1, sctp) <= SCTP_ADDR_OVERLAP) {
711 goto done;
714 /* no match; continue searching */
717 done:
718 if (sctp != NULL) {
719 SCTP_REFHOLD(sctp);
721 return (sctp);