Print this page
5045 use atomic_{inc,dec}_* instead of atomic_add_*
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/inet/sctp/sctp_addr.c
+++ new/usr/src/uts/common/inet/sctp/sctp_addr.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
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 * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
23 23 */
24 24
25 25 #include <sys/types.h>
26 26 #include <sys/systm.h>
27 27 #include <sys/stream.h>
28 28 #include <sys/cmn_err.h>
29 29 #include <sys/ddi.h>
30 30 #include <sys/sunddi.h>
31 31 #include <sys/kmem.h>
32 32 #include <sys/socket.h>
33 33 #include <sys/sysmacros.h>
34 34 #include <sys/list.h>
35 35
36 36 #include <netinet/in.h>
37 37 #include <netinet/ip6.h>
38 38 #include <netinet/sctp.h>
39 39
40 40 #include <inet/common.h>
41 41 #include <inet/ip.h>
42 42 #include <inet/ip6.h>
43 43 #include <inet/ip_ire.h>
44 44 #include <inet/ip_if.h>
45 45 #include <inet/ipclassifier.h>
46 46 #include <inet/sctp_ip.h>
47 47 #include "sctp_impl.h"
48 48 #include "sctp_addr.h"
49 49
50 50 static void sctp_ipif_inactive(sctp_ipif_t *);
51 51 static sctp_ipif_t *sctp_lookup_ipif_addr(in6_addr_t *, boolean_t,
52 52 zoneid_t, boolean_t, uint_t, uint_t, boolean_t,
53 53 sctp_stack_t *);
54 54 static int sctp_get_all_ipifs(sctp_t *, int);
55 55 static int sctp_ipif_hash_insert(sctp_t *, sctp_ipif_t *, int,
56 56 boolean_t, boolean_t);
57 57 static void sctp_ipif_hash_remove(sctp_t *, sctp_ipif_t *,
58 58 boolean_t);
59 59 static void sctp_fix_saddr(sctp_t *, in6_addr_t *);
60 60 static int sctp_compare_ipif_list(sctp_ipif_hash_t *,
61 61 sctp_ipif_hash_t *);
62 62 static int sctp_copy_ipifs(sctp_ipif_hash_t *, sctp_t *, int);
63 63
64 64 #define SCTP_ADDR4_HASH(addr) \
65 65 (((addr) ^ ((addr) >> 8) ^ ((addr) >> 16) ^ ((addr) >> 24)) & \
66 66 (SCTP_IPIF_HASH - 1))
67 67
68 68 #define SCTP_ADDR6_HASH(addr) \
69 69 (((addr).s6_addr32[3] ^ \
70 70 (((addr).s6_addr32[3] ^ (addr).s6_addr32[2]) >> 12)) & \
71 71 (SCTP_IPIF_HASH - 1))
72 72
73 73 #define SCTP_IPIF_ADDR_HASH(addr, isv6) \
74 74 ((isv6) ? SCTP_ADDR6_HASH((addr)) : \
75 75 SCTP_ADDR4_HASH((addr)._S6_un._S6_u32[3]))
76 76
77 77 #define SCTP_IPIF_USABLE(sctp_ipif_state) \
78 78 ((sctp_ipif_state) == SCTP_IPIFS_UP || \
79 79 (sctp_ipif_state) == SCTP_IPIFS_DOWN)
80 80
81 81 #define SCTP_IPIF_DISCARD(sctp_ipif_flags) \
82 82 ((sctp_ipif_flags) & (IPIF_PRIVATE | IPIF_DEPRECATED))
83 83
84 84 #define SCTP_IS_IPIF_LOOPBACK(ipif) \
85 85 ((ipif)->sctp_ipif_ill->sctp_ill_flags & PHYI_LOOPBACK)
86 86
87 87 #define SCTP_IS_IPIF_LINKLOCAL(ipif) \
88 88 ((ipif)->sctp_ipif_isv6 && \
89 89 IN6_IS_ADDR_LINKLOCAL(&(ipif)->sctp_ipif_saddr))
90 90
91 91 #define SCTP_UNSUPP_AF(ipif, supp_af) \
92 92 ((!(ipif)->sctp_ipif_isv6 && !((supp_af) & PARM_SUPP_V4)) || \
93 93 ((ipif)->sctp_ipif_isv6 && !((supp_af) & PARM_SUPP_V6)))
94 94
95 95 #define SCTP_IPIF_ZONE_MATCH(sctp, ipif) \
96 96 IPCL_ZONE_MATCH((sctp)->sctp_connp, (ipif)->sctp_ipif_zoneid)
97 97
98 98 #define SCTP_ILL_HASH_FN(index) ((index) % SCTP_ILL_HASH)
99 99 #define SCTP_ILL_TO_PHYINDEX(ill) ((ill)->ill_phyint->phyint_ifindex)
100 100
101 101 /*
102 102 * SCTP Interface list manipulation functions, locking used.
103 103 */
104 104
105 105 /*
106 106 * Delete an SCTP IPIF from the list if the refcount goes to 0 and it is
107 107 * marked as condemned. Also, check if the ILL needs to go away.
108 108 */
109 109 static void
110 110 sctp_ipif_inactive(sctp_ipif_t *sctp_ipif)
111 111 {
112 112 sctp_ill_t *sctp_ill;
113 113 uint_t hindex;
114 114 uint_t ill_index;
115 115 sctp_stack_t *sctps = sctp_ipif->sctp_ipif_ill->
116 116 sctp_ill_netstack->netstack_sctp;
117 117
118 118 rw_enter(&sctps->sctps_g_ills_lock, RW_READER);
119 119 rw_enter(&sctps->sctps_g_ipifs_lock, RW_WRITER);
120 120
121 121 hindex = SCTP_IPIF_ADDR_HASH(sctp_ipif->sctp_ipif_saddr,
122 122 sctp_ipif->sctp_ipif_isv6);
123 123
124 124 sctp_ill = sctp_ipif->sctp_ipif_ill;
125 125 ASSERT(sctp_ill != NULL);
126 126 ill_index = SCTP_ILL_HASH_FN(sctp_ill->sctp_ill_index);
127 127 if (sctp_ipif->sctp_ipif_state != SCTP_IPIFS_CONDEMNED ||
128 128 sctp_ipif->sctp_ipif_refcnt != 0) {
129 129 rw_exit(&sctps->sctps_g_ipifs_lock);
↓ open down ↓ |
129 lines elided |
↑ open up ↑ |
130 130 rw_exit(&sctps->sctps_g_ills_lock);
131 131 return;
132 132 }
133 133 list_remove(&sctps->sctps_g_ipifs[hindex].sctp_ipif_list,
134 134 sctp_ipif);
135 135 sctps->sctps_g_ipifs[hindex].ipif_count--;
136 136 sctps->sctps_g_ipifs_count--;
137 137 rw_destroy(&sctp_ipif->sctp_ipif_lock);
138 138 kmem_free(sctp_ipif, sizeof (sctp_ipif_t));
139 139
140 - (void) atomic_add_32_nv(&sctp_ill->sctp_ill_ipifcnt, -1);
140 + (void) atomic_dec_32_nv(&sctp_ill->sctp_ill_ipifcnt);
141 141 if (rw_tryupgrade(&sctps->sctps_g_ills_lock) != 0) {
142 142 rw_downgrade(&sctps->sctps_g_ipifs_lock);
143 143 if (sctp_ill->sctp_ill_ipifcnt == 0 &&
144 144 sctp_ill->sctp_ill_state == SCTP_ILLS_CONDEMNED) {
145 145 list_remove(&sctps->sctps_g_ills[ill_index].
146 146 sctp_ill_list, (void *)sctp_ill);
147 147 sctps->sctps_g_ills[ill_index].ill_count--;
148 148 sctps->sctps_ills_count--;
149 149 kmem_free(sctp_ill->sctp_ill_name,
150 150 sctp_ill->sctp_ill_name_length);
151 151 kmem_free(sctp_ill, sizeof (sctp_ill_t));
152 152 }
153 153 }
154 154 rw_exit(&sctps->sctps_g_ipifs_lock);
155 155 rw_exit(&sctps->sctps_g_ills_lock);
156 156 }
157 157
158 158 /*
159 159 * Lookup an SCTP IPIF given an IP address. Increments sctp_ipif refcnt.
160 160 * We are either looking for a IPIF with the given address before
161 161 * inserting it into the global list or looking for an IPIF for an
162 162 * address given an SCTP. In the former case we always check the zoneid,
163 163 * but for the latter case, check_zid could be B_FALSE if the connp
164 164 * for the sctp has conn_all_zones set. When looking for an address we
165 165 * give preference to one that is up, so even though we may find one that
166 166 * is not up we keep looking if there is one up, we hold the down addr
167 167 * in backup_ipif in case we don't find one that is up - i.e. we return
168 168 * the backup_ipif in that case. Note that if we are looking for. If we
169 169 * are specifically looking for an up address, then usable will be set
170 170 * to true.
171 171 */
172 172 static sctp_ipif_t *
173 173 sctp_lookup_ipif_addr(in6_addr_t *addr, boolean_t refhold, zoneid_t zoneid,
174 174 boolean_t check_zid, uint_t ifindex, uint_t seqid, boolean_t usable,
175 175 sctp_stack_t *sctps)
176 176 {
177 177 int j;
178 178 sctp_ipif_t *sctp_ipif;
179 179 sctp_ipif_t *backup_ipif = NULL;
180 180 int hindex;
181 181
182 182 hindex = SCTP_IPIF_ADDR_HASH(*addr, !IN6_IS_ADDR_V4MAPPED(addr));
183 183
184 184 rw_enter(&sctps->sctps_g_ipifs_lock, RW_READER);
185 185 if (sctps->sctps_g_ipifs[hindex].ipif_count == 0) {
186 186 rw_exit(&sctps->sctps_g_ipifs_lock);
187 187 return (NULL);
188 188 }
189 189 sctp_ipif = list_head(&sctps->sctps_g_ipifs[hindex].sctp_ipif_list);
190 190 for (j = 0; j < sctps->sctps_g_ipifs[hindex].ipif_count; j++) {
191 191 rw_enter(&sctp_ipif->sctp_ipif_lock, RW_READER);
192 192 if ((!check_zid ||
193 193 (sctp_ipif->sctp_ipif_zoneid == ALL_ZONES ||
194 194 zoneid == sctp_ipif->sctp_ipif_zoneid)) &&
195 195 (ifindex == 0 || ifindex ==
196 196 sctp_ipif->sctp_ipif_ill->sctp_ill_index) &&
197 197 ((seqid != 0 && seqid == sctp_ipif->sctp_ipif_id) ||
198 198 (IN6_ARE_ADDR_EQUAL(&sctp_ipif->sctp_ipif_saddr,
199 199 addr)))) {
200 200 if (!usable || sctp_ipif->sctp_ipif_state ==
201 201 SCTP_IPIFS_UP) {
202 202 rw_exit(&sctp_ipif->sctp_ipif_lock);
203 203 if (refhold)
204 204 SCTP_IPIF_REFHOLD(sctp_ipif);
205 205 rw_exit(&sctps->sctps_g_ipifs_lock);
206 206 return (sctp_ipif);
207 207 } else if (sctp_ipif->sctp_ipif_state ==
208 208 SCTP_IPIFS_DOWN && backup_ipif == NULL) {
209 209 backup_ipif = sctp_ipif;
210 210 }
211 211 }
212 212 rw_exit(&sctp_ipif->sctp_ipif_lock);
213 213 sctp_ipif = list_next(
214 214 &sctps->sctps_g_ipifs[hindex].sctp_ipif_list, sctp_ipif);
215 215 }
216 216 if (backup_ipif != NULL) {
217 217 if (refhold)
218 218 SCTP_IPIF_REFHOLD(backup_ipif);
219 219 rw_exit(&sctps->sctps_g_ipifs_lock);
220 220 return (backup_ipif);
221 221 }
222 222 rw_exit(&sctps->sctps_g_ipifs_lock);
223 223 return (NULL);
224 224 }
225 225
226 226 /*
227 227 * Populate the list with all the SCTP ipifs for a given ipversion.
228 228 * Increments sctp_ipif refcnt.
229 229 * Called with no locks held.
230 230 */
231 231 static int
232 232 sctp_get_all_ipifs(sctp_t *sctp, int sleep)
233 233 {
234 234 sctp_ipif_t *sctp_ipif;
235 235 int i;
236 236 int j;
237 237 int error = 0;
238 238 sctp_stack_t *sctps = sctp->sctp_sctps;
239 239 boolean_t isv6;
240 240 conn_t *connp = sctp->sctp_connp;
241 241
242 242 rw_enter(&sctps->sctps_g_ipifs_lock, RW_READER);
243 243 for (i = 0; i < SCTP_IPIF_HASH; i++) {
244 244 if (sctps->sctps_g_ipifs[i].ipif_count == 0)
245 245 continue;
246 246 sctp_ipif = list_head(&sctps->sctps_g_ipifs[i].sctp_ipif_list);
247 247 for (j = 0; j < sctps->sctps_g_ipifs[i].ipif_count; j++) {
248 248 rw_enter(&sctp_ipif->sctp_ipif_lock, RW_READER);
249 249 isv6 = sctp_ipif->sctp_ipif_isv6;
250 250 if (SCTP_IPIF_DISCARD(sctp_ipif->sctp_ipif_flags) ||
251 251 !SCTP_IPIF_USABLE(sctp_ipif->sctp_ipif_state) ||
252 252 !SCTP_IPIF_ZONE_MATCH(sctp, sctp_ipif) ||
253 253 SCTP_IS_ADDR_UNSPEC(!isv6,
254 254 sctp_ipif->sctp_ipif_saddr) ||
255 255 (connp->conn_family == AF_INET && isv6) ||
256 256 (connp->conn_ipv6_v6only && !isv6)) {
257 257 rw_exit(&sctp_ipif->sctp_ipif_lock);
258 258 sctp_ipif = list_next(
259 259 &sctps->sctps_g_ipifs[i].sctp_ipif_list,
260 260 sctp_ipif);
261 261 continue;
262 262 }
263 263 rw_exit(&sctp_ipif->sctp_ipif_lock);
264 264 SCTP_IPIF_REFHOLD(sctp_ipif);
265 265 error = sctp_ipif_hash_insert(sctp, sctp_ipif, sleep,
266 266 B_FALSE, B_FALSE);
267 267 if (error != 0 && error != EALREADY)
268 268 goto free_stuff;
269 269 sctp_ipif = list_next(
270 270 &sctps->sctps_g_ipifs[i].sctp_ipif_list,
271 271 sctp_ipif);
272 272 }
273 273 }
274 274 rw_exit(&sctps->sctps_g_ipifs_lock);
275 275 return (0);
276 276 free_stuff:
277 277 rw_exit(&sctps->sctps_g_ipifs_lock);
278 278 sctp_free_saddrs(sctp);
279 279 return (ENOMEM);
280 280 }
281 281
282 282 /*
283 283 * Given a list of address, fills in the list of SCTP ipifs if all the addresses
284 284 * are present in the SCTP interface list, return number of addresses filled
285 285 * or error. If the caller wants the list of addresses, it sends a pre-allocated
286 286 * buffer - list. Currently, this list is only used on a clustered node when
287 287 * the SCTP is in the listen state (from sctp_bind_add()). When called on a
288 288 * clustered node, the input is always a list of addresses (even if the
289 289 * original bind() was to INADDR_ANY).
290 290 * Called with no locks held.
291 291 */
292 292 int
293 293 sctp_valid_addr_list(sctp_t *sctp, const void *addrs, uint32_t addrcnt,
294 294 uchar_t *list, size_t lsize)
295 295 {
296 296 struct sockaddr_in *sin4;
297 297 struct sockaddr_in6 *sin6;
298 298 struct in_addr *addr4;
299 299 in6_addr_t addr;
300 300 int cnt;
301 301 int err = 0;
302 302 int saddr_cnt = 0;
303 303 sctp_ipif_t *ipif;
304 304 boolean_t bind_to_all = B_FALSE;
305 305 boolean_t check_addrs = B_FALSE;
306 306 boolean_t check_lport = B_FALSE;
307 307 uchar_t *p = list;
308 308 conn_t *connp = sctp->sctp_connp;
309 309
310 310 /*
311 311 * Need to check for port and address depending on the state.
312 312 * After a socket is bound, we need to make sure that subsequent
313 313 * bindx() has correct port. After an association is established,
314 314 * we need to check for changing the bound address to invalid
315 315 * addresses.
316 316 */
317 317 if (sctp->sctp_state >= SCTPS_BOUND) {
318 318 check_lport = B_TRUE;
319 319 if (sctp->sctp_state > SCTPS_LISTEN)
320 320 check_addrs = B_TRUE;
321 321 }
322 322
323 323 if (sctp->sctp_conn_tfp != NULL)
324 324 mutex_enter(&sctp->sctp_conn_tfp->tf_lock);
325 325 if (sctp->sctp_listen_tfp != NULL)
326 326 mutex_enter(&sctp->sctp_listen_tfp->tf_lock);
327 327 for (cnt = 0; cnt < addrcnt; cnt++) {
328 328 boolean_t lookup_saddr = B_TRUE;
329 329 uint_t ifindex = 0;
330 330
331 331 switch (connp->conn_family) {
332 332 case AF_INET:
333 333 sin4 = (struct sockaddr_in *)addrs + cnt;
334 334 if (sin4->sin_family != AF_INET || (check_lport &&
335 335 sin4->sin_port != connp->conn_lport)) {
336 336 err = EINVAL;
337 337 goto free_ret;
338 338 }
339 339 addr4 = &sin4->sin_addr;
340 340 if (check_addrs &&
341 341 (addr4->s_addr == INADDR_ANY ||
342 342 addr4->s_addr == INADDR_BROADCAST ||
343 343 CLASSD(addr4->s_addr))) {
344 344 err = EINVAL;
345 345 goto free_ret;
346 346 }
347 347 IN6_INADDR_TO_V4MAPPED(addr4, &addr);
348 348 if (!check_addrs && addr4->s_addr == INADDR_ANY) {
349 349 lookup_saddr = B_FALSE;
350 350 bind_to_all = B_TRUE;
351 351 }
352 352
353 353 break;
354 354 case AF_INET6:
355 355 sin6 = (struct sockaddr_in6 *)addrs + cnt;
356 356 if (sin6->sin6_family != AF_INET6 || (check_lport &&
357 357 sin6->sin6_port != connp->conn_lport)) {
358 358 err = EINVAL;
359 359 goto free_ret;
360 360 }
361 361 addr = sin6->sin6_addr;
362 362 /* Contains the interface index */
363 363 ifindex = sin6->sin6_scope_id;
364 364 if (connp->conn_ipv6_v6only &&
365 365 IN6_IS_ADDR_V4MAPPED(&addr)) {
366 366 err = EAFNOSUPPORT;
367 367 goto free_ret;
368 368 }
369 369 if (check_addrs &&
370 370 (IN6_IS_ADDR_LINKLOCAL(&addr) ||
371 371 IN6_IS_ADDR_MULTICAST(&addr) ||
372 372 IN6_IS_ADDR_UNSPECIFIED(&addr))) {
373 373 err = EINVAL;
374 374 goto free_ret;
375 375 }
376 376 if (!check_addrs && IN6_IS_ADDR_UNSPECIFIED(&addr)) {
377 377 lookup_saddr = B_FALSE;
378 378 bind_to_all = B_TRUE;
379 379 }
380 380
381 381 break;
382 382 default:
383 383 err = EAFNOSUPPORT;
384 384 goto free_ret;
385 385 }
386 386 if (lookup_saddr) {
387 387 ipif = sctp_lookup_ipif_addr(&addr, B_TRUE,
388 388 IPCL_ZONEID(connp), !connp->conn_allzones,
389 389 ifindex, 0, B_TRUE, sctp->sctp_sctps);
390 390 if (ipif == NULL) {
391 391 /* Address not in the list */
392 392 err = EINVAL;
393 393 goto free_ret;
394 394 } else if (check_addrs && SCTP_IS_IPIF_LOOPBACK(ipif) &&
395 395 cl_sctp_check_addrs == NULL) {
396 396 SCTP_IPIF_REFRELE(ipif);
397 397 err = EINVAL;
398 398 goto free_ret;
399 399 }
400 400 }
401 401 if (!bind_to_all) {
402 402 /*
403 403 * If an address is added after association setup,
404 404 * we need to wait for the peer to send us an ASCONF
405 405 * ACK before we can start using it.
406 406 * saddr_ipif_dontsrc will be reset (to 0) when we
407 407 * get the ASCONF ACK for this address.
408 408 */
409 409 err = sctp_ipif_hash_insert(sctp, ipif, KM_SLEEP,
410 410 check_addrs ? B_TRUE : B_FALSE, B_FALSE);
411 411 if (err != 0) {
412 412 SCTP_IPIF_REFRELE(ipif);
413 413 if (check_addrs && err == EALREADY)
414 414 err = EADDRINUSE;
415 415 goto free_ret;
416 416 }
417 417 saddr_cnt++;
418 418 if (lsize >= sizeof (addr)) {
419 419 bcopy(&addr, p, sizeof (addr));
420 420 p += sizeof (addr);
421 421 lsize -= sizeof (addr);
422 422 }
423 423 }
424 424 }
425 425 if (bind_to_all) {
426 426 /*
427 427 * Free whatever we might have added before encountering
428 428 * inaddr_any.
429 429 */
430 430 if (sctp->sctp_nsaddrs > 0) {
431 431 sctp_free_saddrs(sctp);
432 432 ASSERT(sctp->sctp_nsaddrs == 0);
433 433 }
434 434 err = sctp_get_all_ipifs(sctp, KM_SLEEP);
435 435 if (err != 0)
436 436 return (err);
437 437 sctp->sctp_bound_to_all = 1;
438 438 }
439 439 if (sctp->sctp_listen_tfp != NULL)
440 440 mutex_exit(&sctp->sctp_listen_tfp->tf_lock);
441 441 if (sctp->sctp_conn_tfp != NULL)
442 442 mutex_exit(&sctp->sctp_conn_tfp->tf_lock);
443 443 return (0);
444 444 free_ret:
445 445 if (saddr_cnt != 0)
446 446 sctp_del_saddr_list(sctp, addrs, saddr_cnt, B_TRUE);
447 447 if (sctp->sctp_listen_tfp != NULL)
448 448 mutex_exit(&sctp->sctp_listen_tfp->tf_lock);
449 449 if (sctp->sctp_conn_tfp != NULL)
450 450 mutex_exit(&sctp->sctp_conn_tfp->tf_lock);
451 451 return (err);
452 452 }
453 453
454 454 static int
455 455 sctp_ipif_hash_insert(sctp_t *sctp, sctp_ipif_t *ipif, int sleep,
456 456 boolean_t dontsrc, boolean_t allow_dup)
457 457 {
458 458 int cnt;
459 459 sctp_saddr_ipif_t *ipif_obj;
460 460 int hindex;
461 461
462 462 hindex = SCTP_IPIF_ADDR_HASH(ipif->sctp_ipif_saddr,
463 463 ipif->sctp_ipif_isv6);
464 464 rw_enter(&sctp->sctp_saddrs[hindex].ipif_hash_lock, RW_WRITER);
465 465 ipif_obj = list_head(&sctp->sctp_saddrs[hindex].sctp_ipif_list);
466 466 for (cnt = 0; cnt < sctp->sctp_saddrs[hindex].ipif_count; cnt++) {
467 467 if (IN6_ARE_ADDR_EQUAL(&ipif_obj->saddr_ipifp->sctp_ipif_saddr,
468 468 &ipif->sctp_ipif_saddr)) {
469 469 if (ipif->sctp_ipif_id !=
470 470 ipif_obj->saddr_ipifp->sctp_ipif_id &&
471 471 ipif_obj->saddr_ipifp->sctp_ipif_state ==
472 472 SCTP_IPIFS_DOWN && ipif->sctp_ipif_state ==
473 473 SCTP_IPIFS_UP) {
474 474 SCTP_IPIF_REFRELE(ipif_obj->saddr_ipifp);
475 475 ipif_obj->saddr_ipifp = ipif;
476 476 ipif_obj->saddr_ipif_dontsrc = dontsrc ? 1 : 0;
477 477 rw_exit(
478 478 &sctp->sctp_saddrs[hindex].ipif_hash_lock);
479 479 return (0);
480 480 } else if (!allow_dup || ipif->sctp_ipif_id ==
481 481 ipif_obj->saddr_ipifp->sctp_ipif_id) {
482 482 rw_exit(
483 483 &sctp->sctp_saddrs[hindex].ipif_hash_lock);
484 484 return (EALREADY);
485 485 }
486 486 }
487 487 ipif_obj = list_next(&sctp->sctp_saddrs[hindex].sctp_ipif_list,
488 488 ipif_obj);
489 489 }
490 490 ipif_obj = kmem_zalloc(sizeof (sctp_saddr_ipif_t), sleep);
491 491 if (ipif_obj == NULL) {
492 492 rw_exit(&sctp->sctp_saddrs[hindex].ipif_hash_lock);
493 493 /* Need to do something */
494 494 return (ENOMEM);
495 495 }
496 496 ipif_obj->saddr_ipifp = ipif;
497 497 ipif_obj->saddr_ipif_dontsrc = dontsrc ? 1 : 0;
498 498 list_insert_tail(&sctp->sctp_saddrs[hindex].sctp_ipif_list, ipif_obj);
499 499 sctp->sctp_saddrs[hindex].ipif_count++;
500 500 sctp->sctp_nsaddrs++;
501 501 rw_exit(&sctp->sctp_saddrs[hindex].ipif_hash_lock);
502 502 return (0);
503 503 }
504 504
505 505 /*
506 506 * Given a source address, walk through the peer address list to see
507 507 * if the source address is being used. If it is, reset that.
508 508 * A cleared saddr will then make sctp_make_mp lookup the destination again
509 509 * and as part of that look for a new source.
510 510 */
511 511 static void
512 512 sctp_fix_saddr(sctp_t *sctp, in6_addr_t *saddr)
513 513 {
514 514 sctp_faddr_t *fp;
515 515
516 516 for (fp = sctp->sctp_faddrs; fp != NULL; fp = fp->sf_next) {
517 517 if (!IN6_ARE_ADDR_EQUAL(&fp->sf_saddr, saddr))
518 518 continue;
519 519 V6_SET_ZERO(fp->sf_saddr);
520 520 }
521 521 }
522 522
523 523 static void
524 524 sctp_ipif_hash_remove(sctp_t *sctp, sctp_ipif_t *ipif, boolean_t locked)
525 525 {
526 526 int cnt;
527 527 sctp_saddr_ipif_t *ipif_obj;
528 528 int hindex;
529 529
530 530 hindex = SCTP_IPIF_ADDR_HASH(ipif->sctp_ipif_saddr,
531 531 ipif->sctp_ipif_isv6);
532 532 if (!locked)
533 533 rw_enter(&sctp->sctp_saddrs[hindex].ipif_hash_lock, RW_WRITER);
534 534 ipif_obj = list_head(&sctp->sctp_saddrs[hindex].sctp_ipif_list);
535 535 for (cnt = 0; cnt < sctp->sctp_saddrs[hindex].ipif_count; cnt++) {
536 536 if (IN6_ARE_ADDR_EQUAL(&ipif_obj->saddr_ipifp->sctp_ipif_saddr,
537 537 &ipif->sctp_ipif_saddr)) {
538 538 list_remove(&sctp->sctp_saddrs[hindex].sctp_ipif_list,
539 539 ipif_obj);
540 540 sctp->sctp_saddrs[hindex].ipif_count--;
541 541 sctp->sctp_nsaddrs--;
542 542 sctp_fix_saddr(sctp, &ipif->sctp_ipif_saddr);
543 543 SCTP_IPIF_REFRELE(ipif_obj->saddr_ipifp);
544 544 kmem_free(ipif_obj, sizeof (sctp_saddr_ipif_t));
545 545 break;
546 546 }
547 547 ipif_obj = list_next(&sctp->sctp_saddrs[hindex].sctp_ipif_list,
548 548 ipif_obj);
549 549 }
550 550 if (!locked)
551 551 rw_exit(&sctp->sctp_saddrs[hindex].ipif_hash_lock);
552 552 }
553 553
554 554 static int
555 555 sctp_compare_ipif_list(sctp_ipif_hash_t *list1, sctp_ipif_hash_t *list2)
556 556 {
557 557 int i;
558 558 int j;
559 559 sctp_saddr_ipif_t *obj1;
560 560 sctp_saddr_ipif_t *obj2;
561 561 int overlap = 0;
562 562
563 563 rw_enter(&list1->ipif_hash_lock, RW_READER);
564 564 rw_enter(&list2->ipif_hash_lock, RW_READER);
565 565 obj1 = list_head(&list1->sctp_ipif_list);
566 566 for (i = 0; i < list1->ipif_count; i++) {
567 567 obj2 = list_head(&list2->sctp_ipif_list);
568 568 for (j = 0; j < list2->ipif_count; j++) {
569 569 if (IN6_ARE_ADDR_EQUAL(
570 570 &obj1->saddr_ipifp->sctp_ipif_saddr,
571 571 &obj2->saddr_ipifp->sctp_ipif_saddr)) {
572 572 overlap++;
573 573 break;
574 574 }
575 575 obj2 = list_next(&list2->sctp_ipif_list,
576 576 obj2);
577 577 }
578 578 obj1 = list_next(&list1->sctp_ipif_list, obj1);
579 579 }
580 580 rw_exit(&list1->ipif_hash_lock);
581 581 rw_exit(&list2->ipif_hash_lock);
582 582 return (overlap);
583 583 }
584 584
585 585 int
586 586 sctp_compare_saddrs(sctp_t *sctp1, sctp_t *sctp2)
587 587 {
588 588 int i;
589 589 int overlap = 0;
590 590
591 591 for (i = 0; i < SCTP_IPIF_HASH; i++) {
592 592 overlap += sctp_compare_ipif_list(&sctp1->sctp_saddrs[i],
593 593 &sctp2->sctp_saddrs[i]);
594 594 }
595 595
596 596 if (sctp1->sctp_nsaddrs == sctp2->sctp_nsaddrs &&
597 597 overlap == sctp1->sctp_nsaddrs) {
598 598 return (SCTP_ADDR_EQUAL);
599 599 }
600 600
601 601 if (overlap == sctp1->sctp_nsaddrs)
602 602 return (SCTP_ADDR_SUBSET);
603 603
604 604 if (overlap > 0)
605 605 return (SCTP_ADDR_OVERLAP);
606 606
607 607 return (SCTP_ADDR_DISJOINT);
608 608 }
609 609
610 610 static int
611 611 sctp_copy_ipifs(sctp_ipif_hash_t *list1, sctp_t *sctp2, int sleep)
612 612 {
613 613 int i;
614 614 sctp_saddr_ipif_t *obj;
615 615 int error = 0;
616 616
617 617 rw_enter(&list1->ipif_hash_lock, RW_READER);
618 618 obj = list_head(&list1->sctp_ipif_list);
619 619 for (i = 0; i < list1->ipif_count; i++) {
620 620 SCTP_IPIF_REFHOLD(obj->saddr_ipifp);
621 621 error = sctp_ipif_hash_insert(sctp2, obj->saddr_ipifp, sleep,
622 622 B_FALSE, B_FALSE);
623 623 ASSERT(error != EALREADY);
624 624 if (error != 0) {
625 625 rw_exit(&list1->ipif_hash_lock);
626 626 return (error);
627 627 }
628 628 obj = list_next(&list1->sctp_ipif_list, obj);
629 629 }
630 630 rw_exit(&list1->ipif_hash_lock);
631 631 return (error);
632 632 }
633 633
634 634 int
635 635 sctp_dup_saddrs(sctp_t *sctp1, sctp_t *sctp2, int sleep)
636 636 {
637 637 int error = 0;
638 638 int i;
639 639
640 640 if (sctp1 == NULL || sctp1->sctp_bound_to_all == 1)
641 641 return (sctp_get_all_ipifs(sctp2, sleep));
642 642
643 643 for (i = 0; i < SCTP_IPIF_HASH; i++) {
644 644 rw_enter(&sctp1->sctp_saddrs[i].ipif_hash_lock, RW_READER);
645 645 if (sctp1->sctp_saddrs[i].ipif_count == 0) {
646 646 rw_exit(&sctp1->sctp_saddrs[i].ipif_hash_lock);
647 647 continue;
648 648 }
649 649 error = sctp_copy_ipifs(&sctp1->sctp_saddrs[i], sctp2, sleep);
650 650 if (error != 0) {
651 651 rw_exit(&sctp1->sctp_saddrs[i].ipif_hash_lock);
652 652 sctp_free_saddrs(sctp2);
653 653 return (error);
654 654 }
655 655 rw_exit(&sctp1->sctp_saddrs[i].ipif_hash_lock);
656 656 }
657 657 return (0);
658 658 }
659 659
660 660 void
661 661 sctp_free_saddrs(sctp_t *sctp)
662 662 {
663 663 int i;
664 664 int l;
665 665 sctp_saddr_ipif_t *obj;
666 666
667 667 if (sctp->sctp_nsaddrs == 0)
668 668 return;
669 669 for (i = 0; i < SCTP_IPIF_HASH; i++) {
670 670 rw_enter(&sctp->sctp_saddrs[i].ipif_hash_lock, RW_WRITER);
671 671 if (sctp->sctp_saddrs[i].ipif_count == 0) {
672 672 rw_exit(&sctp->sctp_saddrs[i].ipif_hash_lock);
673 673 continue;
674 674 }
675 675 obj = list_tail(&sctp->sctp_saddrs[i].sctp_ipif_list);
676 676 for (l = 0; l < sctp->sctp_saddrs[i].ipif_count; l++) {
677 677 list_remove(&sctp->sctp_saddrs[i].sctp_ipif_list, obj);
678 678 SCTP_IPIF_REFRELE(obj->saddr_ipifp);
679 679 sctp->sctp_nsaddrs--;
680 680 kmem_free(obj, sizeof (sctp_saddr_ipif_t));
681 681 obj = list_tail(&sctp->sctp_saddrs[i].sctp_ipif_list);
682 682 }
683 683 sctp->sctp_saddrs[i].ipif_count = 0;
684 684 rw_exit(&sctp->sctp_saddrs[i].ipif_hash_lock);
685 685 }
686 686 if (sctp->sctp_bound_to_all == 1)
687 687 sctp->sctp_bound_to_all = 0;
688 688 ASSERT(sctp->sctp_nsaddrs == 0);
689 689 }
690 690
691 691 /*
692 692 * Add/Delete the given ILL from the SCTP ILL list. Called with no locks
693 693 * held.
694 694 */
695 695 void
696 696 sctp_update_ill(ill_t *ill, int op)
697 697 {
698 698 int i;
699 699 sctp_ill_t *sctp_ill = NULL;
700 700 uint_t index;
701 701 netstack_t *ns = ill->ill_ipst->ips_netstack;
702 702 sctp_stack_t *sctps = ns->netstack_sctp;
703 703
704 704 rw_enter(&sctps->sctps_g_ills_lock, RW_WRITER);
705 705
706 706 index = SCTP_ILL_HASH_FN(SCTP_ILL_TO_PHYINDEX(ill));
707 707 sctp_ill = list_head(&sctps->sctps_g_ills[index].sctp_ill_list);
708 708 for (i = 0; i < sctps->sctps_g_ills[index].ill_count; i++) {
709 709 if ((sctp_ill->sctp_ill_index == SCTP_ILL_TO_PHYINDEX(ill)) &&
710 710 (sctp_ill->sctp_ill_isv6 == ill->ill_isv6)) {
711 711 break;
712 712 }
713 713 sctp_ill = list_next(&sctps->sctps_g_ills[index].sctp_ill_list,
714 714 sctp_ill);
715 715 }
716 716
717 717 switch (op) {
718 718 case SCTP_ILL_INSERT:
719 719 if (sctp_ill != NULL) {
720 720 /* Unmark it if it is condemned */
721 721 if (sctp_ill->sctp_ill_state == SCTP_ILLS_CONDEMNED)
722 722 sctp_ill->sctp_ill_state = 0;
723 723 rw_exit(&sctps->sctps_g_ills_lock);
724 724 return;
725 725 }
726 726 sctp_ill = kmem_zalloc(sizeof (sctp_ill_t), KM_NOSLEEP);
727 727 /* Need to re-try? */
728 728 if (sctp_ill == NULL) {
729 729 cmn_err(CE_WARN, "sctp_update_ill: error adding "
730 730 "ILL %p to SCTP's ILL list", (void *)ill);
731 731 rw_exit(&sctps->sctps_g_ills_lock);
732 732 return;
733 733 }
734 734 sctp_ill->sctp_ill_name = kmem_zalloc(ill->ill_name_length,
735 735 KM_NOSLEEP);
736 736 if (sctp_ill->sctp_ill_name == NULL) {
737 737 cmn_err(CE_WARN, "sctp_update_ill: error adding "
738 738 "ILL %p to SCTP's ILL list", (void *)ill);
739 739 kmem_free(sctp_ill, sizeof (sctp_ill_t));
740 740 rw_exit(&sctps->sctps_g_ills_lock);
741 741 return;
742 742 }
743 743 bcopy(ill->ill_name, sctp_ill->sctp_ill_name,
744 744 ill->ill_name_length);
745 745 sctp_ill->sctp_ill_name_length = ill->ill_name_length;
746 746 sctp_ill->sctp_ill_index = SCTP_ILL_TO_PHYINDEX(ill);
747 747 sctp_ill->sctp_ill_flags = ill->ill_phyint->phyint_flags;
748 748 sctp_ill->sctp_ill_netstack = ns; /* No netstack_hold */
749 749 sctp_ill->sctp_ill_isv6 = ill->ill_isv6;
750 750 list_insert_tail(&sctps->sctps_g_ills[index].sctp_ill_list,
751 751 (void *)sctp_ill);
752 752 sctps->sctps_g_ills[index].ill_count++;
753 753 sctps->sctps_ills_count++;
754 754
755 755 break;
756 756
757 757 case SCTP_ILL_REMOVE:
758 758
759 759 if (sctp_ill == NULL) {
760 760 rw_exit(&sctps->sctps_g_ills_lock);
761 761 return;
762 762 }
763 763 if (sctp_ill->sctp_ill_ipifcnt == 0) {
764 764 list_remove(&sctps->sctps_g_ills[index].sctp_ill_list,
765 765 (void *)sctp_ill);
766 766 sctps->sctps_g_ills[index].ill_count--;
767 767 sctps->sctps_ills_count--;
768 768 kmem_free(sctp_ill->sctp_ill_name,
769 769 ill->ill_name_length);
770 770 kmem_free(sctp_ill, sizeof (sctp_ill_t));
771 771 } else {
772 772 sctp_ill->sctp_ill_state = SCTP_ILLS_CONDEMNED;
773 773 }
774 774
775 775 break;
776 776 }
777 777 rw_exit(&sctps->sctps_g_ills_lock);
778 778 }
779 779
780 780 /*
781 781 * The ILL's index is being changed, just remove it from the old list,
782 782 * change the SCTP ILL's index and re-insert using the new index.
783 783 */
784 784 void
785 785 sctp_ill_reindex(ill_t *ill, uint_t orig_ill_index)
786 786 {
787 787 sctp_ill_t *sctp_ill = NULL;
788 788 sctp_ill_t *nxt_sill;
789 789 uint_t indx;
790 790 uint_t nindx;
791 791 boolean_t once = B_FALSE;
792 792 netstack_t *ns = ill->ill_ipst->ips_netstack;
793 793 sctp_stack_t *sctps = ns->netstack_sctp;
794 794
795 795 rw_enter(&sctps->sctps_g_ills_lock, RW_WRITER);
796 796
797 797 indx = SCTP_ILL_HASH_FN(orig_ill_index);
798 798 nindx = SCTP_ILL_HASH_FN(SCTP_ILL_TO_PHYINDEX(ill));
799 799 sctp_ill = list_head(&sctps->sctps_g_ills[indx].sctp_ill_list);
800 800 while (sctp_ill != NULL) {
801 801 nxt_sill = list_next(&sctps->sctps_g_ills[indx].sctp_ill_list,
802 802 sctp_ill);
803 803 if (sctp_ill->sctp_ill_index == orig_ill_index) {
804 804 sctp_ill->sctp_ill_index = SCTP_ILL_TO_PHYINDEX(ill);
805 805 /*
806 806 * if the new index hashes to the same value, all's
807 807 * done.
808 808 */
809 809 if (nindx != indx) {
810 810 list_remove(
811 811 &sctps->sctps_g_ills[indx].sctp_ill_list,
812 812 (void *)sctp_ill);
813 813 sctps->sctps_g_ills[indx].ill_count--;
814 814 list_insert_tail(
815 815 &sctps->sctps_g_ills[nindx].sctp_ill_list,
816 816 (void *)sctp_ill);
817 817 sctps->sctps_g_ills[nindx].ill_count++;
818 818 }
819 819 if (once)
820 820 break;
821 821 /* We might have one for v4 and for v6 */
822 822 once = B_TRUE;
823 823 }
824 824 sctp_ill = nxt_sill;
825 825 }
826 826 rw_exit(&sctps->sctps_g_ills_lock);
827 827 }
828 828
829 829 /* move ipif from f_ill to t_ill */
830 830 void
831 831 sctp_move_ipif(ipif_t *ipif, ill_t *f_ill, ill_t *t_ill)
832 832 {
833 833 sctp_ill_t *fsctp_ill = NULL;
834 834 sctp_ill_t *tsctp_ill = NULL;
835 835 sctp_ipif_t *sctp_ipif;
836 836 uint_t hindex;
837 837 int i;
838 838 netstack_t *ns = ipif->ipif_ill->ill_ipst->ips_netstack;
839 839 sctp_stack_t *sctps = ns->netstack_sctp;
840 840
841 841 rw_enter(&sctps->sctps_g_ills_lock, RW_READER);
842 842 rw_enter(&sctps->sctps_g_ipifs_lock, RW_READER);
843 843
844 844 hindex = SCTP_ILL_HASH_FN(SCTP_ILL_TO_PHYINDEX(f_ill));
845 845 fsctp_ill = list_head(&sctps->sctps_g_ills[hindex].sctp_ill_list);
846 846 for (i = 0; i < sctps->sctps_g_ills[hindex].ill_count; i++) {
847 847 if (fsctp_ill->sctp_ill_index == SCTP_ILL_TO_PHYINDEX(f_ill) &&
848 848 fsctp_ill->sctp_ill_isv6 == f_ill->ill_isv6) {
849 849 break;
850 850 }
851 851 fsctp_ill = list_next(
852 852 &sctps->sctps_g_ills[hindex].sctp_ill_list, fsctp_ill);
853 853 }
854 854
855 855 hindex = SCTP_ILL_HASH_FN(SCTP_ILL_TO_PHYINDEX(t_ill));
856 856 tsctp_ill = list_head(&sctps->sctps_g_ills[hindex].sctp_ill_list);
857 857 for (i = 0; i < sctps->sctps_g_ills[hindex].ill_count; i++) {
858 858 if (tsctp_ill->sctp_ill_index == SCTP_ILL_TO_PHYINDEX(t_ill) &&
859 859 tsctp_ill->sctp_ill_isv6 == t_ill->ill_isv6) {
860 860 break;
861 861 }
862 862 tsctp_ill = list_next(
863 863 &sctps->sctps_g_ills[hindex].sctp_ill_list, tsctp_ill);
864 864 }
865 865
866 866 hindex = SCTP_IPIF_ADDR_HASH(ipif->ipif_v6lcl_addr,
867 867 ipif->ipif_ill->ill_isv6);
868 868 sctp_ipif = list_head(&sctps->sctps_g_ipifs[hindex].sctp_ipif_list);
869 869 for (i = 0; i < sctps->sctps_g_ipifs[hindex].ipif_count; i++) {
870 870 if (sctp_ipif->sctp_ipif_id == ipif->ipif_seqid)
871 871 break;
872 872 sctp_ipif = list_next(
873 873 &sctps->sctps_g_ipifs[hindex].sctp_ipif_list, sctp_ipif);
874 874 }
875 875 /* Should be an ASSERT? */
876 876 if (fsctp_ill == NULL || tsctp_ill == NULL || sctp_ipif == NULL) {
↓ open down ↓ |
726 lines elided |
↑ open up ↑ |
877 877 ip1dbg(("sctp_move_ipif: error moving ipif %p from %p to %p\n",
878 878 (void *)ipif, (void *)f_ill, (void *)t_ill));
879 879 rw_exit(&sctps->sctps_g_ipifs_lock);
880 880 rw_exit(&sctps->sctps_g_ills_lock);
881 881 return;
882 882 }
883 883 rw_enter(&sctp_ipif->sctp_ipif_lock, RW_WRITER);
884 884 ASSERT(sctp_ipif->sctp_ipif_ill == fsctp_ill);
885 885 sctp_ipif->sctp_ipif_ill = tsctp_ill;
886 886 rw_exit(&sctp_ipif->sctp_ipif_lock);
887 - (void) atomic_add_32_nv(&fsctp_ill->sctp_ill_ipifcnt, -1);
888 - atomic_add_32(&tsctp_ill->sctp_ill_ipifcnt, 1);
887 + (void) atomic_dec_32_nv(&fsctp_ill->sctp_ill_ipifcnt);
888 + atomic_inc_32(&tsctp_ill->sctp_ill_ipifcnt);
889 889 rw_exit(&sctps->sctps_g_ipifs_lock);
890 890 rw_exit(&sctps->sctps_g_ills_lock);
891 891 }
892 892
893 893 /*
894 894 * Walk the list of SCTPs and find each that has oipif in it's saddr list, and
895 895 * if so replace it with nipif.
896 896 */
897 897 void
898 898 sctp_update_saddrs(sctp_ipif_t *oipif, sctp_ipif_t *nipif, int idx,
899 899 sctp_stack_t *sctps)
900 900 {
901 901 sctp_t *sctp;
902 902 sctp_t *sctp_prev = NULL;
903 903 sctp_saddr_ipif_t *sobj;
904 904 int count;
905 905
906 906 mutex_enter(&sctps->sctps_g_lock);
907 907 sctp = list_head(&sctps->sctps_g_list);
908 908 while (sctp != NULL && oipif->sctp_ipif_refcnt > 0) {
909 909 mutex_enter(&sctp->sctp_reflock);
910 910 if (sctp->sctp_condemned ||
911 911 sctp->sctp_saddrs[idx].ipif_count <= 0) {
912 912 mutex_exit(&sctp->sctp_reflock);
913 913 sctp = list_next(&sctps->sctps_g_list, sctp);
914 914 continue;
915 915 }
916 916 sctp->sctp_refcnt++;
917 917 mutex_exit(&sctp->sctp_reflock);
918 918 mutex_exit(&sctps->sctps_g_lock);
919 919 if (sctp_prev != NULL)
920 920 SCTP_REFRELE(sctp_prev);
921 921
922 922 RUN_SCTP(sctp);
923 923 sobj = list_head(&sctp->sctp_saddrs[idx].sctp_ipif_list);
924 924 for (count = 0; count <
925 925 sctp->sctp_saddrs[idx].ipif_count; count++) {
926 926 if (sobj->saddr_ipifp == oipif) {
927 927 SCTP_IPIF_REFHOLD(nipif);
928 928 sobj->saddr_ipifp = nipif;
929 929 ASSERT(oipif->sctp_ipif_refcnt > 0);
930 930 /* We have the writer lock */
931 931 oipif->sctp_ipif_refcnt--;
932 932 /*
933 933 * Can't have more than one referring
934 934 * to the same sctp_ipif.
935 935 */
936 936 break;
937 937 }
938 938 sobj = list_next(&sctp->sctp_saddrs[idx].sctp_ipif_list,
939 939 sobj);
940 940 }
941 941 WAKE_SCTP(sctp);
942 942 sctp_prev = sctp;
943 943 mutex_enter(&sctps->sctps_g_lock);
944 944 sctp = list_next(&sctps->sctps_g_list, sctp);
945 945 }
946 946 mutex_exit(&sctps->sctps_g_lock);
947 947 if (sctp_prev != NULL)
948 948 SCTP_REFRELE(sctp_prev);
949 949 }
950 950
951 951 /*
952 952 * Given an ipif, walk the hash list in the global ipif table and for
953 953 * any other SCTP ipif with the same address and non-zero reference, walk
954 954 * the SCTP list and update the saddr list, if required, to point to the
955 955 * new SCTP ipif. If it is a loopback interface, then there could be
956 956 * multiple interfaces with 127.0.0.1 if there are zones configured, so
957 957 * check the zoneid in addition to the address.
958 958 */
959 959 void
960 960 sctp_chk_and_updt_saddr(int hindex, sctp_ipif_t *ipif, sctp_stack_t *sctps)
961 961 {
962 962 int cnt;
963 963 sctp_ipif_t *sipif;
964 964
965 965 ASSERT(sctps->sctps_g_ipifs[hindex].ipif_count > 0);
966 966 ASSERT(ipif->sctp_ipif_state == SCTP_IPIFS_UP);
967 967
968 968 sipif = list_head(&sctps->sctps_g_ipifs[hindex].sctp_ipif_list);
969 969 for (cnt = 0; cnt < sctps->sctps_g_ipifs[hindex].ipif_count; cnt++) {
970 970 rw_enter(&sipif->sctp_ipif_lock, RW_WRITER);
971 971 if (sipif->sctp_ipif_id != ipif->sctp_ipif_id &&
972 972 IN6_ARE_ADDR_EQUAL(&sipif->sctp_ipif_saddr,
973 973 &ipif->sctp_ipif_saddr) && sipif->sctp_ipif_refcnt > 0 &&
974 974 (!SCTP_IS_IPIF_LOOPBACK(ipif) || ipif->sctp_ipif_zoneid ==
975 975 sipif->sctp_ipif_zoneid)) {
976 976 /*
977 977 * There can only be one address up at any time
978 978 * and we are here because ipif has been brought
979 979 * up.
980 980 */
981 981 ASSERT(sipif->sctp_ipif_state != SCTP_IPIFS_UP);
982 982 /*
983 983 * Someone has a reference to this we need to update to
984 984 * point to the new sipif.
985 985 */
986 986 sctp_update_saddrs(sipif, ipif, hindex, sctps);
987 987 }
988 988 rw_exit(&sipif->sctp_ipif_lock);
989 989 sipif = list_next(&sctps->sctps_g_ipifs[hindex].sctp_ipif_list,
990 990 sipif);
991 991 }
992 992 }
993 993
994 994 /*
995 995 * Insert a new SCTP ipif using 'ipif'. v6addr is the address that existed
996 996 * prior to the current address in 'ipif'. Only when an existing address
997 997 * is changed on an IPIF, will v6addr be specified. If the IPIF already
998 998 * exists in the global SCTP ipif table, then we either removed it, if
999 999 * it doesn't have any existing reference, or mark it condemned otherwise.
1000 1000 * If an address is being brought up (IPIF_UP), then we need to scan
1001 1001 * the SCTP list to check if there is any SCTP that points to the *same*
1002 1002 * address on a different SCTP ipif and update in that case.
1003 1003 */
1004 1004 void
1005 1005 sctp_update_ipif_addr(ipif_t *ipif, in6_addr_t v6addr)
1006 1006 {
1007 1007 ill_t *ill = ipif->ipif_ill;
1008 1008 int i;
1009 1009 sctp_ill_t *sctp_ill;
1010 1010 sctp_ill_t *osctp_ill;
1011 1011 sctp_ipif_t *sctp_ipif = NULL;
1012 1012 sctp_ipif_t *osctp_ipif = NULL;
1013 1013 uint_t ill_index;
1014 1014 int hindex;
1015 1015 sctp_stack_t *sctps;
1016 1016
1017 1017 sctps = ipif->ipif_ill->ill_ipst->ips_netstack->netstack_sctp;
1018 1018
1019 1019 /* Index for new address */
1020 1020 hindex = SCTP_IPIF_ADDR_HASH(ipif->ipif_v6lcl_addr, ill->ill_isv6);
1021 1021
1022 1022 /*
1023 1023 * The address on this IPIF is changing, we need to look for
1024 1024 * this old address and mark it condemned, before creating
1025 1025 * one for the new address.
1026 1026 */
1027 1027 osctp_ipif = sctp_lookup_ipif_addr(&v6addr, B_FALSE,
1028 1028 ipif->ipif_zoneid, B_TRUE, SCTP_ILL_TO_PHYINDEX(ill),
1029 1029 ipif->ipif_seqid, B_FALSE, sctps);
1030 1030
1031 1031 rw_enter(&sctps->sctps_g_ills_lock, RW_READER);
1032 1032 rw_enter(&sctps->sctps_g_ipifs_lock, RW_WRITER);
1033 1033
1034 1034 ill_index = SCTP_ILL_HASH_FN(SCTP_ILL_TO_PHYINDEX(ill));
1035 1035 sctp_ill = list_head(&sctps->sctps_g_ills[ill_index].sctp_ill_list);
1036 1036 for (i = 0; i < sctps->sctps_g_ills[ill_index].ill_count; i++) {
1037 1037 if (sctp_ill->sctp_ill_index == SCTP_ILL_TO_PHYINDEX(ill) &&
1038 1038 sctp_ill->sctp_ill_isv6 == ill->ill_isv6) {
1039 1039 break;
1040 1040 }
1041 1041 sctp_ill = list_next(
1042 1042 &sctps->sctps_g_ills[ill_index].sctp_ill_list, sctp_ill);
1043 1043 }
1044 1044
1045 1045 if (sctp_ill == NULL) {
1046 1046 ip1dbg(("sctp_update_ipif_addr: ill not found ..\n"));
1047 1047 rw_exit(&sctps->sctps_g_ipifs_lock);
1048 1048 rw_exit(&sctps->sctps_g_ills_lock);
1049 1049 return;
1050 1050 }
1051 1051
1052 1052 if (osctp_ipif != NULL) {
1053 1053
1054 1054 /* The address is the same? */
1055 1055 if (IN6_ARE_ADDR_EQUAL(&ipif->ipif_v6lcl_addr, &v6addr)) {
1056 1056 boolean_t chk_n_updt = B_FALSE;
1057 1057
1058 1058 rw_downgrade(&sctps->sctps_g_ipifs_lock);
1059 1059 rw_enter(&osctp_ipif->sctp_ipif_lock, RW_WRITER);
1060 1060 if (ipif->ipif_flags & IPIF_UP &&
1061 1061 osctp_ipif->sctp_ipif_state != SCTP_IPIFS_UP) {
1062 1062 osctp_ipif->sctp_ipif_state = SCTP_IPIFS_UP;
1063 1063 chk_n_updt = B_TRUE;
1064 1064 } else {
1065 1065 osctp_ipif->sctp_ipif_state = SCTP_IPIFS_DOWN;
1066 1066 }
1067 1067 osctp_ipif->sctp_ipif_flags = ipif->ipif_flags;
1068 1068 rw_exit(&osctp_ipif->sctp_ipif_lock);
1069 1069 if (chk_n_updt) {
1070 1070 sctp_chk_and_updt_saddr(hindex, osctp_ipif,
1071 1071 sctps);
1072 1072 }
1073 1073 rw_exit(&sctps->sctps_g_ipifs_lock);
1074 1074 rw_exit(&sctps->sctps_g_ills_lock);
1075 1075 return;
1076 1076 }
1077 1077 /*
1078 1078 * We are effectively removing this address from the ILL.
1079 1079 */
1080 1080 if (osctp_ipif->sctp_ipif_refcnt != 0) {
1081 1081 osctp_ipif->sctp_ipif_state = SCTP_IPIFS_CONDEMNED;
1082 1082 } else {
1083 1083 list_t *ipif_list;
1084 1084 int ohindex;
1085 1085
1086 1086 osctp_ill = osctp_ipif->sctp_ipif_ill;
1087 1087 /* hash index for the old one */
1088 1088 ohindex = SCTP_IPIF_ADDR_HASH(
1089 1089 osctp_ipif->sctp_ipif_saddr,
↓ open down ↓ |
191 lines elided |
↑ open up ↑ |
1090 1090 osctp_ipif->sctp_ipif_isv6);
1091 1091
1092 1092 ipif_list =
1093 1093 &sctps->sctps_g_ipifs[ohindex].sctp_ipif_list;
1094 1094
1095 1095 list_remove(ipif_list, (void *)osctp_ipif);
1096 1096 sctps->sctps_g_ipifs[ohindex].ipif_count--;
1097 1097 sctps->sctps_g_ipifs_count--;
1098 1098 rw_destroy(&osctp_ipif->sctp_ipif_lock);
1099 1099 kmem_free(osctp_ipif, sizeof (sctp_ipif_t));
1100 - (void) atomic_add_32_nv(&osctp_ill->sctp_ill_ipifcnt,
1101 - -1);
1100 + (void) atomic_dec_32_nv(&osctp_ill->sctp_ill_ipifcnt);
1102 1101 }
1103 1102 }
1104 1103
1105 1104 sctp_ipif = kmem_zalloc(sizeof (sctp_ipif_t), KM_NOSLEEP);
1106 1105 /* Try again? */
1107 1106 if (sctp_ipif == NULL) {
1108 1107 cmn_err(CE_WARN, "sctp_update_ipif_addr: error adding "
1109 1108 "IPIF %p to SCTP's IPIF list", (void *)ipif);
1110 1109 rw_exit(&sctps->sctps_g_ipifs_lock);
1111 1110 rw_exit(&sctps->sctps_g_ills_lock);
1112 1111 return;
1113 1112 }
1114 1113 sctps->sctps_g_ipifs_count++;
1115 1114 rw_init(&sctp_ipif->sctp_ipif_lock, NULL, RW_DEFAULT, NULL);
1116 1115 sctp_ipif->sctp_ipif_saddr = ipif->ipif_v6lcl_addr;
1117 1116 sctp_ipif->sctp_ipif_ill = sctp_ill;
1118 1117 sctp_ipif->sctp_ipif_isv6 = ill->ill_isv6;
1119 1118 sctp_ipif->sctp_ipif_zoneid = ipif->ipif_zoneid;
1120 1119 sctp_ipif->sctp_ipif_id = ipif->ipif_seqid;
1121 1120 if (ipif->ipif_flags & IPIF_UP)
1122 1121 sctp_ipif->sctp_ipif_state = SCTP_IPIFS_UP;
↓ open down ↓ |
11 lines elided |
↑ open up ↑ |
1123 1122 else
1124 1123 sctp_ipif->sctp_ipif_state = SCTP_IPIFS_DOWN;
1125 1124 sctp_ipif->sctp_ipif_flags = ipif->ipif_flags;
1126 1125 /*
1127 1126 * We add it to the head so that it is quicker to find good/recent
1128 1127 * additions.
1129 1128 */
1130 1129 list_insert_head(&sctps->sctps_g_ipifs[hindex].sctp_ipif_list,
1131 1130 (void *)sctp_ipif);
1132 1131 sctps->sctps_g_ipifs[hindex].ipif_count++;
1133 - atomic_add_32(&sctp_ill->sctp_ill_ipifcnt, 1);
1132 + atomic_inc_32(&sctp_ill->sctp_ill_ipifcnt);
1134 1133 if (sctp_ipif->sctp_ipif_state == SCTP_IPIFS_UP)
1135 1134 sctp_chk_and_updt_saddr(hindex, sctp_ipif, sctps);
1136 1135 rw_exit(&sctps->sctps_g_ipifs_lock);
1137 1136 rw_exit(&sctps->sctps_g_ills_lock);
1138 1137 }
1139 1138
1140 1139 /* Insert, Remove, Mark up or Mark down the ipif */
1141 1140 void
1142 1141 sctp_update_ipif(ipif_t *ipif, int op)
1143 1142 {
1144 1143 ill_t *ill = ipif->ipif_ill;
1145 1144 int i;
1146 1145 sctp_ill_t *sctp_ill;
1147 1146 sctp_ipif_t *sctp_ipif;
1148 1147 uint_t ill_index;
1149 1148 uint_t hindex;
1150 1149 netstack_t *ns = ipif->ipif_ill->ill_ipst->ips_netstack;
1151 1150 sctp_stack_t *sctps = ns->netstack_sctp;
1152 1151
1153 1152 ip2dbg(("sctp_update_ipif: %s %d\n", ill->ill_name, ipif->ipif_seqid));
1154 1153
1155 1154 rw_enter(&sctps->sctps_g_ills_lock, RW_READER);
1156 1155 rw_enter(&sctps->sctps_g_ipifs_lock, RW_WRITER);
1157 1156
1158 1157 ill_index = SCTP_ILL_HASH_FN(SCTP_ILL_TO_PHYINDEX(ill));
1159 1158 sctp_ill = list_head(&sctps->sctps_g_ills[ill_index].sctp_ill_list);
1160 1159 for (i = 0; i < sctps->sctps_g_ills[ill_index].ill_count; i++) {
1161 1160 if (sctp_ill->sctp_ill_index == SCTP_ILL_TO_PHYINDEX(ill) &&
1162 1161 sctp_ill->sctp_ill_isv6 == ill->ill_isv6) {
1163 1162 break;
1164 1163 }
1165 1164 sctp_ill = list_next(
1166 1165 &sctps->sctps_g_ills[ill_index].sctp_ill_list, sctp_ill);
1167 1166 }
1168 1167 if (sctp_ill == NULL) {
1169 1168 rw_exit(&sctps->sctps_g_ipifs_lock);
1170 1169 rw_exit(&sctps->sctps_g_ills_lock);
1171 1170 return;
1172 1171 }
1173 1172
1174 1173 hindex = SCTP_IPIF_ADDR_HASH(ipif->ipif_v6lcl_addr,
1175 1174 ipif->ipif_ill->ill_isv6);
1176 1175 sctp_ipif = list_head(&sctps->sctps_g_ipifs[hindex].sctp_ipif_list);
1177 1176 for (i = 0; i < sctps->sctps_g_ipifs[hindex].ipif_count; i++) {
1178 1177 if (sctp_ipif->sctp_ipif_id == ipif->ipif_seqid) {
1179 1178 ASSERT(IN6_ARE_ADDR_EQUAL(&sctp_ipif->sctp_ipif_saddr,
1180 1179 &ipif->ipif_v6lcl_addr));
1181 1180 break;
1182 1181 }
1183 1182 sctp_ipif = list_next(
1184 1183 &sctps->sctps_g_ipifs[hindex].sctp_ipif_list,
1185 1184 sctp_ipif);
1186 1185 }
1187 1186 if (sctp_ipif == NULL) {
1188 1187 ip1dbg(("sctp_update_ipif: null sctp_ipif for %d\n", op));
1189 1188 rw_exit(&sctps->sctps_g_ipifs_lock);
1190 1189 rw_exit(&sctps->sctps_g_ills_lock);
1191 1190 return;
1192 1191 }
1193 1192 ASSERT(sctp_ill == sctp_ipif->sctp_ipif_ill);
1194 1193 switch (op) {
1195 1194 case SCTP_IPIF_REMOVE:
1196 1195 {
1197 1196 list_t *ipif_list;
1198 1197 list_t *ill_list;
1199 1198
1200 1199 ill_list = &sctps->sctps_g_ills[ill_index].sctp_ill_list;
1201 1200 ipif_list = &sctps->sctps_g_ipifs[hindex].sctp_ipif_list;
1202 1201 if (sctp_ipif->sctp_ipif_refcnt != 0) {
↓ open down ↓ |
59 lines elided |
↑ open up ↑ |
1203 1202 sctp_ipif->sctp_ipif_state = SCTP_IPIFS_CONDEMNED;
1204 1203 rw_exit(&sctps->sctps_g_ipifs_lock);
1205 1204 rw_exit(&sctps->sctps_g_ills_lock);
1206 1205 return;
1207 1206 }
1208 1207 list_remove(ipif_list, (void *)sctp_ipif);
1209 1208 sctps->sctps_g_ipifs[hindex].ipif_count--;
1210 1209 sctps->sctps_g_ipifs_count--;
1211 1210 rw_destroy(&sctp_ipif->sctp_ipif_lock);
1212 1211 kmem_free(sctp_ipif, sizeof (sctp_ipif_t));
1213 - (void) atomic_add_32_nv(&sctp_ill->sctp_ill_ipifcnt, -1);
1212 + (void) atomic_dec_32_nv(&sctp_ill->sctp_ill_ipifcnt);
1214 1213 if (rw_tryupgrade(&sctps->sctps_g_ills_lock) != 0) {
1215 1214 rw_downgrade(&sctps->sctps_g_ipifs_lock);
1216 1215 if (sctp_ill->sctp_ill_ipifcnt == 0 &&
1217 1216 sctp_ill->sctp_ill_state == SCTP_ILLS_CONDEMNED) {
1218 1217 list_remove(ill_list, (void *)sctp_ill);
1219 1218 sctps->sctps_ills_count--;
1220 1219 sctps->sctps_g_ills[ill_index].ill_count--;
1221 1220 kmem_free(sctp_ill->sctp_ill_name,
1222 1221 sctp_ill->sctp_ill_name_length);
1223 1222 kmem_free(sctp_ill, sizeof (sctp_ill_t));
1224 1223 }
1225 1224 }
1226 1225 break;
1227 1226 }
1228 1227
1229 1228 case SCTP_IPIF_UP:
1230 1229
1231 1230 rw_downgrade(&sctps->sctps_g_ipifs_lock);
1232 1231 rw_enter(&sctp_ipif->sctp_ipif_lock, RW_WRITER);
1233 1232 sctp_ipif->sctp_ipif_state = SCTP_IPIFS_UP;
1234 1233 sctp_ipif->sctp_ipif_flags = ipif->ipif_flags;
1235 1234 rw_exit(&sctp_ipif->sctp_ipif_lock);
1236 1235 sctp_chk_and_updt_saddr(hindex, sctp_ipif,
1237 1236 ipif->ipif_ill->ill_ipst->ips_netstack->netstack_sctp);
1238 1237
1239 1238 break;
1240 1239
1241 1240 case SCTP_IPIF_UPDATE:
1242 1241
1243 1242 rw_downgrade(&sctps->sctps_g_ipifs_lock);
1244 1243 rw_enter(&sctp_ipif->sctp_ipif_lock, RW_WRITER);
1245 1244 sctp_ipif->sctp_ipif_zoneid = ipif->ipif_zoneid;
1246 1245 sctp_ipif->sctp_ipif_flags = ipif->ipif_flags;
1247 1246 rw_exit(&sctp_ipif->sctp_ipif_lock);
1248 1247
1249 1248 break;
1250 1249
1251 1250 case SCTP_IPIF_DOWN:
1252 1251
1253 1252 rw_downgrade(&sctps->sctps_g_ipifs_lock);
1254 1253 rw_enter(&sctp_ipif->sctp_ipif_lock, RW_WRITER);
1255 1254 sctp_ipif->sctp_ipif_state = SCTP_IPIFS_DOWN;
1256 1255 sctp_ipif->sctp_ipif_flags = ipif->ipif_flags;
1257 1256 rw_exit(&sctp_ipif->sctp_ipif_lock);
1258 1257
1259 1258 break;
1260 1259 }
1261 1260 rw_exit(&sctps->sctps_g_ipifs_lock);
1262 1261 rw_exit(&sctps->sctps_g_ills_lock);
1263 1262 }
1264 1263
1265 1264 /*
1266 1265 * SCTP source address list manipulaton, locking not used (except for
1267 1266 * sctp locking by the caller.
1268 1267 */
1269 1268
1270 1269 /* Remove a specific saddr from the list */
1271 1270 void
1272 1271 sctp_del_saddr(sctp_t *sctp, sctp_saddr_ipif_t *sp)
1273 1272 {
1274 1273 if (sctp->sctp_conn_tfp != NULL)
1275 1274 mutex_enter(&sctp->sctp_conn_tfp->tf_lock);
1276 1275
1277 1276 if (sctp->sctp_listen_tfp != NULL)
1278 1277 mutex_enter(&sctp->sctp_listen_tfp->tf_lock);
1279 1278
1280 1279 sctp_ipif_hash_remove(sctp, sp->saddr_ipifp, B_FALSE);
1281 1280
1282 1281 if (sctp->sctp_bound_to_all == 1)
1283 1282 sctp->sctp_bound_to_all = 0;
1284 1283
1285 1284 if (sctp->sctp_conn_tfp != NULL)
1286 1285 mutex_exit(&sctp->sctp_conn_tfp->tf_lock);
1287 1286
1288 1287 if (sctp->sctp_listen_tfp != NULL)
1289 1288 mutex_exit(&sctp->sctp_listen_tfp->tf_lock);
1290 1289 }
1291 1290
1292 1291 /*
1293 1292 * Delete source address from the existing list. No error checking done here
1294 1293 * Called with no locks held.
1295 1294 */
1296 1295 void
1297 1296 sctp_del_saddr_list(sctp_t *sctp, const void *addrs, int addcnt,
1298 1297 boolean_t fanout_locked)
1299 1298 {
1300 1299 struct sockaddr_in *sin4;
1301 1300 struct sockaddr_in6 *sin6;
1302 1301 int cnt;
1303 1302 in6_addr_t addr;
1304 1303 sctp_ipif_t *sctp_ipif;
1305 1304 int ifindex = 0;
1306 1305 conn_t *connp = sctp->sctp_connp;
1307 1306
1308 1307 ASSERT(sctp->sctp_nsaddrs >= addcnt);
1309 1308
1310 1309 if (!fanout_locked) {
1311 1310 if (sctp->sctp_conn_tfp != NULL)
1312 1311 mutex_enter(&sctp->sctp_conn_tfp->tf_lock);
1313 1312 if (sctp->sctp_listen_tfp != NULL)
1314 1313 mutex_enter(&sctp->sctp_listen_tfp->tf_lock);
1315 1314 }
1316 1315
1317 1316 for (cnt = 0; cnt < addcnt; cnt++) {
1318 1317 switch (connp->conn_family) {
1319 1318 case AF_INET:
1320 1319 sin4 = (struct sockaddr_in *)addrs + cnt;
1321 1320 IN6_INADDR_TO_V4MAPPED(&sin4->sin_addr, &addr);
1322 1321 break;
1323 1322
1324 1323 case AF_INET6:
1325 1324 sin6 = (struct sockaddr_in6 *)addrs + cnt;
1326 1325 addr = sin6->sin6_addr;
1327 1326 ifindex = sin6->sin6_scope_id;
1328 1327 break;
1329 1328 }
1330 1329 sctp_ipif = sctp_lookup_ipif_addr(&addr, B_FALSE,
1331 1330 IPCL_ZONEID(connp), !connp->conn_allzones,
1332 1331 ifindex, 0, B_TRUE, sctp->sctp_sctps);
1333 1332 ASSERT(sctp_ipif != NULL);
1334 1333 sctp_ipif_hash_remove(sctp, sctp_ipif, B_FALSE);
1335 1334 }
1336 1335 if (sctp->sctp_bound_to_all == 1)
1337 1336 sctp->sctp_bound_to_all = 0;
1338 1337
1339 1338 if (!fanout_locked) {
1340 1339 if (sctp->sctp_conn_tfp != NULL)
1341 1340 mutex_exit(&sctp->sctp_conn_tfp->tf_lock);
1342 1341 if (sctp->sctp_listen_tfp != NULL)
1343 1342 mutex_exit(&sctp->sctp_listen_tfp->tf_lock);
1344 1343 }
1345 1344 }
1346 1345
1347 1346 /*
1348 1347 * Given an address get the corresponding entry from the list
1349 1348 * Called with no locks held.
1350 1349 */
1351 1350 sctp_saddr_ipif_t *
1352 1351 sctp_saddr_lookup(sctp_t *sctp, in6_addr_t *addr, uint_t ifindex)
1353 1352 {
1354 1353 int cnt;
1355 1354 sctp_saddr_ipif_t *ipif_obj;
1356 1355 int hindex;
1357 1356 sctp_ipif_t *sctp_ipif;
1358 1357
1359 1358 hindex = SCTP_IPIF_ADDR_HASH(*addr, !IN6_IS_ADDR_V4MAPPED(addr));
1360 1359 rw_enter(&sctp->sctp_saddrs[hindex].ipif_hash_lock, RW_READER);
1361 1360 if (sctp->sctp_saddrs[hindex].ipif_count == 0) {
1362 1361 rw_exit(&sctp->sctp_saddrs[hindex].ipif_hash_lock);
1363 1362 return (NULL);
1364 1363 }
1365 1364
1366 1365 ipif_obj = list_head(&sctp->sctp_saddrs[hindex].sctp_ipif_list);
1367 1366 for (cnt = 0; cnt < sctp->sctp_saddrs[hindex].ipif_count; cnt++) {
1368 1367 sctp_ipif = ipif_obj->saddr_ipifp;
1369 1368 /*
1370 1369 * Zone check shouldn't be needed.
1371 1370 */
1372 1371 if (IN6_ARE_ADDR_EQUAL(addr, &sctp_ipif->sctp_ipif_saddr) &&
1373 1372 (ifindex == 0 ||
1374 1373 ifindex == sctp_ipif->sctp_ipif_ill->sctp_ill_index) &&
1375 1374 SCTP_IPIF_USABLE(sctp_ipif->sctp_ipif_state)) {
1376 1375 rw_exit(&sctp->sctp_saddrs[hindex].ipif_hash_lock);
1377 1376 return (ipif_obj);
1378 1377 }
1379 1378 ipif_obj = list_next(&sctp->sctp_saddrs[hindex].sctp_ipif_list,
1380 1379 ipif_obj);
1381 1380 }
1382 1381 rw_exit(&sctp->sctp_saddrs[hindex].ipif_hash_lock);
1383 1382 return (NULL);
1384 1383 }
1385 1384
1386 1385 /* Given an address, add it to the source address list */
1387 1386 int
1388 1387 sctp_saddr_add_addr(sctp_t *sctp, in6_addr_t *addr, uint_t ifindex)
1389 1388 {
1390 1389 sctp_ipif_t *sctp_ipif;
1391 1390 conn_t *connp = sctp->sctp_connp;
1392 1391
1393 1392 sctp_ipif = sctp_lookup_ipif_addr(addr, B_TRUE, IPCL_ZONEID(connp),
1394 1393 !connp->conn_allzones, ifindex, 0, B_TRUE, sctp->sctp_sctps);
1395 1394 if (sctp_ipif == NULL)
1396 1395 return (EINVAL);
1397 1396
1398 1397 if (sctp_ipif_hash_insert(sctp, sctp_ipif, KM_NOSLEEP, B_FALSE,
1399 1398 B_FALSE) != 0) {
1400 1399 SCTP_IPIF_REFRELE(sctp_ipif);
1401 1400 return (EINVAL);
1402 1401 }
1403 1402 return (0);
1404 1403 }
1405 1404
1406 1405 /*
1407 1406 * Remove or mark as dontsrc addresses that are currently not part of the
1408 1407 * association. One would delete addresses when processing an INIT and
1409 1408 * mark as dontsrc when processing an INIT-ACK.
1410 1409 */
1411 1410 void
1412 1411 sctp_check_saddr(sctp_t *sctp, int supp_af, boolean_t delete,
1413 1412 in6_addr_t *no_del_addr)
1414 1413 {
1415 1414 int i;
1416 1415 int l;
1417 1416 sctp_saddr_ipif_t *obj;
1418 1417 int scanned = 0;
1419 1418 int naddr;
1420 1419 int nsaddr;
1421 1420 conn_t *connp = sctp->sctp_connp;
1422 1421
1423 1422 ASSERT(!sctp->sctp_loopback && !sctp->sctp_linklocal && supp_af != 0);
1424 1423
1425 1424 /*
1426 1425 * Irregardless of the supported address in the INIT, v4
1427 1426 * must be supported.
1428 1427 */
1429 1428 if (connp->conn_family == AF_INET)
1430 1429 supp_af = PARM_SUPP_V4;
1431 1430
1432 1431 nsaddr = sctp->sctp_nsaddrs;
1433 1432 for (i = 0; i < SCTP_IPIF_HASH; i++) {
1434 1433 rw_enter(&sctp->sctp_saddrs[i].ipif_hash_lock, RW_WRITER);
1435 1434 if (sctp->sctp_saddrs[i].ipif_count == 0) {
1436 1435 rw_exit(&sctp->sctp_saddrs[i].ipif_hash_lock);
1437 1436 continue;
1438 1437 }
1439 1438 obj = list_head(&sctp->sctp_saddrs[i].sctp_ipif_list);
1440 1439 naddr = sctp->sctp_saddrs[i].ipif_count;
1441 1440 for (l = 0; l < naddr; l++) {
1442 1441 sctp_ipif_t *ipif;
1443 1442
1444 1443 ipif = obj->saddr_ipifp;
1445 1444 scanned++;
1446 1445
1447 1446 if (IN6_ARE_ADDR_EQUAL(&ipif->sctp_ipif_saddr,
1448 1447 no_del_addr)) {
1449 1448 goto next_obj;
1450 1449 }
1451 1450
1452 1451 /*
1453 1452 * Delete/mark dontsrc loopback/linklocal addresses and
1454 1453 * unsupported address.
1455 1454 * On a clustered node, we trust the clustering module
1456 1455 * to do the right thing w.r.t loopback addresses, so
1457 1456 * we ignore loopback addresses in this check.
1458 1457 */
1459 1458 if ((SCTP_IS_IPIF_LOOPBACK(ipif) &&
1460 1459 cl_sctp_check_addrs == NULL) ||
1461 1460 SCTP_IS_IPIF_LINKLOCAL(ipif) ||
1462 1461 SCTP_UNSUPP_AF(ipif, supp_af)) {
1463 1462 if (!delete) {
1464 1463 obj->saddr_ipif_unconfirmed = 1;
1465 1464 goto next_obj;
1466 1465 }
1467 1466 if (sctp->sctp_bound_to_all == 1)
1468 1467 sctp->sctp_bound_to_all = 0;
1469 1468 if (scanned < nsaddr) {
1470 1469 obj = list_next(&sctp->sctp_saddrs[i].
1471 1470 sctp_ipif_list, obj);
1472 1471 sctp_ipif_hash_remove(sctp, ipif,
1473 1472 B_TRUE);
1474 1473 continue;
1475 1474 }
1476 1475 sctp_ipif_hash_remove(sctp, ipif, B_TRUE);
1477 1476 }
1478 1477 next_obj:
1479 1478 if (scanned >= nsaddr) {
1480 1479 rw_exit(&sctp->sctp_saddrs[i].ipif_hash_lock);
1481 1480 return;
1482 1481 }
1483 1482 obj = list_next(&sctp->sctp_saddrs[i].sctp_ipif_list,
1484 1483 obj);
1485 1484 }
1486 1485 rw_exit(&sctp->sctp_saddrs[i].ipif_hash_lock);
1487 1486 }
1488 1487 }
1489 1488
1490 1489
1491 1490 /* Get the first valid address from the list. Called with no locks held */
1492 1491 in6_addr_t
1493 1492 sctp_get_valid_addr(sctp_t *sctp, boolean_t isv6, boolean_t *addr_set)
1494 1493 {
1495 1494 int i;
1496 1495 int l;
1497 1496 sctp_saddr_ipif_t *obj;
1498 1497 int scanned = 0;
1499 1498 in6_addr_t addr;
1500 1499
1501 1500 for (i = 0; i < SCTP_IPIF_HASH; i++) {
1502 1501 rw_enter(&sctp->sctp_saddrs[i].ipif_hash_lock, RW_READER);
1503 1502 if (sctp->sctp_saddrs[i].ipif_count == 0) {
1504 1503 rw_exit(&sctp->sctp_saddrs[i].ipif_hash_lock);
1505 1504 continue;
1506 1505 }
1507 1506 obj = list_head(&sctp->sctp_saddrs[i].sctp_ipif_list);
1508 1507 for (l = 0; l < sctp->sctp_saddrs[i].ipif_count; l++) {
1509 1508 sctp_ipif_t *ipif;
1510 1509
1511 1510 ipif = obj->saddr_ipifp;
1512 1511 if (!SCTP_DONT_SRC(obj) &&
1513 1512 ipif->sctp_ipif_isv6 == isv6 &&
1514 1513 ipif->sctp_ipif_state == SCTP_IPIFS_UP) {
1515 1514 *addr_set = B_TRUE;
1516 1515 rw_exit(&sctp->sctp_saddrs[i].ipif_hash_lock);
1517 1516 return (ipif->sctp_ipif_saddr);
1518 1517 }
1519 1518 scanned++;
1520 1519 if (scanned >= sctp->sctp_nsaddrs) {
1521 1520 rw_exit(&sctp->sctp_saddrs[i].ipif_hash_lock);
1522 1521 goto got_none;
1523 1522 }
1524 1523 obj = list_next(&sctp->sctp_saddrs[i].sctp_ipif_list,
1525 1524 obj);
1526 1525 }
1527 1526 rw_exit(&sctp->sctp_saddrs[i].ipif_hash_lock);
1528 1527 }
1529 1528 got_none:
1530 1529 /* Need to double check this */
1531 1530 if (isv6 == B_TRUE)
1532 1531 addr = ipv6_all_zeros;
1533 1532 else
1534 1533 IN6_IPADDR_TO_V4MAPPED(0, &addr);
1535 1534 *addr_set = B_FALSE;
1536 1535 return (addr);
1537 1536 }
1538 1537
1539 1538 /*
1540 1539 * Return the list of local addresses of an association. The parameter
1541 1540 * myaddrs is supposed to be either (struct sockaddr_in *) or (struct
1542 1541 * sockaddr_in6 *) depending on the address family.
1543 1542 */
1544 1543 int
1545 1544 sctp_getmyaddrs(void *conn, void *myaddrs, int *addrcnt)
1546 1545 {
1547 1546 int i;
1548 1547 int l;
1549 1548 sctp_saddr_ipif_t *obj;
1550 1549 sctp_t *sctp = (sctp_t *)conn;
1551 1550 conn_t *connp = sctp->sctp_connp;
1552 1551 int family = connp->conn_family;
1553 1552 int max = *addrcnt;
1554 1553 size_t added = 0;
1555 1554 struct sockaddr_in6 *sin6;
1556 1555 struct sockaddr_in *sin4;
1557 1556 int scanned = 0;
1558 1557 boolean_t skip_lback = B_FALSE;
1559 1558 ip_xmit_attr_t *ixa = connp->conn_ixa;
1560 1559
1561 1560 if (sctp->sctp_nsaddrs == 0)
1562 1561 return (EINVAL);
1563 1562
1564 1563 /*
1565 1564 * Skip loopback addresses for non-loopback assoc., ignore
1566 1565 * this on a clustered node.
1567 1566 */
1568 1567 if (sctp->sctp_state >= SCTPS_ESTABLISHED && !sctp->sctp_loopback &&
1569 1568 (cl_sctp_check_addrs == NULL)) {
1570 1569 skip_lback = B_TRUE;
1571 1570 }
1572 1571
1573 1572 for (i = 0; i < SCTP_IPIF_HASH; i++) {
1574 1573 rw_enter(&sctp->sctp_saddrs[i].ipif_hash_lock, RW_READER);
1575 1574 if (sctp->sctp_saddrs[i].ipif_count == 0) {
1576 1575 rw_exit(&sctp->sctp_saddrs[i].ipif_hash_lock);
1577 1576 continue;
1578 1577 }
1579 1578 obj = list_head(&sctp->sctp_saddrs[i].sctp_ipif_list);
1580 1579 for (l = 0; l < sctp->sctp_saddrs[i].ipif_count; l++) {
1581 1580 sctp_ipif_t *ipif = obj->saddr_ipifp;
1582 1581 in6_addr_t addr = ipif->sctp_ipif_saddr;
1583 1582
1584 1583 scanned++;
1585 1584 if ((ipif->sctp_ipif_state == SCTP_IPIFS_CONDEMNED) ||
1586 1585 SCTP_DONT_SRC(obj) ||
1587 1586 (SCTP_IS_IPIF_LOOPBACK(ipif) && skip_lback)) {
1588 1587 if (scanned >= sctp->sctp_nsaddrs) {
1589 1588 rw_exit(&sctp->
1590 1589 sctp_saddrs[i].ipif_hash_lock);
1591 1590 goto done;
1592 1591 }
1593 1592 obj = list_next(&sctp->sctp_saddrs[i].
1594 1593 sctp_ipif_list, obj);
1595 1594 continue;
1596 1595 }
1597 1596 switch (family) {
1598 1597 case AF_INET:
1599 1598 sin4 = (struct sockaddr_in *)myaddrs + added;
1600 1599 sin4->sin_family = AF_INET;
1601 1600 sin4->sin_port = connp->conn_lport;
1602 1601 IN6_V4MAPPED_TO_INADDR(&addr, &sin4->sin_addr);
1603 1602 break;
1604 1603
1605 1604 case AF_INET6:
1606 1605 sin6 = (struct sockaddr_in6 *)myaddrs + added;
1607 1606 sin6->sin6_family = AF_INET6;
1608 1607 sin6->sin6_port = connp->conn_lport;
1609 1608 sin6->sin6_addr = addr;
1610 1609 /*
1611 1610 * Note that flowinfo is only returned for
1612 1611 * getpeername just like for TCP and UDP.
1613 1612 */
1614 1613 sin6->sin6_flowinfo = 0;
1615 1614
1616 1615 if (IN6_IS_ADDR_LINKSCOPE(&sin6->sin6_addr) &&
1617 1616 (ixa->ixa_flags & IXAF_SCOPEID_SET))
1618 1617 sin6->sin6_scope_id = ixa->ixa_scopeid;
1619 1618 else
1620 1619 sin6->sin6_scope_id = 0;
1621 1620 sin6->__sin6_src_id = 0;
1622 1621 break;
1623 1622 }
1624 1623 added++;
1625 1624 if (added >= max || scanned >= sctp->sctp_nsaddrs) {
1626 1625 rw_exit(&sctp->sctp_saddrs[i].ipif_hash_lock);
1627 1626 goto done;
1628 1627 }
1629 1628 obj = list_next(&sctp->sctp_saddrs[i].sctp_ipif_list,
1630 1629 obj);
1631 1630 }
1632 1631 rw_exit(&sctp->sctp_saddrs[i].ipif_hash_lock);
1633 1632 }
1634 1633 done:
1635 1634 *addrcnt = added;
1636 1635 return (0);
1637 1636 }
1638 1637
1639 1638 /*
1640 1639 * Given the supported address family, walk through the source address list
1641 1640 * and return the total length of the available addresses. If 'p' is not
1642 1641 * null, construct the parameter list for the addresses in 'p'.
1643 1642 * 'modify' will only be set when we want the source address list to
1644 1643 * be modified. The source address list will be modified only when
1645 1644 * generating an INIT chunk. For generating an INIT-ACK 'modify' will
1646 1645 * be false since the 'sctp' will be that of the listener.
1647 1646 */
1648 1647 size_t
1649 1648 sctp_saddr_info(sctp_t *sctp, int supp_af, uchar_t *p, boolean_t modify)
1650 1649 {
1651 1650 int i;
1652 1651 int l;
1653 1652 sctp_saddr_ipif_t *obj;
1654 1653 size_t paramlen = 0;
1655 1654 sctp_parm_hdr_t *hdr;
1656 1655 int scanned = 0;
1657 1656 int naddr;
1658 1657 int nsaddr;
1659 1658 boolean_t del_ll = B_FALSE;
1660 1659 boolean_t del_lb = B_FALSE;
1661 1660
1662 1661
1663 1662 /*
1664 1663 * On a clustered node don't bother changing anything
1665 1664 * on the loopback interface.
1666 1665 */
1667 1666 if (modify && !sctp->sctp_loopback && (cl_sctp_check_addrs == NULL))
1668 1667 del_lb = B_TRUE;
1669 1668
1670 1669 if (modify && !sctp->sctp_linklocal)
1671 1670 del_ll = B_TRUE;
1672 1671
1673 1672 nsaddr = sctp->sctp_nsaddrs;
1674 1673 for (i = 0; i < SCTP_IPIF_HASH; i++) {
1675 1674 rw_enter(&sctp->sctp_saddrs[i].ipif_hash_lock, RW_WRITER);
1676 1675 if (sctp->sctp_saddrs[i].ipif_count == 0) {
1677 1676 rw_exit(&sctp->sctp_saddrs[i].ipif_hash_lock);
1678 1677 continue;
1679 1678 }
1680 1679 obj = list_head(&sctp->sctp_saddrs[i].sctp_ipif_list);
1681 1680 naddr = sctp->sctp_saddrs[i].ipif_count;
1682 1681 for (l = 0; l < naddr; l++) {
1683 1682 in6_addr_t addr;
1684 1683 sctp_ipif_t *ipif;
1685 1684 boolean_t ipif_lb;
1686 1685 boolean_t ipif_ll;
1687 1686 boolean_t unsupp_af;
1688 1687
1689 1688 ipif = obj->saddr_ipifp;
1690 1689 scanned++;
1691 1690
1692 1691 ipif_lb = SCTP_IS_IPIF_LOOPBACK(ipif);
1693 1692 ipif_ll = SCTP_IS_IPIF_LINKLOCAL(ipif);
1694 1693 unsupp_af = SCTP_UNSUPP_AF(ipif, supp_af);
1695 1694 /*
1696 1695 * We need to either delete or skip loopback/linklocal
1697 1696 * or unsupported addresses, if required.
1698 1697 */
1699 1698 if ((ipif_ll && del_ll) || (ipif_lb && del_lb) ||
1700 1699 (unsupp_af && modify)) {
1701 1700 if (sctp->sctp_bound_to_all == 1)
1702 1701 sctp->sctp_bound_to_all = 0;
1703 1702 if (scanned < nsaddr) {
1704 1703 obj = list_next(&sctp->sctp_saddrs[i].
1705 1704 sctp_ipif_list, obj);
1706 1705 sctp_ipif_hash_remove(sctp, ipif,
1707 1706 B_TRUE);
1708 1707 continue;
1709 1708 }
1710 1709 sctp_ipif_hash_remove(sctp, ipif, B_TRUE);
1711 1710
1712 1711 goto next_addr;
1713 1712 } else if (ipif_ll || unsupp_af ||
1714 1713 (ipif_lb && (cl_sctp_check_addrs == NULL))) {
1715 1714 goto next_addr;
1716 1715 }
1717 1716
1718 1717 if (!SCTP_IPIF_USABLE(ipif->sctp_ipif_state))
1719 1718 goto next_addr;
1720 1719 if (p != NULL)
1721 1720 hdr = (sctp_parm_hdr_t *)(p + paramlen);
1722 1721 addr = ipif->sctp_ipif_saddr;
1723 1722 if (!ipif->sctp_ipif_isv6) {
1724 1723 struct in_addr *v4;
1725 1724
1726 1725 if (p != NULL) {
1727 1726 hdr->sph_type = htons(PARM_ADDR4);
1728 1727 hdr->sph_len = htons(PARM_ADDR4_LEN);
1729 1728 v4 = (struct in_addr *)(hdr + 1);
1730 1729 IN6_V4MAPPED_TO_INADDR(&addr, v4);
1731 1730 }
1732 1731 paramlen += PARM_ADDR4_LEN;
1733 1732 } else {
1734 1733 if (p != NULL) {
1735 1734 hdr->sph_type = htons(PARM_ADDR6);
1736 1735 hdr->sph_len = htons(PARM_ADDR6_LEN);
1737 1736 bcopy(&addr, hdr + 1, sizeof (addr));
1738 1737 }
1739 1738 paramlen += PARM_ADDR6_LEN;
1740 1739 }
1741 1740 next_addr:
1742 1741 if (scanned >= nsaddr) {
1743 1742 rw_exit(&sctp->sctp_saddrs[i].ipif_hash_lock);
1744 1743 return (paramlen);
1745 1744 }
1746 1745 obj = list_next(&sctp->sctp_saddrs[i].sctp_ipif_list,
1747 1746 obj);
1748 1747 }
1749 1748 rw_exit(&sctp->sctp_saddrs[i].ipif_hash_lock);
1750 1749 }
1751 1750 return (paramlen);
1752 1751 }
1753 1752
1754 1753 /*
1755 1754 * This is used on a clustered node to obtain a list of addresses, the list
1756 1755 * consists of sockaddr_in structs for v4 and sockaddr_in6 for v6. The list
1757 1756 * is then passed onto the clustering module which sends back the correct
1758 1757 * list based on the port info. Regardless of the input, i.e INADDR_ANY
1759 1758 * or specific address(es), we create the list since it could be modified by
1760 1759 * the clustering module. When given a list of addresses, we simply
1761 1760 * create the list of sockaddr_in or sockaddr_in6 structs using those
1762 1761 * addresses. If there is an INADDR_ANY in the input list, or if the
1763 1762 * input is INADDR_ANY, we create a list of sockaddr_in or sockaddr_in6
1764 1763 * structs consisting all the addresses in the global interface list
1765 1764 * except those that are hosted on the loopback interface. We create
1766 1765 * a list of sockaddr_in[6] structs just so that it can be directly input
1767 1766 * to sctp_valid_addr_list() once the clustering module has processed it.
1768 1767 */
1769 1768 int
1770 1769 sctp_get_addrlist(sctp_t *sctp, const void *addrs, uint32_t *addrcnt,
1771 1770 uchar_t **addrlist, int *uspec, size_t *size)
1772 1771 {
1773 1772 int cnt;
1774 1773 int icnt;
1775 1774 sctp_ipif_t *sctp_ipif;
1776 1775 struct sockaddr_in *s4;
1777 1776 struct sockaddr_in6 *s6;
1778 1777 uchar_t *p;
1779 1778 int err = 0;
1780 1779 sctp_stack_t *sctps = sctp->sctp_sctps;
1781 1780 conn_t *connp = sctp->sctp_connp;
1782 1781
1783 1782 *addrlist = NULL;
1784 1783 *size = 0;
1785 1784
1786 1785 /*
1787 1786 * Create a list of sockaddr_in[6] structs using the input list.
1788 1787 */
1789 1788 if (connp->conn_family == AF_INET) {
1790 1789 *size = sizeof (struct sockaddr_in) * *addrcnt;
1791 1790 *addrlist = kmem_zalloc(*size, KM_SLEEP);
1792 1791 p = *addrlist;
1793 1792 for (cnt = 0; cnt < *addrcnt; cnt++) {
1794 1793 s4 = (struct sockaddr_in *)addrs + cnt;
1795 1794 /*
1796 1795 * We need to create a list of all the available
1797 1796 * addresses if there is an INADDR_ANY. However,
1798 1797 * if we are beyond LISTEN, then this is invalid
1799 1798 * (see sctp_valid_addr_list(). So, we just fail
1800 1799 * it here rather than wait till it fails in
1801 1800 * sctp_valid_addr_list().
1802 1801 */
1803 1802 if (s4->sin_addr.s_addr == INADDR_ANY) {
1804 1803 kmem_free(*addrlist, *size);
1805 1804 *addrlist = NULL;
1806 1805 *size = 0;
1807 1806 if (sctp->sctp_state > SCTPS_LISTEN) {
1808 1807 *addrcnt = 0;
1809 1808 return (EINVAL);
1810 1809 }
1811 1810 if (uspec != NULL)
1812 1811 *uspec = 1;
1813 1812 goto get_all_addrs;
1814 1813 } else {
1815 1814 bcopy(s4, p, sizeof (*s4));
1816 1815 p += sizeof (*s4);
1817 1816 }
1818 1817 }
1819 1818 } else {
1820 1819 *size = sizeof (struct sockaddr_in6) * *addrcnt;
1821 1820 *addrlist = kmem_zalloc(*size, KM_SLEEP);
1822 1821 p = *addrlist;
1823 1822 for (cnt = 0; cnt < *addrcnt; cnt++) {
1824 1823 s6 = (struct sockaddr_in6 *)addrs + cnt;
1825 1824 /*
1826 1825 * Comments for INADDR_ANY, above, apply here too.
1827 1826 */
1828 1827 if (IN6_IS_ADDR_UNSPECIFIED(&s6->sin6_addr)) {
1829 1828 kmem_free(*addrlist, *size);
1830 1829 *size = 0;
1831 1830 *addrlist = NULL;
1832 1831 if (sctp->sctp_state > SCTPS_LISTEN) {
1833 1832 *addrcnt = 0;
1834 1833 return (EINVAL);
1835 1834 }
1836 1835 if (uspec != NULL)
1837 1836 *uspec = 1;
1838 1837 goto get_all_addrs;
1839 1838 } else {
1840 1839 bcopy(addrs, p, sizeof (*s6));
1841 1840 p += sizeof (*s6);
1842 1841 }
1843 1842 }
1844 1843 }
1845 1844 return (err);
1846 1845 get_all_addrs:
1847 1846
1848 1847 /*
1849 1848 * Allocate max possible size. We allocate the max. size here because
1850 1849 * the clustering module could end up adding addresses to the list.
1851 1850 * We allocate upfront so that the clustering module need to bother
1852 1851 * re-sizing the list.
1853 1852 */
1854 1853 if (connp->conn_family == AF_INET) {
1855 1854 *size = sizeof (struct sockaddr_in) *
1856 1855 sctps->sctps_g_ipifs_count;
1857 1856 } else {
1858 1857 *size = sizeof (struct sockaddr_in6) *
1859 1858 sctps->sctps_g_ipifs_count;
1860 1859 }
1861 1860 *addrlist = kmem_zalloc(*size, KM_SLEEP);
1862 1861 *addrcnt = 0;
1863 1862 p = *addrlist;
1864 1863 rw_enter(&sctps->sctps_g_ipifs_lock, RW_READER);
1865 1864
1866 1865 /*
1867 1866 * Walk through the global interface list and add all addresses,
1868 1867 * except those that are hosted on loopback interfaces.
1869 1868 */
1870 1869 for (cnt = 0; cnt < SCTP_IPIF_HASH; cnt++) {
1871 1870 if (sctps->sctps_g_ipifs[cnt].ipif_count == 0)
1872 1871 continue;
1873 1872 sctp_ipif = list_head(
1874 1873 &sctps->sctps_g_ipifs[cnt].sctp_ipif_list);
1875 1874 for (icnt = 0;
1876 1875 icnt < sctps->sctps_g_ipifs[cnt].ipif_count;
1877 1876 icnt++) {
1878 1877 in6_addr_t addr;
1879 1878
1880 1879 rw_enter(&sctp_ipif->sctp_ipif_lock, RW_READER);
1881 1880 addr = sctp_ipif->sctp_ipif_saddr;
1882 1881 if (SCTP_IPIF_DISCARD(sctp_ipif->sctp_ipif_flags) ||
1883 1882 !SCTP_IPIF_USABLE(sctp_ipif->sctp_ipif_state) ||
1884 1883 SCTP_IS_IPIF_LOOPBACK(sctp_ipif) ||
1885 1884 SCTP_IS_IPIF_LINKLOCAL(sctp_ipif) ||
1886 1885 !SCTP_IPIF_ZONE_MATCH(sctp, sctp_ipif) ||
1887 1886 (connp->conn_family == AF_INET &&
1888 1887 sctp_ipif->sctp_ipif_isv6) ||
1889 1888 (sctp->sctp_connp->conn_ipv6_v6only &&
1890 1889 !sctp_ipif->sctp_ipif_isv6)) {
1891 1890 rw_exit(&sctp_ipif->sctp_ipif_lock);
1892 1891 sctp_ipif = list_next(
1893 1892 &sctps->sctps_g_ipifs[cnt].sctp_ipif_list,
1894 1893 sctp_ipif);
1895 1894 continue;
1896 1895 }
1897 1896 rw_exit(&sctp_ipif->sctp_ipif_lock);
1898 1897 if (connp->conn_family == AF_INET) {
1899 1898 s4 = (struct sockaddr_in *)p;
1900 1899 IN6_V4MAPPED_TO_INADDR(&addr, &s4->sin_addr);
1901 1900 s4->sin_family = AF_INET;
1902 1901 p += sizeof (*s4);
1903 1902 } else {
1904 1903 s6 = (struct sockaddr_in6 *)p;
1905 1904 s6->sin6_addr = addr;
1906 1905 s6->sin6_family = AF_INET6;
1907 1906 s6->sin6_scope_id =
1908 1907 sctp_ipif->sctp_ipif_ill->sctp_ill_index;
1909 1908 p += sizeof (*s6);
1910 1909 }
1911 1910 (*addrcnt)++;
1912 1911 sctp_ipif = list_next(
1913 1912 &sctps->sctps_g_ipifs[cnt].sctp_ipif_list,
1914 1913 sctp_ipif);
1915 1914 }
1916 1915 }
1917 1916 rw_exit(&sctps->sctps_g_ipifs_lock);
1918 1917 return (err);
1919 1918 }
1920 1919
1921 1920 /*
1922 1921 * Get a list of addresses from the source address list. The caller is
1923 1922 * responsible for allocating sufficient buffer for this.
1924 1923 */
1925 1924 void
1926 1925 sctp_get_saddr_list(sctp_t *sctp, uchar_t *p, size_t psize)
1927 1926 {
1928 1927 int cnt;
1929 1928 int icnt;
1930 1929 sctp_saddr_ipif_t *obj;
1931 1930 int naddr;
1932 1931 int scanned = 0;
1933 1932
1934 1933 for (cnt = 0; cnt < SCTP_IPIF_HASH; cnt++) {
1935 1934 rw_enter(&sctp->sctp_saddrs[cnt].ipif_hash_lock, RW_READER);
1936 1935 if (sctp->sctp_saddrs[cnt].ipif_count == 0) {
1937 1936 rw_exit(&sctp->sctp_saddrs[cnt].ipif_hash_lock);
1938 1937 continue;
1939 1938 }
1940 1939 obj = list_head(&sctp->sctp_saddrs[cnt].sctp_ipif_list);
1941 1940 naddr = sctp->sctp_saddrs[cnt].ipif_count;
1942 1941 for (icnt = 0; icnt < naddr; icnt++) {
1943 1942 sctp_ipif_t *ipif;
1944 1943
1945 1944 if (psize < sizeof (ipif->sctp_ipif_saddr)) {
1946 1945 rw_exit(&sctp->sctp_saddrs[cnt].ipif_hash_lock);
1947 1946 return;
1948 1947 }
1949 1948
1950 1949 scanned++;
1951 1950 ipif = obj->saddr_ipifp;
1952 1951 bcopy(&ipif->sctp_ipif_saddr, p,
1953 1952 sizeof (ipif->sctp_ipif_saddr));
1954 1953 p += sizeof (ipif->sctp_ipif_saddr);
1955 1954 psize -= sizeof (ipif->sctp_ipif_saddr);
1956 1955 if (scanned >= sctp->sctp_nsaddrs) {
1957 1956 rw_exit(&sctp->sctp_saddrs[cnt].ipif_hash_lock);
1958 1957 return;
1959 1958 }
1960 1959 obj = list_next(
1961 1960 &sctp->sctp_saddrs[icnt].sctp_ipif_list,
1962 1961 obj);
1963 1962 }
1964 1963 rw_exit(&sctp->sctp_saddrs[cnt].ipif_hash_lock);
1965 1964 }
1966 1965 }
1967 1966
1968 1967 /*
1969 1968 * Get a list of addresses from the remote address list. The caller is
1970 1969 * responsible for allocating sufficient buffer for this.
1971 1970 */
1972 1971 void
1973 1972 sctp_get_faddr_list(sctp_t *sctp, uchar_t *p, size_t psize)
1974 1973 {
1975 1974 sctp_faddr_t *fp;
1976 1975
1977 1976 for (fp = sctp->sctp_faddrs; fp != NULL; fp = fp->sf_next) {
1978 1977 if (psize < sizeof (fp->sf_faddr))
1979 1978 return;
1980 1979 bcopy(&fp->sf_faddr, p, sizeof (fp->sf_faddr));
1981 1980 p += sizeof (fp->sf_faddr);
1982 1981 psize -= sizeof (fp->sf_faddr);
1983 1982 }
1984 1983 }
1985 1984
1986 1985 static void
1987 1986 sctp_free_ills(sctp_stack_t *sctps)
1988 1987 {
1989 1988 int i;
1990 1989 int l;
1991 1990 sctp_ill_t *sctp_ill;
1992 1991
1993 1992 if (sctps->sctps_ills_count == 0)
1994 1993 return;
1995 1994
1996 1995 for (i = 0; i < SCTP_ILL_HASH; i++) {
1997 1996 sctp_ill = list_tail(&sctps->sctps_g_ills[i].sctp_ill_list);
1998 1997 for (l = 0; l < sctps->sctps_g_ills[i].ill_count; l++) {
1999 1998 ASSERT(sctp_ill->sctp_ill_ipifcnt == 0);
2000 1999 list_remove(&sctps->sctps_g_ills[i].sctp_ill_list,
2001 2000 sctp_ill);
2002 2001 sctps->sctps_ills_count--;
2003 2002 kmem_free(sctp_ill->sctp_ill_name,
2004 2003 sctp_ill->sctp_ill_name_length);
2005 2004 kmem_free(sctp_ill, sizeof (sctp_ill_t));
2006 2005 sctp_ill =
2007 2006 list_tail(&sctps->sctps_g_ills[i].sctp_ill_list);
2008 2007 }
2009 2008 sctps->sctps_g_ills[i].ill_count = 0;
2010 2009 }
2011 2010 ASSERT(sctps->sctps_ills_count == 0);
2012 2011 }
2013 2012
2014 2013 static void
2015 2014 sctp_free_ipifs(sctp_stack_t *sctps)
2016 2015 {
2017 2016 int i;
2018 2017 int l;
2019 2018 sctp_ipif_t *sctp_ipif;
2020 2019 sctp_ill_t *sctp_ill;
2021 2020
2022 2021 if (sctps->sctps_g_ipifs_count == 0)
↓ open down ↓ |
799 lines elided |
↑ open up ↑ |
2023 2022 return;
2024 2023
2025 2024 for (i = 0; i < SCTP_IPIF_HASH; i++) {
2026 2025 sctp_ipif = list_tail(&sctps->sctps_g_ipifs[i].sctp_ipif_list);
2027 2026 for (l = 0; l < sctps->sctps_g_ipifs[i].ipif_count; l++) {
2028 2027 sctp_ill = sctp_ipif->sctp_ipif_ill;
2029 2028
2030 2029 list_remove(&sctps->sctps_g_ipifs[i].sctp_ipif_list,
2031 2030 sctp_ipif);
2032 2031 sctps->sctps_g_ipifs_count--;
2033 - (void) atomic_add_32_nv(&sctp_ill->sctp_ill_ipifcnt,
2034 - -1);
2032 + (void) atomic_dec_32_nv(&sctp_ill->sctp_ill_ipifcnt);
2035 2033 kmem_free(sctp_ipif, sizeof (sctp_ipif_t));
2036 2034 sctp_ipif =
2037 2035 list_tail(&sctps->sctps_g_ipifs[i].sctp_ipif_list);
2038 2036 }
2039 2037 sctps->sctps_g_ipifs[i].ipif_count = 0;
2040 2038 }
2041 2039 ASSERT(sctps->sctps_g_ipifs_count == 0);
2042 2040 }
2043 2041
2044 2042
2045 2043 /* Initialize the SCTP ILL list and lock */
2046 2044 void
2047 2045 sctp_saddr_init(sctp_stack_t *sctps)
2048 2046 {
2049 2047 int i;
2050 2048
2051 2049 sctps->sctps_g_ills = kmem_zalloc(sizeof (sctp_ill_hash_t) *
2052 2050 SCTP_ILL_HASH, KM_SLEEP);
2053 2051 sctps->sctps_g_ipifs = kmem_zalloc(sizeof (sctp_ipif_hash_t) *
2054 2052 SCTP_IPIF_HASH, KM_SLEEP);
2055 2053
2056 2054 rw_init(&sctps->sctps_g_ills_lock, NULL, RW_DEFAULT, NULL);
2057 2055 rw_init(&sctps->sctps_g_ipifs_lock, NULL, RW_DEFAULT, NULL);
2058 2056
2059 2057 for (i = 0; i < SCTP_ILL_HASH; i++) {
2060 2058 sctps->sctps_g_ills[i].ill_count = 0;
2061 2059 list_create(&sctps->sctps_g_ills[i].sctp_ill_list,
2062 2060 sizeof (sctp_ill_t),
2063 2061 offsetof(sctp_ill_t, sctp_ills));
2064 2062 }
2065 2063 for (i = 0; i < SCTP_IPIF_HASH; i++) {
2066 2064 sctps->sctps_g_ipifs[i].ipif_count = 0;
2067 2065 list_create(&sctps->sctps_g_ipifs[i].sctp_ipif_list,
2068 2066 sizeof (sctp_ipif_t), offsetof(sctp_ipif_t, sctp_ipifs));
2069 2067 }
2070 2068 }
2071 2069
2072 2070 void
2073 2071 sctp_saddr_fini(sctp_stack_t *sctps)
2074 2072 {
2075 2073 int i;
2076 2074
2077 2075 sctp_free_ipifs(sctps);
2078 2076 sctp_free_ills(sctps);
2079 2077
2080 2078 for (i = 0; i < SCTP_ILL_HASH; i++)
2081 2079 list_destroy(&sctps->sctps_g_ills[i].sctp_ill_list);
2082 2080 for (i = 0; i < SCTP_IPIF_HASH; i++)
2083 2081 list_destroy(&sctps->sctps_g_ipifs[i].sctp_ipif_list);
2084 2082
2085 2083 ASSERT(sctps->sctps_ills_count == 0 && sctps->sctps_g_ipifs_count == 0);
2086 2084 kmem_free(sctps->sctps_g_ills, sizeof (sctp_ill_hash_t) *
2087 2085 SCTP_ILL_HASH);
2088 2086 sctps->sctps_g_ills = NULL;
2089 2087 kmem_free(sctps->sctps_g_ipifs, sizeof (sctp_ipif_hash_t) *
2090 2088 SCTP_IPIF_HASH);
2091 2089 sctps->sctps_g_ipifs = NULL;
2092 2090 rw_destroy(&sctps->sctps_g_ills_lock);
2093 2091 rw_destroy(&sctps->sctps_g_ipifs_lock);
2094 2092 }
↓ open down ↓ |
50 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX