Print this page
5255 uts shouldn't open-code ISP2
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/inet/sctp/sctp_hash.c
+++ new/usr/src/uts/common/inet/sctp/sctp_hash.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
↓ open down ↓ |
15 lines elided |
↑ open up ↑ |
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
24 24 */
25 25
26 +#include <sys/sysmacros.h>
26 27 #include <sys/socket.h>
27 28 #include <sys/ddi.h>
28 29 #include <sys/sunddi.h>
29 30 #include <sys/tsol/tndb.h>
30 31 #include <sys/tsol/tnet.h>
31 32
32 33 #include <netinet/in.h>
33 34 #include <netinet/ip6.h>
34 35
35 36 #include <inet/common.h>
36 37 #include <inet/ip.h>
37 38 #include <inet/ip6.h>
38 39 #include <inet/ipclassifier.h>
39 40 #include <inet/ipsec_impl.h>
40 41 #include <inet/ipp_common.h>
41 42 #include <inet/sctp_ip.h>
42 43
43 44 #include "sctp_impl.h"
44 45 #include "sctp_addr.h"
45 46
46 47 /* Default association hash size. The size must be a power of 2. */
47 48 #define SCTP_CONN_HASH_SIZE 8192
48 49
49 50 uint_t sctp_conn_hash_size = SCTP_CONN_HASH_SIZE; /* /etc/system */
50 51
51 52 /*
52 53 * Cluster networking hook for traversing current assoc list.
53 54 * This routine is used to extract the current list of live associations
54 55 * which must continue to to be dispatched to this node.
55 56 */
56 57 int cl_sctp_walk_list(int (*cl_callback)(cl_sctp_info_t *, void *), void *,
57 58 boolean_t);
58 59 static int cl_sctp_walk_list_stack(int (*cl_callback)(cl_sctp_info_t *,
↓ open down ↓ |
23 lines elided |
↑ open up ↑ |
59 60 void *), void *arg, boolean_t cansleep, sctp_stack_t *sctps);
60 61
61 62 void
62 63 sctp_hash_init(sctp_stack_t *sctps)
63 64 {
64 65 int i;
65 66
66 67 /* Start with /etc/system value */
67 68 sctps->sctps_conn_hash_size = sctp_conn_hash_size;
68 69
69 - if (sctps->sctps_conn_hash_size & (sctps->sctps_conn_hash_size - 1)) {
70 + if (!ISP2(sctps->sctps_conn_hash_size)) {
70 71 /* Not a power of two. Round up to nearest power of two */
71 72 for (i = 0; i < 31; i++) {
72 73 if (sctps->sctps_conn_hash_size < (1 << i))
73 74 break;
74 75 }
75 76 sctps->sctps_conn_hash_size = 1 << i;
76 77 }
77 78 if (sctps->sctps_conn_hash_size < SCTP_CONN_HASH_SIZE) {
78 79 sctps->sctps_conn_hash_size = SCTP_CONN_HASH_SIZE;
79 80 cmn_err(CE_CONT, "using sctp_conn_hash_size = %u\n",
80 81 sctps->sctps_conn_hash_size);
81 82 }
82 83 sctps->sctps_conn_fanout =
83 84 (sctp_tf_t *)kmem_zalloc(sctps->sctps_conn_hash_size *
84 85 sizeof (sctp_tf_t), KM_SLEEP);
85 86 for (i = 0; i < sctps->sctps_conn_hash_size; i++) {
86 87 mutex_init(&sctps->sctps_conn_fanout[i].tf_lock, NULL,
87 88 MUTEX_DEFAULT, NULL);
88 89 }
89 90 sctps->sctps_listen_fanout = kmem_zalloc(SCTP_LISTEN_FANOUT_SIZE *
90 91 sizeof (sctp_tf_t), KM_SLEEP);
91 92 for (i = 0; i < SCTP_LISTEN_FANOUT_SIZE; i++) {
92 93 mutex_init(&sctps->sctps_listen_fanout[i].tf_lock, NULL,
93 94 MUTEX_DEFAULT, NULL);
94 95 }
95 96 sctps->sctps_bind_fanout = kmem_zalloc(SCTP_BIND_FANOUT_SIZE *
96 97 sizeof (sctp_tf_t), KM_SLEEP);
97 98 for (i = 0; i < SCTP_BIND_FANOUT_SIZE; i++) {
98 99 mutex_init(&sctps->sctps_bind_fanout[i].tf_lock, NULL,
99 100 MUTEX_DEFAULT, NULL);
100 101 }
101 102 }
102 103
103 104 void
104 105 sctp_hash_destroy(sctp_stack_t *sctps)
105 106 {
106 107 int i;
107 108
108 109 for (i = 0; i < sctps->sctps_conn_hash_size; i++) {
109 110 mutex_destroy(&sctps->sctps_conn_fanout[i].tf_lock);
110 111 }
111 112 kmem_free(sctps->sctps_conn_fanout, sctps->sctps_conn_hash_size *
112 113 sizeof (sctp_tf_t));
113 114 sctps->sctps_conn_fanout = NULL;
114 115
115 116 for (i = 0; i < SCTP_LISTEN_FANOUT_SIZE; i++) {
116 117 mutex_destroy(&sctps->sctps_listen_fanout[i].tf_lock);
117 118 }
118 119 kmem_free(sctps->sctps_listen_fanout, SCTP_LISTEN_FANOUT_SIZE *
119 120 sizeof (sctp_tf_t));
120 121 sctps->sctps_listen_fanout = NULL;
121 122
122 123 for (i = 0; i < SCTP_BIND_FANOUT_SIZE; i++) {
123 124 mutex_destroy(&sctps->sctps_bind_fanout[i].tf_lock);
124 125 }
125 126 kmem_free(sctps->sctps_bind_fanout, SCTP_BIND_FANOUT_SIZE *
126 127 sizeof (sctp_tf_t));
127 128 sctps->sctps_bind_fanout = NULL;
128 129 }
129 130
130 131 /*
131 132 * Exported routine for extracting active SCTP associations.
132 133 * Like TCP, we terminate the walk if the callback returns non-zero.
133 134 *
134 135 * Need to walk all sctp_stack_t instances since this clustering
135 136 * interface is assumed global for all instances
136 137 */
137 138 int
138 139 cl_sctp_walk_list(int (*cl_callback)(cl_sctp_info_t *, void *),
139 140 void *arg, boolean_t cansleep)
140 141 {
141 142 netstack_handle_t nh;
142 143 netstack_t *ns;
143 144 int ret = 0;
144 145
145 146 netstack_next_init(&nh);
146 147 while ((ns = netstack_next(&nh)) != NULL) {
147 148 ret = cl_sctp_walk_list_stack(cl_callback, arg, cansleep,
148 149 ns->netstack_sctp);
149 150 netstack_rele(ns);
150 151 }
151 152 netstack_next_fini(&nh);
152 153 return (ret);
153 154 }
154 155
155 156 static int
156 157 cl_sctp_walk_list_stack(int (*cl_callback)(cl_sctp_info_t *, void *),
157 158 void *arg, boolean_t cansleep, sctp_stack_t *sctps)
158 159 {
159 160 sctp_t *sctp;
160 161 sctp_t *sctp_prev;
161 162 cl_sctp_info_t cl_sctpi;
162 163 uchar_t *slist;
163 164 uchar_t *flist;
164 165
165 166 sctp_prev = NULL;
166 167 mutex_enter(&sctps->sctps_g_lock);
167 168 sctp = list_head(&sctps->sctps_g_list);
168 169 while (sctp != NULL) {
169 170 size_t ssize;
170 171 size_t fsize;
171 172
172 173 mutex_enter(&sctp->sctp_reflock);
173 174 if (sctp->sctp_condemned || sctp->sctp_state <= SCTPS_LISTEN) {
174 175 mutex_exit(&sctp->sctp_reflock);
175 176 sctp = list_next(&sctps->sctps_g_list, sctp);
176 177 continue;
177 178 }
178 179 sctp->sctp_refcnt++;
179 180 mutex_exit(&sctp->sctp_reflock);
180 181 mutex_exit(&sctps->sctps_g_lock);
181 182 if (sctp_prev != NULL)
182 183 SCTP_REFRELE(sctp_prev);
183 184 RUN_SCTP(sctp);
184 185 ssize = sizeof (in6_addr_t) * sctp->sctp_nsaddrs;
185 186 fsize = sizeof (in6_addr_t) * sctp->sctp_nfaddrs;
186 187
187 188 slist = kmem_alloc(ssize, cansleep ? KM_SLEEP : KM_NOSLEEP);
188 189 flist = kmem_alloc(fsize, cansleep ? KM_SLEEP : KM_NOSLEEP);
189 190 if (slist == NULL || flist == NULL) {
190 191 WAKE_SCTP(sctp);
191 192 if (slist != NULL)
192 193 kmem_free(slist, ssize);
193 194 if (flist != NULL)
194 195 kmem_free(flist, fsize);
195 196 SCTP_REFRELE(sctp);
196 197 return (1);
197 198 }
198 199 cl_sctpi.cl_sctpi_version = CL_SCTPI_V1;
199 200 sctp_get_saddr_list(sctp, slist, ssize);
200 201 sctp_get_faddr_list(sctp, flist, fsize);
201 202 cl_sctpi.cl_sctpi_nladdr = sctp->sctp_nsaddrs;
202 203 cl_sctpi.cl_sctpi_nfaddr = sctp->sctp_nfaddrs;
203 204 cl_sctpi.cl_sctpi_family = sctp->sctp_connp->conn_family;
204 205 if (cl_sctpi.cl_sctpi_family == AF_INET)
205 206 cl_sctpi.cl_sctpi_ipversion = IPV4_VERSION;
206 207 else
207 208 cl_sctpi.cl_sctpi_ipversion = IPV6_VERSION;
208 209 cl_sctpi.cl_sctpi_state = sctp->sctp_state;
209 210 cl_sctpi.cl_sctpi_lport = sctp->sctp_connp->conn_lport;
210 211 cl_sctpi.cl_sctpi_fport = sctp->sctp_connp->conn_fport;
211 212 cl_sctpi.cl_sctpi_handle = (cl_sctp_handle_t)sctp;
212 213 WAKE_SCTP(sctp);
213 214 cl_sctpi.cl_sctpi_laddrp = slist;
214 215 cl_sctpi.cl_sctpi_faddrp = flist;
215 216 if ((*cl_callback)(&cl_sctpi, arg) != 0) {
216 217 kmem_free(slist, ssize);
217 218 kmem_free(flist, fsize);
218 219 SCTP_REFRELE(sctp);
219 220 return (1);
220 221 }
221 222 /* list will be freed by cl_callback */
222 223 sctp_prev = sctp;
223 224 mutex_enter(&sctps->sctps_g_lock);
224 225 sctp = list_next(&sctps->sctps_g_list, sctp);
225 226 }
226 227 mutex_exit(&sctps->sctps_g_lock);
227 228 if (sctp_prev != NULL)
228 229 SCTP_REFRELE(sctp_prev);
229 230 return (0);
230 231 }
231 232
232 233 sctp_t *
233 234 sctp_conn_match(in6_addr_t **faddrpp, uint32_t nfaddr, in6_addr_t *laddr,
234 235 uint32_t ports, zoneid_t zoneid, iaflags_t iraflags, sctp_stack_t *sctps)
235 236 {
236 237 sctp_tf_t *tf;
237 238 sctp_t *sctp;
238 239 sctp_faddr_t *fp;
239 240 conn_t *connp;
240 241 in6_addr_t **faddrs, **endaddrs = &faddrpp[nfaddr];
241 242
242 243 tf = &(sctps->sctps_conn_fanout[SCTP_CONN_HASH(sctps, ports)]);
243 244 mutex_enter(&tf->tf_lock);
244 245
245 246 for (sctp = tf->tf_sctp; sctp != NULL; sctp =
246 247 sctp->sctp_conn_hash_next) {
247 248 connp = sctp->sctp_connp;
248 249 if (ports != connp->conn_ports)
249 250 continue;
250 251 if (!(connp->conn_zoneid == zoneid ||
251 252 connp->conn_allzones ||
252 253 ((connp->conn_mac_mode != CONN_MAC_DEFAULT) &&
253 254 (iraflags & IRAF_TX_MAC_EXEMPTABLE) &&
254 255 (iraflags & IRAF_TX_SHARED_ADDR))))
255 256 continue;
256 257
257 258 /* check for faddr match */
258 259 for (fp = sctp->sctp_faddrs; fp != NULL; fp = fp->sf_next) {
259 260 for (faddrs = faddrpp; faddrs < endaddrs; faddrs++) {
260 261 if (IN6_ARE_ADDR_EQUAL(*faddrs,
261 262 &fp->sf_faddr)) {
262 263 /* check for laddr match */
263 264 if (sctp_saddr_lookup(sctp, laddr, 0)
264 265 != NULL) {
265 266 SCTP_REFHOLD(sctp);
266 267 mutex_exit(&tf->tf_lock);
267 268 return (sctp);
268 269 }
269 270 }
270 271 }
271 272 }
272 273
273 274 /* no match; continue to the next in the chain */
274 275 }
275 276
276 277 mutex_exit(&tf->tf_lock);
277 278 return (sctp);
278 279 }
279 280
280 281 static sctp_t *
281 282 listen_match(in6_addr_t *laddr, uint32_t ports, zoneid_t zoneid,
282 283 iaflags_t iraflags, sctp_stack_t *sctps)
283 284 {
284 285 sctp_t *sctp;
285 286 sctp_tf_t *tf;
286 287 uint16_t lport;
287 288 conn_t *connp;
288 289
289 290 lport = ((uint16_t *)&ports)[1];
290 291
291 292 tf = &(sctps->sctps_listen_fanout[SCTP_LISTEN_HASH(ntohs(lport))]);
292 293 mutex_enter(&tf->tf_lock);
293 294
294 295 for (sctp = tf->tf_sctp; sctp; sctp = sctp->sctp_listen_hash_next) {
295 296 connp = sctp->sctp_connp;
296 297 if (lport != connp->conn_lport)
297 298 continue;
298 299
299 300 if (!(connp->conn_zoneid == zoneid ||
300 301 connp->conn_allzones ||
301 302 ((connp->conn_mac_mode != CONN_MAC_DEFAULT) &&
302 303 (iraflags & IRAF_TX_MAC_EXEMPTABLE) &&
303 304 (iraflags & IRAF_TX_SHARED_ADDR))))
304 305 continue;
305 306
306 307 if (sctp_saddr_lookup(sctp, laddr, 0) != NULL) {
307 308 SCTP_REFHOLD(sctp);
308 309 goto done;
309 310 }
310 311 /* no match; continue to the next in the chain */
311 312 }
312 313
313 314 done:
314 315 mutex_exit(&tf->tf_lock);
315 316 return (sctp);
316 317 }
317 318
318 319 /* called by ipsec_sctp_pol */
319 320 conn_t *
320 321 sctp_find_conn(in6_addr_t *src, in6_addr_t *dst, uint32_t ports,
321 322 zoneid_t zoneid, iaflags_t iraflags, sctp_stack_t *sctps)
322 323 {
323 324 sctp_t *sctp;
324 325
325 326 sctp = sctp_conn_match(&src, 1, dst, ports, zoneid, iraflags, sctps);
326 327 if (sctp == NULL) {
327 328 /* Not in conn fanout; check listen fanout */
328 329 sctp = listen_match(dst, ports, zoneid, iraflags, sctps);
329 330 if (sctp == NULL)
330 331 return (NULL);
331 332 }
332 333 return (sctp->sctp_connp);
333 334 }
334 335
335 336 /*
336 337 * This is called from sctp_fanout() with IP header src & dst addresses.
337 338 * First call sctp_conn_match() to get a match by passing in src & dst
338 339 * addresses from IP header.
339 340 * However sctp_conn_match() can return no match under condition such as :
340 341 * A host can send an INIT ACK from a different address than the INIT was sent
341 342 * to (in a multi-homed env).
342 343 * According to RFC4960, a host can send additional addresses in an INIT
343 344 * ACK chunk.
344 345 * Therefore extract all addresses from the INIT ACK chunk, pass to
345 346 * sctp_conn_match() to get a match.
346 347 */
347 348 static sctp_t *
348 349 sctp_lookup_by_faddrs(mblk_t *mp, sctp_hdr_t *sctph, in6_addr_t *srcp,
349 350 in6_addr_t *dstp, uint32_t ports, zoneid_t zoneid, sctp_stack_t *sctps,
350 351 iaflags_t iraflags)
351 352 {
352 353 sctp_t *sctp;
353 354 sctp_chunk_hdr_t *ich;
354 355 sctp_init_chunk_t *iack;
355 356 sctp_parm_hdr_t *ph;
356 357 ssize_t mlen, remaining;
357 358 uint16_t param_type, addr_len = PARM_ADDR4_LEN;
358 359 in6_addr_t src;
359 360 in6_addr_t **addrbuf = NULL, **faddrpp = NULL;
360 361 boolean_t isv4;
361 362 uint32_t totaddr, nfaddr = 0;
362 363
363 364 /*
364 365 * If we get a match with the passed-in IP header src & dst addresses,
365 366 * quickly return the matched sctp.
366 367 */
367 368 if ((sctp = sctp_conn_match(&srcp, 1, dstp, ports, zoneid, iraflags,
368 369 sctps)) != NULL) {
369 370 return (sctp);
370 371 }
371 372
372 373 /*
373 374 * Currently sctph is set to NULL in icmp error fanout case
374 375 * (ip_fanout_sctp()).
375 376 * The above sctp_conn_match() should handle that, otherwise
376 377 * return no match found.
377 378 */
378 379 if (sctph == NULL)
379 380 return (NULL);
380 381
381 382 /*
382 383 * Do a pullup again in case the previous one was partially successful,
383 384 * so try to complete the pullup here and have a single contiguous
384 385 * chunk for processing of entire INIT ACK chunk below.
385 386 */
386 387 if (mp->b_cont != NULL) {
387 388 if (pullupmsg(mp, -1) == 0) {
388 389 return (NULL);
389 390 }
390 391 }
391 392
392 393 mlen = mp->b_wptr - (uchar_t *)(sctph + 1);
393 394 if ((ich = sctp_first_chunk((uchar_t *)(sctph + 1), mlen)) == NULL) {
394 395 return (NULL);
395 396 }
396 397
397 398 if (ich->sch_id == CHUNK_INIT_ACK) {
398 399 remaining = ntohs(ich->sch_len) - sizeof (*ich) -
399 400 sizeof (*iack);
400 401 if (remaining < sizeof (*ph)) {
401 402 return (NULL);
402 403 }
403 404
404 405 isv4 = (iraflags & IRAF_IS_IPV4) ? B_TRUE : B_FALSE;
405 406 if (!isv4)
406 407 addr_len = PARM_ADDR6_LEN;
407 408 totaddr = remaining/addr_len;
408 409
409 410 iack = (sctp_init_chunk_t *)(ich + 1);
410 411 ph = (sctp_parm_hdr_t *)(iack + 1);
411 412
412 413 addrbuf = (in6_addr_t **)
413 414 kmem_zalloc(totaddr * sizeof (in6_addr_t *), KM_NOSLEEP);
414 415 if (addrbuf == NULL)
415 416 return (NULL);
416 417 faddrpp = addrbuf;
417 418
418 419 while (ph != NULL) {
419 420 /*
420 421 * According to RFC4960 :
421 422 * All integer fields in an SCTP packet MUST be
422 423 * transmitted in network byte order,
423 424 * unless otherwise stated.
424 425 * Therefore convert the param type to host byte order.
425 426 * Also do not add src address present in IP header
426 427 * as it has already been thru sctp_conn_match() above.
427 428 */
428 429 param_type = ntohs(ph->sph_type);
429 430 switch (param_type) {
430 431 case PARM_ADDR4:
431 432 IN6_INADDR_TO_V4MAPPED((struct in_addr *)
432 433 (ph + 1), &src);
433 434 if (IN6_ARE_ADDR_EQUAL(&src, srcp))
434 435 break;
435 436 *faddrpp = (in6_addr_t *)
436 437 kmem_zalloc(sizeof (in6_addr_t),
437 438 KM_NOSLEEP);
438 439 if (*faddrpp == NULL)
439 440 break;
440 441 IN6_INADDR_TO_V4MAPPED((struct in_addr *)
441 442 (ph + 1), *faddrpp);
442 443 nfaddr++;
443 444 faddrpp++;
444 445 break;
445 446 case PARM_ADDR6:
446 447 *faddrpp = (in6_addr_t *)(ph + 1);
447 448 if (IN6_ARE_ADDR_EQUAL(*faddrpp, srcp))
448 449 break;
449 450 nfaddr++;
450 451 faddrpp++;
451 452 break;
452 453 default:
453 454 break;
454 455 }
455 456 ph = sctp_next_parm(ph, &remaining);
456 457 }
457 458
458 459 ASSERT(nfaddr < totaddr);
459 460
460 461 if (nfaddr > 0) {
461 462 sctp = sctp_conn_match(addrbuf, nfaddr, dstp, ports,
462 463 zoneid, iraflags, sctps);
463 464
464 465 if (isv4) {
465 466 for (faddrpp = addrbuf; nfaddr > 0;
466 467 faddrpp++, nfaddr--) {
467 468 if (IN6_IS_ADDR_V4MAPPED(*faddrpp)) {
468 469 kmem_free(*faddrpp,
469 470 sizeof (in6_addr_t));
470 471 }
471 472 }
472 473 }
473 474 }
474 475 kmem_free(addrbuf, totaddr * sizeof (in6_addr_t *));
475 476 }
476 477 return (sctp);
477 478 }
478 479
479 480 /*
480 481 * Fanout to a sctp instance.
481 482 */
482 483 conn_t *
483 484 sctp_fanout(in6_addr_t *src, in6_addr_t *dst, uint32_t ports,
484 485 ip_recv_attr_t *ira, mblk_t *mp, sctp_stack_t *sctps, sctp_hdr_t *sctph)
485 486 {
486 487 zoneid_t zoneid = ira->ira_zoneid;
487 488 iaflags_t iraflags = ira->ira_flags;
488 489 sctp_t *sctp;
489 490
490 491 sctp = sctp_lookup_by_faddrs(mp, sctph, src, dst, ports, zoneid,
491 492 sctps, iraflags);
492 493 if (sctp == NULL) {
493 494 /* Not in conn fanout; check listen fanout */
494 495 sctp = listen_match(dst, ports, zoneid, iraflags, sctps);
495 496 if (sctp == NULL)
496 497 return (NULL);
497 498 /*
498 499 * On systems running trusted extensions, check if dst
499 500 * should accept the packet. "IPV6_VERSION" indicates
500 501 * that dst is in 16 byte AF_INET6 format. IPv4-mapped
501 502 * IPv6 addresses are supported.
502 503 */
503 504 if ((iraflags & IRAF_SYSTEM_LABELED) &&
504 505 !tsol_receive_local(mp, dst, IPV6_VERSION, ira,
505 506 sctp->sctp_connp)) {
506 507 DTRACE_PROBE3(
507 508 tx__ip__log__info__classify__sctp,
508 509 char *,
509 510 "connp(1) could not receive mp(2)",
510 511 conn_t *, sctp->sctp_connp, mblk_t *, mp);
511 512 SCTP_REFRELE(sctp);
512 513 return (NULL);
513 514 }
514 515 }
515 516 /*
516 517 * For labeled systems, there's no need to check the
517 518 * label here. It's known to be good as we checked
518 519 * before allowing the connection to become bound.
519 520 */
520 521 return (sctp->sctp_connp);
521 522 }
522 523
523 524 /*
524 525 * Fanout for ICMP errors for SCTP
525 526 * The caller puts <fport, lport> in the ports parameter.
526 527 */
527 528 void
528 529 ip_fanout_sctp(mblk_t *mp, ipha_t *ipha, ip6_t *ip6h, uint32_t ports,
529 530 ip_recv_attr_t *ira)
530 531 {
531 532 sctp_t *sctp;
532 533 conn_t *connp;
533 534 in6_addr_t map_src, map_dst;
534 535 in6_addr_t *src, *dst;
535 536 boolean_t secure;
536 537 ill_t *ill = ira->ira_ill;
537 538 ip_stack_t *ipst = ill->ill_ipst;
538 539 netstack_t *ns = ipst->ips_netstack;
539 540 ipsec_stack_t *ipss = ns->netstack_ipsec;
540 541 sctp_stack_t *sctps = ns->netstack_sctp;
541 542 iaflags_t iraflags = ira->ira_flags;
542 543 ill_t *rill = ira->ira_rill;
543 544
544 545 ASSERT(iraflags & IRAF_ICMP_ERROR);
545 546
546 547 secure = iraflags & IRAF_IPSEC_SECURE;
547 548
548 549 /* Assume IP provides aligned packets - otherwise toss */
549 550 if (!OK_32PTR(mp->b_rptr)) {
550 551 BUMP_MIB(ill->ill_ip_mib, ipIfStatsInDiscards);
551 552 ip_drop_input("ipIfStatsInDiscards", mp, ill);
552 553 freemsg(mp);
553 554 return;
554 555 }
555 556
556 557 if (!(iraflags & IRAF_IS_IPV4)) {
557 558 src = &ip6h->ip6_src;
558 559 dst = &ip6h->ip6_dst;
559 560 } else {
560 561 IN6_IPADDR_TO_V4MAPPED(ipha->ipha_src, &map_src);
561 562 IN6_IPADDR_TO_V4MAPPED(ipha->ipha_dst, &map_dst);
562 563 src = &map_src;
563 564 dst = &map_dst;
564 565 }
565 566 connp = sctp_fanout(src, dst, ports, ira, mp, sctps, NULL);
566 567 if (connp == NULL) {
567 568 ip_fanout_sctp_raw(mp, ipha, ip6h, ports, ira);
568 569 return;
569 570 }
570 571 sctp = CONN2SCTP(connp);
571 572
572 573 /*
573 574 * We check some fields in conn_t without holding a lock.
574 575 * This should be fine.
575 576 */
576 577 if (((iraflags & IRAF_IS_IPV4) ?
577 578 CONN_INBOUND_POLICY_PRESENT(connp, ipss) :
578 579 CONN_INBOUND_POLICY_PRESENT_V6(connp, ipss)) ||
579 580 secure) {
580 581 mp = ipsec_check_inbound_policy(mp, connp, ipha,
581 582 ip6h, ira);
582 583 if (mp == NULL) {
583 584 SCTP_REFRELE(sctp);
584 585 return;
585 586 }
586 587 }
587 588
588 589 ira->ira_ill = ira->ira_rill = NULL;
589 590
590 591 mutex_enter(&sctp->sctp_lock);
591 592 if (sctp->sctp_running) {
592 593 sctp_add_recvq(sctp, mp, B_FALSE, ira);
593 594 mutex_exit(&sctp->sctp_lock);
594 595 } else {
595 596 sctp->sctp_running = B_TRUE;
596 597 mutex_exit(&sctp->sctp_lock);
597 598
598 599 mutex_enter(&sctp->sctp_recvq_lock);
599 600 if (sctp->sctp_recvq != NULL) {
600 601 sctp_add_recvq(sctp, mp, B_TRUE, ira);
601 602 mutex_exit(&sctp->sctp_recvq_lock);
602 603 WAKE_SCTP(sctp);
603 604 } else {
604 605 mutex_exit(&sctp->sctp_recvq_lock);
605 606 if (ira->ira_flags & IRAF_ICMP_ERROR) {
606 607 sctp_icmp_error(sctp, mp);
607 608 } else {
608 609 sctp_input_data(sctp, mp, ira);
609 610 }
610 611 WAKE_SCTP(sctp);
611 612 }
612 613 }
613 614 SCTP_REFRELE(sctp);
614 615 ira->ira_ill = ill;
615 616 ira->ira_rill = rill;
616 617 }
617 618
618 619 void
619 620 sctp_conn_hash_remove(sctp_t *sctp)
620 621 {
621 622 sctp_tf_t *tf = sctp->sctp_conn_tfp;
622 623
623 624 if (!tf) {
624 625 return;
625 626 }
626 627 /*
627 628 * On a clustered note send this notification to the clustering
628 629 * subsystem.
629 630 */
630 631 if (cl_sctp_disconnect != NULL) {
631 632 (*cl_sctp_disconnect)(sctp->sctp_connp->conn_family,
632 633 (cl_sctp_handle_t)sctp);
633 634 }
634 635
635 636 mutex_enter(&tf->tf_lock);
636 637 ASSERT(tf->tf_sctp);
637 638 if (tf->tf_sctp == sctp) {
638 639 tf->tf_sctp = sctp->sctp_conn_hash_next;
639 640 if (sctp->sctp_conn_hash_next) {
640 641 ASSERT(tf->tf_sctp->sctp_conn_hash_prev == sctp);
641 642 tf->tf_sctp->sctp_conn_hash_prev = NULL;
642 643 }
643 644 } else {
644 645 ASSERT(sctp->sctp_conn_hash_prev);
645 646 ASSERT(sctp->sctp_conn_hash_prev->sctp_conn_hash_next == sctp);
646 647 sctp->sctp_conn_hash_prev->sctp_conn_hash_next =
647 648 sctp->sctp_conn_hash_next;
648 649
649 650 if (sctp->sctp_conn_hash_next) {
650 651 ASSERT(sctp->sctp_conn_hash_next->sctp_conn_hash_prev
651 652 == sctp);
652 653 sctp->sctp_conn_hash_next->sctp_conn_hash_prev =
653 654 sctp->sctp_conn_hash_prev;
654 655 }
655 656 }
656 657 sctp->sctp_conn_hash_next = NULL;
657 658 sctp->sctp_conn_hash_prev = NULL;
658 659 sctp->sctp_conn_tfp = NULL;
659 660 mutex_exit(&tf->tf_lock);
660 661 }
661 662
662 663 void
663 664 sctp_conn_hash_insert(sctp_tf_t *tf, sctp_t *sctp, int caller_holds_lock)
664 665 {
665 666 if (sctp->sctp_conn_tfp) {
666 667 sctp_conn_hash_remove(sctp);
667 668 }
668 669
669 670 if (!caller_holds_lock) {
670 671 mutex_enter(&tf->tf_lock);
671 672 } else {
672 673 ASSERT(MUTEX_HELD(&tf->tf_lock));
673 674 }
674 675
675 676 sctp->sctp_conn_hash_next = tf->tf_sctp;
676 677 if (tf->tf_sctp) {
677 678 tf->tf_sctp->sctp_conn_hash_prev = sctp;
678 679 }
679 680 sctp->sctp_conn_hash_prev = NULL;
680 681 tf->tf_sctp = sctp;
681 682 sctp->sctp_conn_tfp = tf;
682 683 if (!caller_holds_lock) {
683 684 mutex_exit(&tf->tf_lock);
684 685 }
685 686 }
686 687
687 688 void
688 689 sctp_listen_hash_remove(sctp_t *sctp)
689 690 {
690 691 sctp_tf_t *tf = sctp->sctp_listen_tfp;
691 692 conn_t *connp = sctp->sctp_connp;
692 693
693 694 if (!tf) {
694 695 return;
695 696 }
696 697 /*
697 698 * On a clustered note send this notification to the clustering
698 699 * subsystem.
699 700 */
700 701 if (cl_sctp_unlisten != NULL) {
701 702 uchar_t *slist;
702 703 ssize_t ssize;
703 704
704 705 ssize = sizeof (in6_addr_t) * sctp->sctp_nsaddrs;
705 706 slist = kmem_alloc(ssize, KM_SLEEP);
706 707 sctp_get_saddr_list(sctp, slist, ssize);
707 708 (*cl_sctp_unlisten)(connp->conn_family, slist,
708 709 sctp->sctp_nsaddrs, connp->conn_lport);
709 710 /* list will be freed by the clustering module */
710 711 }
711 712
712 713 mutex_enter(&tf->tf_lock);
713 714 ASSERT(tf->tf_sctp);
714 715 if (tf->tf_sctp == sctp) {
715 716 tf->tf_sctp = sctp->sctp_listen_hash_next;
716 717 if (sctp->sctp_listen_hash_next != NULL) {
717 718 ASSERT(tf->tf_sctp->sctp_listen_hash_prev == sctp);
718 719 tf->tf_sctp->sctp_listen_hash_prev = NULL;
719 720 }
720 721 } else {
721 722 ASSERT(sctp->sctp_listen_hash_prev);
722 723 ASSERT(sctp->sctp_listen_hash_prev->sctp_listen_hash_next ==
723 724 sctp);
724 725 ASSERT(sctp->sctp_listen_hash_next == NULL ||
725 726 sctp->sctp_listen_hash_next->sctp_listen_hash_prev == sctp);
726 727
727 728 sctp->sctp_listen_hash_prev->sctp_listen_hash_next =
728 729 sctp->sctp_listen_hash_next;
729 730
730 731 if (sctp->sctp_listen_hash_next != NULL) {
731 732 sctp_t *next = sctp->sctp_listen_hash_next;
732 733
733 734 ASSERT(next->sctp_listen_hash_prev == sctp);
734 735 next->sctp_listen_hash_prev =
735 736 sctp->sctp_listen_hash_prev;
736 737 }
737 738 }
738 739 sctp->sctp_listen_hash_next = NULL;
739 740 sctp->sctp_listen_hash_prev = NULL;
740 741 sctp->sctp_listen_tfp = NULL;
741 742 mutex_exit(&tf->tf_lock);
742 743 }
743 744
744 745 void
745 746 sctp_listen_hash_insert(sctp_tf_t *tf, sctp_t *sctp)
746 747 {
747 748 conn_t *connp = sctp->sctp_connp;
748 749
749 750 if (sctp->sctp_listen_tfp) {
750 751 sctp_listen_hash_remove(sctp);
751 752 }
752 753
753 754 mutex_enter(&tf->tf_lock);
754 755 sctp->sctp_listen_hash_next = tf->tf_sctp;
755 756 if (tf->tf_sctp) {
756 757 tf->tf_sctp->sctp_listen_hash_prev = sctp;
757 758 }
758 759 sctp->sctp_listen_hash_prev = NULL;
759 760 tf->tf_sctp = sctp;
760 761 sctp->sctp_listen_tfp = tf;
761 762 mutex_exit(&tf->tf_lock);
762 763 /*
763 764 * On a clustered note send this notification to the clustering
764 765 * subsystem.
765 766 */
766 767 if (cl_sctp_listen != NULL) {
767 768 uchar_t *slist;
768 769 ssize_t ssize;
769 770
770 771 ssize = sizeof (in6_addr_t) * sctp->sctp_nsaddrs;
771 772 slist = kmem_alloc(ssize, KM_SLEEP);
772 773 sctp_get_saddr_list(sctp, slist, ssize);
773 774 (*cl_sctp_listen)(connp->conn_family, slist,
774 775 sctp->sctp_nsaddrs, connp->conn_lport);
775 776 /* list will be freed by the clustering module */
776 777 }
777 778 }
778 779
779 780 /*
780 781 * Hash list insertion routine for sctp_t structures.
781 782 * Inserts entries with the ones bound to a specific IP address first
782 783 * followed by those bound to INADDR_ANY.
783 784 */
784 785 void
785 786 sctp_bind_hash_insert(sctp_tf_t *tbf, sctp_t *sctp, int caller_holds_lock)
786 787 {
787 788 sctp_t **sctpp;
788 789 sctp_t *sctpnext;
789 790
790 791 if (sctp->sctp_ptpbhn != NULL) {
791 792 ASSERT(!caller_holds_lock);
792 793 sctp_bind_hash_remove(sctp);
793 794 }
794 795 sctpp = &tbf->tf_sctp;
795 796 if (!caller_holds_lock) {
796 797 mutex_enter(&tbf->tf_lock);
797 798 } else {
798 799 ASSERT(MUTEX_HELD(&tbf->tf_lock));
799 800 }
800 801 sctpnext = sctpp[0];
801 802 if (sctpnext) {
802 803 sctpnext->sctp_ptpbhn = &sctp->sctp_bind_hash;
803 804 }
804 805 sctp->sctp_bind_hash = sctpnext;
805 806 sctp->sctp_ptpbhn = sctpp;
806 807 sctpp[0] = sctp;
807 808 /* For sctp_*_hash_remove */
808 809 sctp->sctp_bind_lockp = &tbf->tf_lock;
809 810 if (!caller_holds_lock)
810 811 mutex_exit(&tbf->tf_lock);
811 812 }
812 813
813 814 /*
814 815 * Hash list removal routine for sctp_t structures.
815 816 */
816 817 void
817 818 sctp_bind_hash_remove(sctp_t *sctp)
818 819 {
819 820 sctp_t *sctpnext;
820 821 kmutex_t *lockp;
821 822
822 823 lockp = sctp->sctp_bind_lockp;
823 824
824 825 if (sctp->sctp_ptpbhn == NULL)
825 826 return;
826 827
827 828 ASSERT(lockp != NULL);
828 829 mutex_enter(lockp);
829 830 if (sctp->sctp_ptpbhn) {
830 831 sctpnext = sctp->sctp_bind_hash;
831 832 if (sctpnext) {
832 833 sctpnext->sctp_ptpbhn = sctp->sctp_ptpbhn;
833 834 sctp->sctp_bind_hash = NULL;
834 835 }
835 836 *sctp->sctp_ptpbhn = sctpnext;
836 837 sctp->sctp_ptpbhn = NULL;
837 838 }
838 839 mutex_exit(lockp);
839 840 sctp->sctp_bind_lockp = NULL;
840 841 }
841 842
842 843 /*
843 844 * Similar to but different from sctp_conn_match().
844 845 *
845 846 * Matches sets of addresses as follows: if the argument addr set is
846 847 * a complete subset of the corresponding addr set in the sctp_t, it
847 848 * is a match.
848 849 *
849 850 * Caller must hold tf->tf_lock.
850 851 *
851 852 * Returns with a SCTP_REFHOLD sctp structure. Caller must do a SCTP_REFRELE.
852 853 */
853 854 sctp_t *
854 855 sctp_lookup(sctp_t *sctp1, in6_addr_t *faddr, sctp_tf_t *tf, uint32_t *ports,
855 856 int min_state)
856 857 {
857 858 sctp_t *sctp;
858 859 sctp_faddr_t *fp;
859 860
860 861 ASSERT(MUTEX_HELD(&tf->tf_lock));
861 862
862 863 for (sctp = tf->tf_sctp; sctp != NULL;
863 864 sctp = sctp->sctp_conn_hash_next) {
864 865 if (*ports != sctp->sctp_connp->conn_ports ||
865 866 sctp->sctp_state < min_state) {
866 867 continue;
867 868 }
868 869
869 870 /* check for faddr match */
870 871 for (fp = sctp->sctp_faddrs; fp != NULL; fp = fp->sf_next) {
871 872 if (IN6_ARE_ADDR_EQUAL(faddr, &fp->sf_faddr)) {
872 873 break;
873 874 }
874 875 }
875 876
876 877 if (fp == NULL) {
877 878 /* no faddr match; keep looking */
878 879 continue;
879 880 }
880 881
881 882 /*
882 883 * There is an existing association with the same peer
883 884 * address. So now we need to check if our local address
884 885 * set overlaps with the one of the existing association.
885 886 * If they overlap, we should return it.
886 887 */
887 888 if (sctp_compare_saddrs(sctp1, sctp) <= SCTP_ADDR_OVERLAP) {
888 889 goto done;
889 890 }
890 891
891 892 /* no match; continue searching */
892 893 }
893 894
894 895 done:
895 896 if (sctp != NULL) {
896 897 SCTP_REFHOLD(sctp);
897 898 }
898 899 return (sctp);
899 900 }
↓ open down ↓ |
820 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX