1 /*-
2 * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved.
3 * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
4 * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * a) Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
11 *
12 * b) Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the distribution.
15 *
16 * c) Neither the name of Cisco Systems, Inc. nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
30 * THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 #ifdef __FreeBSD__
34 #include <sys/cdefs.h>
35 __FBSDID("$FreeBSD: head/sys/netinet/sctp_asconf.c 257803 2013-11-07 17:08:09Z tuexen $");
36 #endif
37
38 #include <netinet/sctp_os.h>
39 #include <netinet/sctp_var.h>
40 #include <netinet/sctp_sysctl.h>
41 #include <netinet/sctp_pcb.h>
42 #include <netinet/sctp_header.h>
43 #include <netinet/sctputil.h>
44 #include <netinet/sctp_output.h>
45 #include <netinet/sctp_asconf.h>
46 #include <netinet/sctp_timer.h>
47
48 /*
49 * debug flags:
50 * SCTP_DEBUG_ASCONF1: protocol info, general info and errors
51 * SCTP_DEBUG_ASCONF2: detailed info
52 */
53
54 #if defined(__APPLE__)
55 #define APPLE_FILE_NO 1
56 #endif
57
58 /*
59 * RFC 5061
60 *
61 * An ASCONF parameter queue exists per asoc which holds the pending address
62 * operations. Lists are updated upon receipt of ASCONF-ACK.
63 *
64 * A restricted_addrs list exists per assoc to hold local addresses that are
65 * not (yet) usable by the assoc as a source address. These addresses are
66 * either pending an ASCONF operation (and exist on the ASCONF parameter
67 * queue), or they are permanently restricted (the peer has returned an
68 * ERROR indication to an ASCONF(ADD), or the peer does not support ASCONF).
69 *
70 * Deleted addresses are always immediately removed from the lists as they will
71 * (shortly) no longer exist in the kernel. We send ASCONFs as a courtesy,
72 * only if allowed.
73 */
74
75 /*
76 * ASCONF parameter processing.
77 * response_required: set if a reply is required (eg. SUCCESS_REPORT).
78 * returns a mbuf to an "error" response parameter or NULL/"success" if ok.
79 * FIX: allocating this many mbufs on the fly is pretty inefficient...
80 */
81 static struct mbuf *
sctp_asconf_success_response(uint32_t id)82 sctp_asconf_success_response(uint32_t id)
83 {
84 struct mbuf *m_reply = NULL;
85 struct sctp_asconf_paramhdr *aph;
86
87 m_reply = sctp_get_mbuf_for_msg(sizeof(struct sctp_asconf_paramhdr),
88 0, M_NOWAIT, 1, MT_DATA);
89 if (m_reply == NULL) {
90 SCTPDBG(SCTP_DEBUG_ASCONF1,
91 "asconf_success_response: couldn't get mbuf!\n");
92 return (NULL);
93 }
94 aph = mtod(m_reply, struct sctp_asconf_paramhdr *);
95 aph->correlation_id = id;
96 aph->ph.param_type = htons(SCTP_SUCCESS_REPORT);
97 aph->ph.param_length = sizeof(struct sctp_asconf_paramhdr);
98 SCTP_BUF_LEN(m_reply) = aph->ph.param_length;
99 aph->ph.param_length = htons(aph->ph.param_length);
100
101 return (m_reply);
102 }
103
104 static struct mbuf *
sctp_asconf_error_response(uint32_t id,uint16_t cause,uint8_t * error_tlv,uint16_t tlv_length)105 sctp_asconf_error_response(uint32_t id, uint16_t cause, uint8_t *error_tlv,
106 uint16_t tlv_length)
107 {
108 struct mbuf *m_reply = NULL;
109 struct sctp_asconf_paramhdr *aph;
110 struct sctp_error_cause *error;
111 uint8_t *tlv;
112
113 m_reply = sctp_get_mbuf_for_msg((sizeof(struct sctp_asconf_paramhdr) +
114 tlv_length +
115 sizeof(struct sctp_error_cause)),
116 0, M_NOWAIT, 1, MT_DATA);
117 if (m_reply == NULL) {
118 SCTPDBG(SCTP_DEBUG_ASCONF1,
119 "asconf_error_response: couldn't get mbuf!\n");
120 return (NULL);
121 }
122 aph = mtod(m_reply, struct sctp_asconf_paramhdr *);
123 error = (struct sctp_error_cause *)(aph + 1);
124
125 aph->correlation_id = id;
126 aph->ph.param_type = htons(SCTP_ERROR_CAUSE_IND);
127 error->code = htons(cause);
128 error->length = tlv_length + sizeof(struct sctp_error_cause);
129 aph->ph.param_length = error->length +
130 sizeof(struct sctp_asconf_paramhdr);
131
132 if (aph->ph.param_length > MLEN) {
133 SCTPDBG(SCTP_DEBUG_ASCONF1,
134 "asconf_error_response: tlv_length (%xh) too big\n",
135 tlv_length);
136 sctp_m_freem(m_reply); /* discard */
137 return (NULL);
138 }
139 if (error_tlv != NULL) {
140 tlv = (uint8_t *) (error + 1);
141 memcpy(tlv, error_tlv, tlv_length);
142 }
143 SCTP_BUF_LEN(m_reply) = aph->ph.param_length;
144 error->length = htons(error->length);
145 aph->ph.param_length = htons(aph->ph.param_length);
146
147 return (m_reply);
148 }
149
150 static struct mbuf *
sctp_process_asconf_add_ip(struct sockaddr * src,struct sctp_asconf_paramhdr * aph,struct sctp_tcb * stcb,int send_hb,int response_required)151 sctp_process_asconf_add_ip(struct sockaddr *src, struct sctp_asconf_paramhdr *aph,
152 struct sctp_tcb *stcb, int send_hb, int response_required)
153 {
154 struct sctp_nets *net;
155 struct mbuf *m_reply = NULL;
156 struct sockaddr_storage sa_store;
157 struct sctp_paramhdr *ph;
158 uint16_t param_type, aparam_length;
159 #if defined(INET) || defined(INET6)
160 uint16_t param_length;
161 #endif
162 struct sockaddr *sa;
163 int zero_address = 0;
164 int bad_address = 0;
165 #ifdef INET
166 struct sockaddr_in *sin;
167 struct sctp_ipv4addr_param *v4addr;
168 #endif
169 #ifdef INET6
170 struct sockaddr_in6 *sin6;
171 struct sctp_ipv6addr_param *v6addr;
172 #endif
173
174 aparam_length = ntohs(aph->ph.param_length);
175 ph = (struct sctp_paramhdr *)(aph + 1);
176 param_type = ntohs(ph->param_type);
177 #if defined(INET) || defined(INET6)
178 param_length = ntohs(ph->param_length);
179 #endif
180 sa = (struct sockaddr *)&sa_store;
181 switch (param_type) {
182 #ifdef INET
183 case SCTP_IPV4_ADDRESS:
184 if (param_length != sizeof(struct sctp_ipv4addr_param)) {
185 /* invalid param size */
186 return (NULL);
187 }
188 v4addr = (struct sctp_ipv4addr_param *)ph;
189 sin = (struct sockaddr_in *)&sa_store;
190 bzero(sin, sizeof(*sin));
191 sin->sin_family = AF_INET;
192 #ifdef HAVE_SIN_LEN
193 sin->sin_len = sizeof(struct sockaddr_in);
194 #endif
195 sin->sin_port = stcb->rport;
196 sin->sin_addr.s_addr = v4addr->addr;
197 if ((sin->sin_addr.s_addr == INADDR_BROADCAST) ||
198 IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) {
199 bad_address = 1;
200 }
201 if (sin->sin_addr.s_addr == INADDR_ANY)
202 zero_address = 1;
203 SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_add_ip: adding ");
204 SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa);
205 break;
206 #endif
207 #ifdef INET6
208 case SCTP_IPV6_ADDRESS:
209 if (param_length != sizeof(struct sctp_ipv6addr_param)) {
210 /* invalid param size */
211 return (NULL);
212 }
213 v6addr = (struct sctp_ipv6addr_param *)ph;
214 sin6 = (struct sockaddr_in6 *)&sa_store;
215 bzero(sin6, sizeof(*sin6));
216 sin6->sin6_family = AF_INET6;
217 #ifdef HAVE_SIN6_LEN
218 sin6->sin6_len = sizeof(struct sockaddr_in6);
219 #endif
220 sin6->sin6_port = stcb->rport;
221 memcpy((caddr_t)&sin6->sin6_addr, v6addr->addr,
222 sizeof(struct in6_addr));
223 if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) {
224 bad_address = 1;
225 }
226 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))
227 zero_address = 1;
228 SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_add_ip: adding ");
229 SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa);
230 break;
231 #endif
232 default:
233 m_reply = sctp_asconf_error_response(aph->correlation_id,
234 SCTP_CAUSE_INVALID_PARAM, (uint8_t *) aph,
235 aparam_length);
236 return (m_reply);
237 } /* end switch */
238
239 /* if 0.0.0.0/::0, add the source address instead */
240 if (zero_address && SCTP_BASE_SYSCTL(sctp_nat_friendly)) {
241 sa = src;
242 SCTPDBG(SCTP_DEBUG_ASCONF1,
243 "process_asconf_add_ip: using source addr ");
244 SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, src);
245 }
246 /* add the address */
247 if (bad_address) {
248 m_reply = sctp_asconf_error_response(aph->correlation_id,
249 SCTP_CAUSE_INVALID_PARAM, (uint8_t *) aph,
250 aparam_length);
251 } else if (sctp_add_remote_addr(stcb, sa, &net, SCTP_DONOT_SETSCOPE,
252 SCTP_ADDR_DYNAMIC_ADDED) != 0) {
253 SCTPDBG(SCTP_DEBUG_ASCONF1,
254 "process_asconf_add_ip: error adding address\n");
255 m_reply = sctp_asconf_error_response(aph->correlation_id,
256 SCTP_CAUSE_RESOURCE_SHORTAGE, (uint8_t *) aph,
257 aparam_length);
258 } else {
259 /* notify upper layer */
260 sctp_ulp_notify(SCTP_NOTIFY_ASCONF_ADD_IP, stcb, 0, sa, SCTP_SO_NOT_LOCKED);
261 if (response_required) {
262 m_reply =
263 sctp_asconf_success_response(aph->correlation_id);
264 }
265 sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, stcb->sctp_ep, stcb, net);
266 sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep,
267 stcb, net);
268 if (send_hb) {
269 sctp_send_hb(stcb, net, SCTP_SO_NOT_LOCKED);
270 }
271 }
272 return (m_reply);
273 }
274
275 static int
sctp_asconf_del_remote_addrs_except(struct sctp_tcb * stcb,struct sockaddr * src)276 sctp_asconf_del_remote_addrs_except(struct sctp_tcb *stcb, struct sockaddr *src)
277 {
278 struct sctp_nets *src_net, *net;
279
280 /* make sure the source address exists as a destination net */
281 src_net = sctp_findnet(stcb, src);
282 if (src_net == NULL) {
283 /* not found */
284 return (-1);
285 }
286
287 /* delete all destination addresses except the source */
288 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
289 if (net != src_net) {
290 /* delete this address */
291 sctp_remove_net(stcb, net);
292 SCTPDBG(SCTP_DEBUG_ASCONF1,
293 "asconf_del_remote_addrs_except: deleting ");
294 SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1,
295 (struct sockaddr *)&net->ro._l_addr);
296 /* notify upper layer */
297 sctp_ulp_notify(SCTP_NOTIFY_ASCONF_DELETE_IP, stcb, 0,
298 (struct sockaddr *)&net->ro._l_addr, SCTP_SO_NOT_LOCKED);
299 }
300 }
301 return (0);
302 }
303
304 static struct mbuf *
sctp_process_asconf_delete_ip(struct sockaddr * src,struct sctp_asconf_paramhdr * aph,struct sctp_tcb * stcb,int response_required)305 sctp_process_asconf_delete_ip(struct sockaddr *src,
306 struct sctp_asconf_paramhdr *aph,
307 struct sctp_tcb *stcb, int response_required)
308 {
309 struct mbuf *m_reply = NULL;
310 struct sockaddr_storage sa_store;
311 struct sctp_paramhdr *ph;
312 uint16_t param_type, aparam_length;
313 #if defined(INET) || defined(INET6)
314 uint16_t param_length;
315 #endif
316 struct sockaddr *sa;
317 int zero_address = 0;
318 int result;
319 #ifdef INET
320 struct sockaddr_in *sin;
321 struct sctp_ipv4addr_param *v4addr;
322 #endif
323 #ifdef INET6
324 struct sockaddr_in6 *sin6;
325 struct sctp_ipv6addr_param *v6addr;
326 #endif
327
328 aparam_length = ntohs(aph->ph.param_length);
329 ph = (struct sctp_paramhdr *)(aph + 1);
330 param_type = ntohs(ph->param_type);
331 #if defined(INET) || defined(INET6)
332 param_length = ntohs(ph->param_length);
333 #endif
334 sa = (struct sockaddr *)&sa_store;
335 switch (param_type) {
336 #ifdef INET
337 case SCTP_IPV4_ADDRESS:
338 if (param_length != sizeof(struct sctp_ipv4addr_param)) {
339 /* invalid param size */
340 return (NULL);
341 }
342 v4addr = (struct sctp_ipv4addr_param *)ph;
343 sin = (struct sockaddr_in *)&sa_store;
344 bzero(sin, sizeof(*sin));
345 sin->sin_family = AF_INET;
346 #ifdef HAVE_SIN_LEN
347 sin->sin_len = sizeof(struct sockaddr_in);
348 #endif
349 sin->sin_port = stcb->rport;
350 sin->sin_addr.s_addr = v4addr->addr;
351 if (sin->sin_addr.s_addr == INADDR_ANY)
352 zero_address = 1;
353 SCTPDBG(SCTP_DEBUG_ASCONF1,
354 "process_asconf_delete_ip: deleting ");
355 SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa);
356 break;
357 #endif
358 #ifdef INET6
359 case SCTP_IPV6_ADDRESS:
360 if (param_length != sizeof(struct sctp_ipv6addr_param)) {
361 /* invalid param size */
362 return (NULL);
363 }
364 v6addr = (struct sctp_ipv6addr_param *)ph;
365 sin6 = (struct sockaddr_in6 *)&sa_store;
366 bzero(sin6, sizeof(*sin6));
367 sin6->sin6_family = AF_INET6;
368 #ifdef HAVE_SIN6_LEN
369 sin6->sin6_len = sizeof(struct sockaddr_in6);
370 #endif
371 sin6->sin6_port = stcb->rport;
372 memcpy(&sin6->sin6_addr, v6addr->addr,
373 sizeof(struct in6_addr));
374 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))
375 zero_address = 1;
376 SCTPDBG(SCTP_DEBUG_ASCONF1,
377 "process_asconf_delete_ip: deleting ");
378 SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa);
379 break;
380 #endif
381 default:
382 m_reply = sctp_asconf_error_response(aph->correlation_id,
383 SCTP_CAUSE_UNRESOLVABLE_ADDR, (uint8_t *) aph,
384 aparam_length);
385 return (m_reply);
386 }
387
388 /* make sure the source address is not being deleted */
389 if (sctp_cmpaddr(sa, src)) {
390 /* trying to delete the source address! */
391 SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_delete_ip: tried to delete source addr\n");
392 m_reply = sctp_asconf_error_response(aph->correlation_id,
393 SCTP_CAUSE_DELETING_SRC_ADDR, (uint8_t *) aph,
394 aparam_length);
395 return (m_reply);
396 }
397
398 /* if deleting 0.0.0.0/::0, delete all addresses except src addr */
399 if (zero_address && SCTP_BASE_SYSCTL(sctp_nat_friendly)) {
400 result = sctp_asconf_del_remote_addrs_except(stcb, src);
401
402 if (result) {
403 /* src address did not exist? */
404 SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_delete_ip: src addr does not exist?\n");
405 /* what error to reply with?? */
406 m_reply =
407 sctp_asconf_error_response(aph->correlation_id,
408 SCTP_CAUSE_REQUEST_REFUSED, (uint8_t *) aph,
409 aparam_length);
410 } else if (response_required) {
411 m_reply =
412 sctp_asconf_success_response(aph->correlation_id);
413 }
414 return (m_reply);
415 }
416
417 /* delete the address */
418 result = sctp_del_remote_addr(stcb, sa);
419 /*
420 * note if result == -2, the address doesn't exist in the asoc but
421 * since it's being deleted anyways, we just ack the delete -- but
422 * this probably means something has already gone awry
423 */
424 if (result == -1) {
425 /* only one address in the asoc */
426 SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_delete_ip: tried to delete last IP addr!\n");
427 m_reply = sctp_asconf_error_response(aph->correlation_id,
428 SCTP_CAUSE_DELETING_LAST_ADDR, (uint8_t *) aph,
429 aparam_length);
430 } else {
431 if (response_required) {
432 m_reply = sctp_asconf_success_response(aph->correlation_id);
433 }
434 /* notify upper layer */
435 sctp_ulp_notify(SCTP_NOTIFY_ASCONF_DELETE_IP, stcb, 0, sa, SCTP_SO_NOT_LOCKED);
436 }
437 return (m_reply);
438 }
439
440 static struct mbuf *
sctp_process_asconf_set_primary(struct sockaddr * src,struct sctp_asconf_paramhdr * aph,struct sctp_tcb * stcb,int response_required)441 sctp_process_asconf_set_primary(struct sockaddr *src,
442 struct sctp_asconf_paramhdr *aph,
443 struct sctp_tcb *stcb, int response_required)
444 {
445 struct mbuf *m_reply = NULL;
446 struct sockaddr_storage sa_store;
447 struct sctp_paramhdr *ph;
448 uint16_t param_type, aparam_length;
449 #if defined(INET) || defined(INET6)
450 uint16_t param_length;
451 #endif
452 struct sockaddr *sa;
453 int zero_address = 0;
454 #ifdef INET
455 struct sockaddr_in *sin;
456 struct sctp_ipv4addr_param *v4addr;
457 #endif
458 #ifdef INET6
459 struct sockaddr_in6 *sin6;
460 struct sctp_ipv6addr_param *v6addr;
461 #endif
462
463 aparam_length = ntohs(aph->ph.param_length);
464 ph = (struct sctp_paramhdr *)(aph + 1);
465 param_type = ntohs(ph->param_type);
466 #if defined(INET) || defined(INET6)
467 param_length = ntohs(ph->param_length);
468 #endif
469 sa = (struct sockaddr *)&sa_store;
470 switch (param_type) {
471 #ifdef INET
472 case SCTP_IPV4_ADDRESS:
473 if (param_length != sizeof(struct sctp_ipv4addr_param)) {
474 /* invalid param size */
475 return (NULL);
476 }
477 v4addr = (struct sctp_ipv4addr_param *)ph;
478 sin = (struct sockaddr_in *)&sa_store;
479 bzero(sin, sizeof(*sin));
480 sin->sin_family = AF_INET;
481 #ifdef HAVE_SIN_LEN
482 sin->sin_len = sizeof(struct sockaddr_in);
483 #endif
484 sin->sin_addr.s_addr = v4addr->addr;
485 if (sin->sin_addr.s_addr == INADDR_ANY)
486 zero_address = 1;
487 SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_set_primary: ");
488 SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa);
489 break;
490 #endif
491 #ifdef INET6
492 case SCTP_IPV6_ADDRESS:
493 if (param_length != sizeof(struct sctp_ipv6addr_param)) {
494 /* invalid param size */
495 return (NULL);
496 }
497 v6addr = (struct sctp_ipv6addr_param *)ph;
498 sin6 = (struct sockaddr_in6 *)&sa_store;
499 bzero(sin6, sizeof(*sin6));
500 sin6->sin6_family = AF_INET6;
501 #ifdef HAVE_SIN6_LEN
502 sin6->sin6_len = sizeof(struct sockaddr_in6);
503 #endif
504 memcpy((caddr_t)&sin6->sin6_addr, v6addr->addr,
505 sizeof(struct in6_addr));
506 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))
507 zero_address = 1;
508 SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_set_primary: ");
509 SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa);
510 break;
511 #endif
512 default:
513 m_reply = sctp_asconf_error_response(aph->correlation_id,
514 SCTP_CAUSE_UNRESOLVABLE_ADDR, (uint8_t *) aph,
515 aparam_length);
516 return (m_reply);
517 }
518
519 /* if 0.0.0.0/::0, use the source address instead */
520 if (zero_address && SCTP_BASE_SYSCTL(sctp_nat_friendly)) {
521 sa = src;
522 SCTPDBG(SCTP_DEBUG_ASCONF1,
523 "process_asconf_set_primary: using source addr ");
524 SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, src);
525 }
526 /* set the primary address */
527 if (sctp_set_primary_addr(stcb, sa, NULL) == 0) {
528 SCTPDBG(SCTP_DEBUG_ASCONF1,
529 "process_asconf_set_primary: primary address set\n");
530 /* notify upper layer */
531 sctp_ulp_notify(SCTP_NOTIFY_ASCONF_SET_PRIMARY, stcb, 0, sa, SCTP_SO_NOT_LOCKED);
532 if ((stcb->asoc.primary_destination->dest_state & SCTP_ADDR_REACHABLE) &&
533 (!(stcb->asoc.primary_destination->dest_state & SCTP_ADDR_PF)) &&
534 (stcb->asoc.alternate)) {
535 sctp_free_remote_addr(stcb->asoc.alternate);
536 stcb->asoc.alternate = NULL;
537 }
538 if (response_required) {
539 m_reply = sctp_asconf_success_response(aph->correlation_id);
540 }
541 /* Mobility adaptation.
542 Ideally, when the reception of SET PRIMARY with DELETE IP
543 ADDRESS of the previous primary destination, unacknowledged
544 DATA are retransmitted immediately to the new primary
545 destination for seamless handover.
546 If the destination is UNCONFIRMED and marked to REQ_PRIM,
547 The retransmission occur when reception of the
548 HEARTBEAT-ACK. (See sctp_handle_heartbeat_ack in
549 sctp_input.c)
550 Also, when change of the primary destination, it is better
551 that all subsequent new DATA containing already queued DATA
552 are transmitted to the new primary destination. (by micchie)
553 */
554 if ((sctp_is_mobility_feature_on(stcb->sctp_ep,
555 SCTP_MOBILITY_BASE) ||
556 sctp_is_mobility_feature_on(stcb->sctp_ep,
557 SCTP_MOBILITY_FASTHANDOFF)) &&
558 sctp_is_mobility_feature_on(stcb->sctp_ep,
559 SCTP_MOBILITY_PRIM_DELETED) &&
560 (stcb->asoc.primary_destination->dest_state &
561 SCTP_ADDR_UNCONFIRMED) == 0) {
562
563 sctp_timer_stop(SCTP_TIMER_TYPE_PRIM_DELETED, stcb->sctp_ep, stcb, NULL, SCTP_FROM_SCTP_TIMER+SCTP_LOC_7);
564 if (sctp_is_mobility_feature_on(stcb->sctp_ep,
565 SCTP_MOBILITY_FASTHANDOFF)) {
566 sctp_assoc_immediate_retrans(stcb,
567 stcb->asoc.primary_destination);
568 }
569 if (sctp_is_mobility_feature_on(stcb->sctp_ep,
570 SCTP_MOBILITY_BASE)) {
571 sctp_move_chunks_from_net(stcb,
572 stcb->asoc.deleted_primary);
573 }
574 sctp_delete_prim_timer(stcb->sctp_ep, stcb,
575 stcb->asoc.deleted_primary);
576 }
577 } else {
578 /* couldn't set the requested primary address! */
579 SCTPDBG(SCTP_DEBUG_ASCONF1,
580 "process_asconf_set_primary: set primary failed!\n");
581 /* must have been an invalid address, so report */
582 m_reply = sctp_asconf_error_response(aph->correlation_id,
583 SCTP_CAUSE_UNRESOLVABLE_ADDR, (uint8_t *) aph,
584 aparam_length);
585 }
586
587 return (m_reply);
588 }
589
590 /*
591 * handles an ASCONF chunk.
592 * if all parameters are processed ok, send a plain (empty) ASCONF-ACK
593 */
594 void
sctp_handle_asconf(struct mbuf * m,unsigned int offset,struct sockaddr * src,struct sctp_asconf_chunk * cp,struct sctp_tcb * stcb,int first)595 sctp_handle_asconf(struct mbuf *m, unsigned int offset,
596 struct sockaddr *src,
597 struct sctp_asconf_chunk *cp, struct sctp_tcb *stcb,
598 int first)
599 {
600 struct sctp_association *asoc;
601 uint32_t serial_num;
602 struct mbuf *n, *m_ack, *m_result, *m_tail;
603 struct sctp_asconf_ack_chunk *ack_cp;
604 struct sctp_asconf_paramhdr *aph, *ack_aph;
605 struct sctp_ipv6addr_param *p_addr;
606 unsigned int asconf_limit, cnt;
607 int error = 0; /* did an error occur? */
608
609 /* asconf param buffer */
610 uint8_t aparam_buf[SCTP_PARAM_BUFFER_SIZE];
611 struct sctp_asconf_ack *ack, *ack_next;
612
613 /* verify minimum length */
614 if (ntohs(cp->ch.chunk_length) < sizeof(struct sctp_asconf_chunk)) {
615 SCTPDBG(SCTP_DEBUG_ASCONF1,
616 "handle_asconf: chunk too small = %xh\n",
617 ntohs(cp->ch.chunk_length));
618 return;
619 }
620 asoc = &stcb->asoc;
621 serial_num = ntohl(cp->serial_number);
622
623 if (SCTP_TSN_GE(asoc->asconf_seq_in, serial_num)) {
624 /* got a duplicate ASCONF */
625 SCTPDBG(SCTP_DEBUG_ASCONF1,
626 "handle_asconf: got duplicate serial number = %xh\n",
627 serial_num);
628 return;
629 } else if (serial_num != (asoc->asconf_seq_in + 1)) {
630 SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: incorrect serial number = %xh (expected next = %xh)\n",
631 serial_num, asoc->asconf_seq_in + 1);
632 return;
633 }
634
635 /* it's the expected "next" sequence number, so process it */
636 asoc->asconf_seq_in = serial_num; /* update sequence */
637 /* get length of all the param's in the ASCONF */
638 asconf_limit = offset + ntohs(cp->ch.chunk_length);
639 SCTPDBG(SCTP_DEBUG_ASCONF1,
640 "handle_asconf: asconf_limit=%u, sequence=%xh\n",
641 asconf_limit, serial_num);
642
643 if (first) {
644 /* delete old cache */
645 SCTPDBG(SCTP_DEBUG_ASCONF1,"handle_asconf: Now processing first ASCONF. Try to delete old cache\n");
646
647 TAILQ_FOREACH_SAFE(ack, &asoc->asconf_ack_sent, next, ack_next) {
648 if (ack->serial_number == serial_num)
649 break;
650 SCTPDBG(SCTP_DEBUG_ASCONF1,"handle_asconf: delete old(%u) < first(%u)\n",
651 ack->serial_number, serial_num);
652 TAILQ_REMOVE(&asoc->asconf_ack_sent, ack, next);
653 if (ack->data != NULL) {
654 sctp_m_freem(ack->data);
655 }
656 SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_asconf_ack), ack);
657 }
658 }
659
660 m_ack = sctp_get_mbuf_for_msg(sizeof(struct sctp_asconf_ack_chunk), 0,
661 M_NOWAIT, 1, MT_DATA);
662 if (m_ack == NULL) {
663 SCTPDBG(SCTP_DEBUG_ASCONF1,
664 "handle_asconf: couldn't get mbuf!\n");
665 return;
666 }
667 m_tail = m_ack; /* current reply chain's tail */
668
669 /* fill in ASCONF-ACK header */
670 ack_cp = mtod(m_ack, struct sctp_asconf_ack_chunk *);
671 ack_cp->ch.chunk_type = SCTP_ASCONF_ACK;
672 ack_cp->ch.chunk_flags = 0;
673 ack_cp->serial_number = htonl(serial_num);
674 /* set initial lengths (eg. just an ASCONF-ACK), ntohx at the end! */
675 SCTP_BUF_LEN(m_ack) = sizeof(struct sctp_asconf_ack_chunk);
676 ack_cp->ch.chunk_length = sizeof(struct sctp_asconf_ack_chunk);
677
678 /* skip the lookup address parameter */
679 offset += sizeof(struct sctp_asconf_chunk);
680 p_addr = (struct sctp_ipv6addr_param *)sctp_m_getptr(m, offset, sizeof(struct sctp_paramhdr), (uint8_t *)&aparam_buf);
681 if (p_addr == NULL) {
682 SCTPDBG(SCTP_DEBUG_ASCONF1,
683 "handle_asconf: couldn't get lookup addr!\n");
684 /* respond with a missing/invalid mandatory parameter error */
685 return;
686 }
687 /* param_length is already validated in process_control... */
688 offset += ntohs(p_addr->ph.param_length); /* skip lookup addr */
689
690 /* get pointer to first asconf param in ASCONF-ACK */
691 ack_aph = (struct sctp_asconf_paramhdr *)(mtod(m_ack, caddr_t) + sizeof(struct sctp_asconf_ack_chunk));
692 if (ack_aph == NULL) {
693 SCTPDBG(SCTP_DEBUG_ASCONF1, "Gak in asconf2\n");
694 return;
695 }
696 /* get pointer to first asconf param in ASCONF */
697 aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(m, offset, sizeof(struct sctp_asconf_paramhdr), (uint8_t *)&aparam_buf);
698 if (aph == NULL) {
699 SCTPDBG(SCTP_DEBUG_ASCONF1, "Empty ASCONF received?\n");
700 goto send_reply;
701 }
702 /* process through all parameters */
703 cnt = 0;
704 while (aph != NULL) {
705 unsigned int param_length, param_type;
706
707 param_type = ntohs(aph->ph.param_type);
708 param_length = ntohs(aph->ph.param_length);
709 if (offset + param_length > asconf_limit) {
710 /* parameter goes beyond end of chunk! */
711 sctp_m_freem(m_ack);
712 return;
713 }
714 m_result = NULL;
715
716 if (param_length > sizeof(aparam_buf)) {
717 SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: param length (%u) larger than buffer size!\n", param_length);
718 sctp_m_freem(m_ack);
719 return;
720 }
721 if (param_length <= sizeof(struct sctp_paramhdr)) {
722 SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: param length (%u) too short\n", param_length);
723 sctp_m_freem(m_ack);
724 }
725 /* get the entire parameter */
726 aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(m, offset, param_length, aparam_buf);
727 if (aph == NULL) {
728 SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: couldn't get entire param\n");
729 sctp_m_freem(m_ack);
730 return;
731 }
732 switch (param_type) {
733 case SCTP_ADD_IP_ADDRESS:
734 asoc->peer_supports_asconf = 1;
735 m_result = sctp_process_asconf_add_ip(src, aph, stcb,
736 (cnt < SCTP_BASE_SYSCTL(sctp_hb_maxburst)), error);
737 cnt++;
738 break;
739 case SCTP_DEL_IP_ADDRESS:
740 asoc->peer_supports_asconf = 1;
741 m_result = sctp_process_asconf_delete_ip(src, aph, stcb,
742 error);
743 break;
744 case SCTP_ERROR_CAUSE_IND:
745 /* not valid in an ASCONF chunk */
746 break;
747 case SCTP_SET_PRIM_ADDR:
748 asoc->peer_supports_asconf = 1;
749 m_result = sctp_process_asconf_set_primary(src, aph,
750 stcb, error);
751 break;
752 case SCTP_NAT_VTAGS:
753 SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: sees a NAT VTAG state parameter\n");
754 break;
755 case SCTP_SUCCESS_REPORT:
756 /* not valid in an ASCONF chunk */
757 break;
758 case SCTP_ULP_ADAPTATION:
759 /* FIX */
760 break;
761 default:
762 if ((param_type & 0x8000) == 0) {
763 /* Been told to STOP at this param */
764 asconf_limit = offset;
765 /*
766 * FIX FIX - We need to call
767 * sctp_arethere_unrecognized_parameters()
768 * to get a operr and send it for any
769 * param's with the 0x4000 bit set OR do it
770 * here ourselves... note we still must STOP
771 * if the 0x8000 bit is clear.
772 */
773 }
774 /* unknown/invalid param type */
775 break;
776 } /* switch */
777
778 /* add any (error) result to the reply mbuf chain */
779 if (m_result != NULL) {
780 SCTP_BUF_NEXT(m_tail) = m_result;
781 m_tail = m_result;
782 /* update lengths, make sure it's aligned too */
783 SCTP_BUF_LEN(m_result) = SCTP_SIZE32(SCTP_BUF_LEN(m_result));
784 ack_cp->ch.chunk_length += SCTP_BUF_LEN(m_result);
785 /* set flag to force success reports */
786 error = 1;
787 }
788 offset += SCTP_SIZE32(param_length);
789 /* update remaining ASCONF message length to process */
790 if (offset >= asconf_limit) {
791 /* no more data in the mbuf chain */
792 break;
793 }
794 /* get pointer to next asconf param */
795 aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(m, offset,
796 sizeof(struct sctp_asconf_paramhdr),
797 (uint8_t *)&aparam_buf);
798 if (aph == NULL) {
799 /* can't get an asconf paramhdr */
800 SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: can't get asconf param hdr!\n");
801 /* FIX ME - add error here... */
802 }
803 }
804
805 send_reply:
806 ack_cp->ch.chunk_length = htons(ack_cp->ch.chunk_length);
807 /* save the ASCONF-ACK reply */
808 ack = SCTP_ZONE_GET(SCTP_BASE_INFO(ipi_zone_asconf_ack),
809 struct sctp_asconf_ack);
810 if (ack == NULL) {
811 sctp_m_freem(m_ack);
812 return;
813 }
814 ack->serial_number = serial_num;
815 ack->last_sent_to = NULL;
816 ack->data = m_ack;
817 ack->len = 0;
818 for (n = m_ack; n != NULL; n = SCTP_BUF_NEXT(n)) {
819 ack->len += SCTP_BUF_LEN(n);
820 }
821 TAILQ_INSERT_TAIL(&stcb->asoc.asconf_ack_sent, ack, next);
822
823 /* see if last_control_chunk_from is set properly (use IP src addr) */
824 if (stcb->asoc.last_control_chunk_from == NULL) {
825 /*
826 * this could happen if the source address was just newly
827 * added
828 */
829 SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: looking up net for IP source address\n");
830 SCTPDBG(SCTP_DEBUG_ASCONF1, "Looking for IP source: ");
831 SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, src);
832 /* look up the from address */
833 stcb->asoc.last_control_chunk_from = sctp_findnet(stcb, src);
834 #ifdef SCTP_DEBUG
835 if (stcb->asoc.last_control_chunk_from == NULL) {
836 SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: IP source address not found?!\n");
837 }
838 #endif
839 }
840 }
841
842 /*
843 * does the address match? returns 0 if not, 1 if so
844 */
845 static uint32_t
sctp_asconf_addr_match(struct sctp_asconf_addr * aa,struct sockaddr * sa)846 sctp_asconf_addr_match(struct sctp_asconf_addr *aa, struct sockaddr *sa)
847 {
848 switch (sa->sa_family) {
849 #ifdef INET6
850 case AF_INET6:
851 {
852 /* XXX scopeid */
853 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
854
855 if ((aa->ap.addrp.ph.param_type == SCTP_IPV6_ADDRESS) &&
856 (memcmp(&aa->ap.addrp.addr, &sin6->sin6_addr,
857 sizeof(struct in6_addr)) == 0)) {
858 return (1);
859 }
860 break;
861 }
862 #endif
863 #ifdef INET
864 case AF_INET:
865 {
866 struct sockaddr_in *sin = (struct sockaddr_in *)sa;
867
868 if ((aa->ap.addrp.ph.param_type == SCTP_IPV4_ADDRESS) &&
869 (memcmp(&aa->ap.addrp.addr, &sin->sin_addr,
870 sizeof(struct in_addr)) == 0)) {
871 return (1);
872 }
873 break;
874 }
875 #endif
876 default:
877 break;
878 }
879 return (0);
880 }
881
882 /*
883 * does the address match? returns 0 if not, 1 if so
884 */
885 static uint32_t
sctp_addr_match(struct sctp_paramhdr * ph,struct sockaddr * sa)886 sctp_addr_match(struct sctp_paramhdr *ph, struct sockaddr *sa)
887 {
888 #if defined(INET) || defined(INET6)
889 uint16_t param_type, param_length;
890
891 param_type = ntohs(ph->param_type);
892 param_length = ntohs(ph->param_length);
893 #endif
894 switch (sa->sa_family) {
895 #ifdef INET6
896 case AF_INET6:
897 {
898 /* XXX scopeid */
899 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
900 struct sctp_ipv6addr_param *v6addr;
901
902 v6addr = (struct sctp_ipv6addr_param *)ph;
903 if ((param_type == SCTP_IPV6_ADDRESS) &&
904 (param_length == sizeof(struct sctp_ipv6addr_param)) &&
905 (memcmp(&v6addr->addr, &sin6->sin6_addr,
906 sizeof(struct in6_addr)) == 0)) {
907 return (1);
908 }
909 break;
910 }
911 #endif
912 #ifdef INET
913 case AF_INET:
914 {
915 struct sockaddr_in *sin = (struct sockaddr_in *)sa;
916 struct sctp_ipv4addr_param *v4addr;
917
918 v4addr = (struct sctp_ipv4addr_param *)ph;
919 if ((param_type == SCTP_IPV4_ADDRESS) &&
920 (param_length == sizeof(struct sctp_ipv4addr_param)) &&
921 (memcmp(&v4addr->addr, &sin->sin_addr,
922 sizeof(struct in_addr)) == 0)) {
923 return (1);
924 }
925 break;
926 }
927 #endif
928 default:
929 break;
930 }
931 return (0);
932 }
933 /*
934 * Cleanup for non-responded/OP ERR'd ASCONF
935 */
936 void
sctp_asconf_cleanup(struct sctp_tcb * stcb,struct sctp_nets * net)937 sctp_asconf_cleanup(struct sctp_tcb *stcb, struct sctp_nets *net)
938 {
939 /* mark peer as ASCONF incapable */
940 stcb->asoc.peer_supports_asconf = 0;
941 /*
942 * clear out any existing asconfs going out
943 */
944 sctp_timer_stop(SCTP_TIMER_TYPE_ASCONF, stcb->sctp_ep, stcb, net,
945 SCTP_FROM_SCTP_ASCONF+SCTP_LOC_2);
946 stcb->asoc.asconf_seq_out_acked = stcb->asoc.asconf_seq_out;
947 /* remove the old ASCONF on our outbound queue */
948 sctp_toss_old_asconf(stcb);
949 }
950
951 /*
952 * cleanup any cached source addresses that may be topologically
953 * incorrect after a new address has been added to this interface.
954 */
955 static void
sctp_asconf_nets_cleanup(struct sctp_tcb * stcb,struct sctp_ifn * ifn)956 sctp_asconf_nets_cleanup(struct sctp_tcb *stcb, struct sctp_ifn *ifn)
957 {
958 struct sctp_nets *net;
959
960 /*
961 * Ideally, we want to only clear cached routes and source addresses
962 * that are topologically incorrect. But since there is no easy way
963 * to know whether the newly added address on the ifn would cause a
964 * routing change (i.e. a new egress interface would be chosen)
965 * without doing a new routing lookup and source address selection,
966 * we will (for now) just flush any cached route using a different
967 * ifn (and cached source addrs) and let output re-choose them during
968 * the next send on that net.
969 */
970 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
971 /*
972 * clear any cached route (and cached source address) if the
973 * route's interface is NOT the same as the address change.
974 * If it's the same interface, just clear the cached source
975 * address.
976 */
977 if (SCTP_ROUTE_HAS_VALID_IFN(&net->ro) &&
978 ((ifn == NULL) ||
979 (SCTP_GET_IF_INDEX_FROM_ROUTE(&net->ro) != ifn->ifn_index))) {
980 /* clear any cached route */
981 RTFREE(net->ro.ro_rt);
982 net->ro.ro_rt = NULL;
983 }
984 /* clear any cached source address */
985 if (net->src_addr_selected) {
986 sctp_free_ifa(net->ro._s_addr);
987 net->ro._s_addr = NULL;
988 net->src_addr_selected = 0;
989 }
990 }
991 }
992
993
994 void
sctp_assoc_immediate_retrans(struct sctp_tcb * stcb,struct sctp_nets * dstnet)995 sctp_assoc_immediate_retrans(struct sctp_tcb *stcb, struct sctp_nets *dstnet)
996 {
997 int error;
998
999 if (dstnet->dest_state & SCTP_ADDR_UNCONFIRMED) {
1000 return;
1001 }
1002 if (stcb->asoc.deleted_primary == NULL) {
1003 return;
1004 }
1005
1006 if (!TAILQ_EMPTY(&stcb->asoc.sent_queue)) {
1007 SCTPDBG(SCTP_DEBUG_ASCONF1, "assoc_immediate_retrans: Deleted primary is ");
1008 SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, &stcb->asoc.deleted_primary->ro._l_addr.sa);
1009 SCTPDBG(SCTP_DEBUG_ASCONF1, "Current Primary is ");
1010 SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, &stcb->asoc.primary_destination->ro._l_addr.sa);
1011 sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb,
1012 stcb->asoc.deleted_primary,
1013 SCTP_FROM_SCTP_TIMER+SCTP_LOC_8);
1014 stcb->asoc.num_send_timers_up--;
1015 if (stcb->asoc.num_send_timers_up < 0) {
1016 stcb->asoc.num_send_timers_up = 0;
1017 }
1018 SCTP_TCB_LOCK_ASSERT(stcb);
1019 error = sctp_t3rxt_timer(stcb->sctp_ep, stcb,
1020 stcb->asoc.deleted_primary);
1021 if (error) {
1022 SCTP_INP_DECR_REF(stcb->sctp_ep);
1023 return;
1024 }
1025 SCTP_TCB_LOCK_ASSERT(stcb);
1026 #ifdef SCTP_AUDITING_ENABLED
1027 sctp_auditing(4, stcb->sctp_ep, stcb, stcb->asoc.deleted_primary);
1028 #endif
1029 sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_NOT_LOCKED);
1030 if ((stcb->asoc.num_send_timers_up == 0) &&
1031 (stcb->asoc.sent_queue_cnt > 0)) {
1032 struct sctp_tmit_chunk *chk;
1033
1034 chk = TAILQ_FIRST(&stcb->asoc.sent_queue);
1035 sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep,
1036 stcb, chk->whoTo);
1037 }
1038 }
1039 return;
1040 }
1041
1042 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Userspace__)
1043 static int
1044 sctp_asconf_queue_mgmt(struct sctp_tcb *, struct sctp_ifa *, uint16_t);
1045
1046 void
sctp_net_immediate_retrans(struct sctp_tcb * stcb,struct sctp_nets * net)1047 sctp_net_immediate_retrans(struct sctp_tcb *stcb, struct sctp_nets *net)
1048 {
1049 struct sctp_tmit_chunk *chk;
1050
1051 SCTPDBG(SCTP_DEBUG_ASCONF1, "net_immediate_retrans: RTO is %d\n", net->RTO);
1052 sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, net,
1053 SCTP_FROM_SCTP_TIMER+SCTP_LOC_5);
1054 stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb, net);
1055 net->error_count = 0;
1056 TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) {
1057 if (chk->whoTo == net) {
1058 if (chk->sent < SCTP_DATAGRAM_RESEND) {
1059 chk->sent = SCTP_DATAGRAM_RESEND;
1060 sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt);
1061 sctp_flight_size_decrease(chk);
1062 sctp_total_flight_decrease(stcb, chk);
1063 net->marked_retrans++;
1064 stcb->asoc.marked_retrans++;
1065 }
1066 }
1067 }
1068 if (net->marked_retrans) {
1069 sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_NOT_LOCKED);
1070 }
1071 }
1072
1073 static void
sctp_path_check_and_react(struct sctp_tcb * stcb,struct sctp_ifa * newifa)1074 sctp_path_check_and_react(struct sctp_tcb *stcb, struct sctp_ifa *newifa)
1075 {
1076 struct sctp_nets *net;
1077 int addrnum, changed;
1078
1079 /* If number of local valid addresses is 1, the valid address is
1080 probably newly added address.
1081 Several valid addresses in this association. A source address
1082 may not be changed. Additionally, they can be configured on a
1083 same interface as "alias" addresses. (by micchie)
1084 */
1085 addrnum = sctp_local_addr_count(stcb);
1086 SCTPDBG(SCTP_DEBUG_ASCONF1, "p_check_react(): %d local addresses\n",
1087 addrnum);
1088 if (addrnum == 1) {
1089 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
1090 /* clear any cached route and source address */
1091 if (net->ro.ro_rt) {
1092 RTFREE(net->ro.ro_rt);
1093 net->ro.ro_rt = NULL;
1094 }
1095 if (net->src_addr_selected) {
1096 sctp_free_ifa(net->ro._s_addr);
1097 net->ro._s_addr = NULL;
1098 net->src_addr_selected = 0;
1099 }
1100 /* Retransmit unacknowledged DATA chunks immediately */
1101 if (sctp_is_mobility_feature_on(stcb->sctp_ep,
1102 SCTP_MOBILITY_FASTHANDOFF)) {
1103 sctp_net_immediate_retrans(stcb, net);
1104 }
1105 /* also, SET PRIMARY is maybe already sent */
1106 }
1107 return;
1108 }
1109
1110 /* Multiple local addresses exsist in the association. */
1111 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
1112 /* clear any cached route and source address */
1113 if (net->ro.ro_rt) {
1114 RTFREE(net->ro.ro_rt);
1115 net->ro.ro_rt = NULL;
1116 }
1117 if (net->src_addr_selected) {
1118 sctp_free_ifa(net->ro._s_addr);
1119 net->ro._s_addr = NULL;
1120 net->src_addr_selected = 0;
1121 }
1122 /* Check if the nexthop is corresponding to the new address.
1123 If the new address is corresponding to the current nexthop,
1124 the path will be changed.
1125 If the new address is NOT corresponding to the current
1126 nexthop, the path will not be changed.
1127 */
1128 SCTP_RTALLOC((sctp_route_t *)&net->ro,
1129 stcb->sctp_ep->def_vrf_id);
1130 if (net->ro.ro_rt == NULL)
1131 continue;
1132
1133 changed = 0;
1134 switch (net->ro._l_addr.sa.sa_family) {
1135 #ifdef INET
1136 case AF_INET:
1137 if (sctp_v4src_match_nexthop(newifa, (sctp_route_t *)&net->ro)) {
1138 changed = 1;
1139 }
1140 break;
1141 #endif
1142 #ifdef INET6
1143 case AF_INET6:
1144 if (sctp_v6src_match_nexthop(
1145 &newifa->address.sin6, (sctp_route_t *)&net->ro)) {
1146 changed = 1;
1147 }
1148 break;
1149 #endif
1150 default:
1151 break;
1152 }
1153 /* if the newly added address does not relate routing
1154 information, we skip.
1155 */
1156 if (changed == 0)
1157 continue;
1158 /* Retransmit unacknowledged DATA chunks immediately */
1159 if (sctp_is_mobility_feature_on(stcb->sctp_ep,
1160 SCTP_MOBILITY_FASTHANDOFF)) {
1161 sctp_net_immediate_retrans(stcb, net);
1162 }
1163 /* Send SET PRIMARY for this new address */
1164 if (net == stcb->asoc.primary_destination) {
1165 (void)sctp_asconf_queue_mgmt(stcb, newifa,
1166 SCTP_SET_PRIM_ADDR);
1167 }
1168 }
1169 }
1170 #endif /* __FreeBSD__ __APPLE__ __Userspace__ */
1171
1172 /*
1173 * process an ADD/DELETE IP ack from peer.
1174 * addr: corresponding sctp_ifa to the address being added/deleted.
1175 * type: SCTP_ADD_IP_ADDRESS or SCTP_DEL_IP_ADDRESS.
1176 * flag: 1=success, 0=failure.
1177 */
1178 static void
sctp_asconf_addr_mgmt_ack(struct sctp_tcb * stcb,struct sctp_ifa * addr,uint32_t flag)1179 sctp_asconf_addr_mgmt_ack(struct sctp_tcb *stcb, struct sctp_ifa *addr, uint32_t flag)
1180 {
1181 /*
1182 * do the necessary asoc list work- if we get a failure indication,
1183 * leave the address on the assoc's restricted list. If we get a
1184 * success indication, remove the address from the restricted list.
1185 */
1186 /*
1187 * Note: this will only occur for ADD_IP_ADDRESS, since
1188 * DEL_IP_ADDRESS is never actually added to the list...
1189 */
1190 if (flag) {
1191 /* success case, so remove from the restricted list */
1192 sctp_del_local_addr_restricted(stcb, addr);
1193
1194 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Userspace__)
1195 if (sctp_is_mobility_feature_on(stcb->sctp_ep,
1196 SCTP_MOBILITY_BASE) ||
1197 sctp_is_mobility_feature_on(stcb->sctp_ep,
1198 SCTP_MOBILITY_FASTHANDOFF)) {
1199 sctp_path_check_and_react(stcb, addr);
1200 return;
1201 }
1202 #endif /* __FreeBSD__ __APPLE__ __Userspace__ */
1203 /* clear any cached/topologically incorrect source addresses */
1204 sctp_asconf_nets_cleanup(stcb, addr->ifn_p);
1205 }
1206 /* else, leave it on the list */
1207 }
1208
1209 /*
1210 * add an asconf add/delete/set primary IP address parameter to the queue.
1211 * type = SCTP_ADD_IP_ADDRESS, SCTP_DEL_IP_ADDRESS, SCTP_SET_PRIM_ADDR.
1212 * returns 0 if queued, -1 if not queued/removed.
1213 * NOTE: if adding, but a delete for the same address is already scheduled
1214 * (and not yet sent out), simply remove it from queue. Same for deleting
1215 * an address already scheduled for add. If a duplicate operation is found,
1216 * ignore the new one.
1217 */
1218 static int
sctp_asconf_queue_mgmt(struct sctp_tcb * stcb,struct sctp_ifa * ifa,uint16_t type)1219 sctp_asconf_queue_mgmt(struct sctp_tcb *stcb, struct sctp_ifa *ifa,
1220 uint16_t type)
1221 {
1222 struct sctp_asconf_addr *aa, *aa_next;
1223
1224 /* make sure the request isn't already in the queue */
1225 TAILQ_FOREACH_SAFE(aa, &stcb->asoc.asconf_queue, next, aa_next) {
1226 /* address match? */
1227 if (sctp_asconf_addr_match(aa, &ifa->address.sa) == 0)
1228 continue;
1229 /* is the request already in queue but not sent?
1230 * pass the request already sent in order to resolve the following case:
1231 * 1. arrival of ADD, then sent
1232 * 2. arrival of DEL. we can't remove the ADD request already sent
1233 * 3. arrival of ADD
1234 */
1235 if (aa->ap.aph.ph.param_type == type && aa->sent == 0) {
1236 return (-1);
1237 }
1238 /* is the negative request already in queue, and not sent */
1239 if ((aa->sent == 0) && (type == SCTP_ADD_IP_ADDRESS) &&
1240 (aa->ap.aph.ph.param_type == SCTP_DEL_IP_ADDRESS)) {
1241 /* add requested, delete already queued */
1242 TAILQ_REMOVE(&stcb->asoc.asconf_queue, aa, next);
1243 /* remove the ifa from the restricted list */
1244 sctp_del_local_addr_restricted(stcb, ifa);
1245 /* free the asconf param */
1246 SCTP_FREE(aa, SCTP_M_ASC_ADDR);
1247 SCTPDBG(SCTP_DEBUG_ASCONF2, "asconf_queue_mgmt: add removes queued entry\n");
1248 return (-1);
1249 }
1250 if ((aa->sent == 0) && (type == SCTP_DEL_IP_ADDRESS) &&
1251 (aa->ap.aph.ph.param_type == SCTP_ADD_IP_ADDRESS)) {
1252 /* delete requested, add already queued */
1253 TAILQ_REMOVE(&stcb->asoc.asconf_queue, aa, next);
1254 /* remove the aa->ifa from the restricted list */
1255 sctp_del_local_addr_restricted(stcb, aa->ifa);
1256 /* free the asconf param */
1257 SCTP_FREE(aa, SCTP_M_ASC_ADDR);
1258 SCTPDBG(SCTP_DEBUG_ASCONF2, "asconf_queue_mgmt: delete removes queued entry\n");
1259 return (-1);
1260 }
1261 } /* for each aa */
1262
1263 /* adding new request to the queue */
1264 SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa),
1265 SCTP_M_ASC_ADDR);
1266 if (aa == NULL) {
1267 /* didn't get memory */
1268 SCTPDBG(SCTP_DEBUG_ASCONF1, "asconf_queue_mgmt: failed to get memory!\n");
1269 return (-1);
1270 }
1271 aa->special_del = 0;
1272 /* fill in asconf address parameter fields */
1273 /* top level elements are "networked" during send */
1274 aa->ap.aph.ph.param_type = type;
1275 aa->ifa = ifa;
1276 atomic_add_int(&ifa->refcount, 1);
1277 /* correlation_id filled in during send routine later... */
1278 switch (ifa->address.sa.sa_family) {
1279 #ifdef INET6
1280 case AF_INET6:
1281 {
1282 struct sockaddr_in6 *sin6;
1283
1284 sin6 = (struct sockaddr_in6 *)&ifa->address.sa;
1285 aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS;
1286 aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv6addr_param));
1287 aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) +
1288 sizeof(struct sctp_ipv6addr_param);
1289 memcpy(&aa->ap.addrp.addr, &sin6->sin6_addr,
1290 sizeof(struct in6_addr));
1291 break;
1292 }
1293 #endif
1294 #ifdef INET
1295 case AF_INET:
1296 {
1297 struct sockaddr_in *sin;
1298
1299 sin= (struct sockaddr_in *)&ifa->address.sa;
1300 aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS;
1301 aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv4addr_param));
1302 aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) +
1303 sizeof(struct sctp_ipv4addr_param);
1304 memcpy(&aa->ap.addrp.addr, &sin->sin_addr,
1305 sizeof(struct in_addr));
1306 break;
1307 }
1308 #endif
1309 default:
1310 /* invalid family! */
1311 SCTP_FREE(aa, SCTP_M_ASC_ADDR);
1312 sctp_free_ifa(ifa);
1313 return (-1);
1314 }
1315 aa->sent = 0; /* clear sent flag */
1316
1317 TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next);
1318 #ifdef SCTP_DEBUG
1319 if (SCTP_BASE_SYSCTL(sctp_debug_on) & SCTP_DEBUG_ASCONF2) {
1320 if (type == SCTP_ADD_IP_ADDRESS) {
1321 SCTP_PRINTF("asconf_queue_mgmt: inserted asconf ADD_IP_ADDRESS: ");
1322 SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, &ifa->address.sa);
1323 } else if (type == SCTP_DEL_IP_ADDRESS) {
1324 SCTP_PRINTF("asconf_queue_mgmt: appended asconf DEL_IP_ADDRESS: ");
1325 SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, &ifa->address.sa);
1326 } else {
1327 SCTP_PRINTF("asconf_queue_mgmt: appended asconf SET_PRIM_ADDR: ");
1328 SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, &ifa->address.sa);
1329 }
1330 }
1331 #endif
1332
1333 return (0);
1334 }
1335
1336
1337 /*
1338 * add an asconf operation for the given ifa and type.
1339 * type = SCTP_ADD_IP_ADDRESS, SCTP_DEL_IP_ADDRESS, SCTP_SET_PRIM_ADDR.
1340 * returns 0 if completed, -1 if not completed, 1 if immediate send is
1341 * advisable.
1342 */
1343 static int
sctp_asconf_queue_add(struct sctp_tcb * stcb,struct sctp_ifa * ifa,uint16_t type)1344 sctp_asconf_queue_add(struct sctp_tcb *stcb, struct sctp_ifa *ifa,
1345 uint16_t type)
1346 {
1347 uint32_t status;
1348 int pending_delete_queued = 0;
1349
1350 /* see if peer supports ASCONF */
1351 if (stcb->asoc.peer_supports_asconf == 0) {
1352 return (-1);
1353 }
1354
1355 /*
1356 * if this is deleting the last address from the assoc, mark it as
1357 * pending.
1358 */
1359 if ((type == SCTP_DEL_IP_ADDRESS) && !stcb->asoc.asconf_del_pending &&
1360 (sctp_local_addr_count(stcb) < 2)) {
1361 /* set the pending delete info only */
1362 stcb->asoc.asconf_del_pending = 1;
1363 stcb->asoc.asconf_addr_del_pending = ifa;
1364 atomic_add_int(&ifa->refcount, 1);
1365 SCTPDBG(SCTP_DEBUG_ASCONF2,
1366 "asconf_queue_add: mark delete last address pending\n");
1367 return (-1);
1368 }
1369
1370 /* queue an asconf parameter */
1371 status = sctp_asconf_queue_mgmt(stcb, ifa, type);
1372
1373 /*
1374 * if this is an add, and there is a delete also pending (i.e. the
1375 * last local address is being changed), queue the pending delete too.
1376 */
1377 if ((type == SCTP_ADD_IP_ADDRESS) && stcb->asoc.asconf_del_pending && (status == 0)) {
1378 /* queue in the pending delete */
1379 if (sctp_asconf_queue_mgmt(stcb,
1380 stcb->asoc.asconf_addr_del_pending,
1381 SCTP_DEL_IP_ADDRESS) == 0) {
1382 SCTPDBG(SCTP_DEBUG_ASCONF2, "asconf_queue_add: queing pending delete\n");
1383 pending_delete_queued = 1;
1384 /* clear out the pending delete info */
1385 stcb->asoc.asconf_del_pending = 0;
1386 sctp_free_ifa(stcb->asoc.asconf_addr_del_pending);
1387 stcb->asoc.asconf_addr_del_pending = NULL;
1388 }
1389 }
1390
1391 if (pending_delete_queued) {
1392 struct sctp_nets *net;
1393 /*
1394 * since we know that the only/last address is now being
1395 * changed in this case, reset the cwnd/rto on all nets to
1396 * start as a new address and path. Also clear the error
1397 * counts to give the assoc the best chance to complete the
1398 * address change.
1399 */
1400 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
1401 stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb,
1402 net);
1403 net->RTO = 0;
1404 net->error_count = 0;
1405 }
1406 stcb->asoc.overall_error_count = 0;
1407 if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) {
1408 sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
1409 stcb->asoc.overall_error_count,
1410 0,
1411 SCTP_FROM_SCTP_ASCONF,
1412 __LINE__);
1413 }
1414
1415 /* queue in an advisory set primary too */
1416 (void)sctp_asconf_queue_mgmt(stcb, ifa, SCTP_SET_PRIM_ADDR);
1417 /* let caller know we should send this out immediately */
1418 status = 1;
1419 }
1420 return (status);
1421 }
1422
1423 /*-
1424 * add an asconf delete IP address parameter to the queue by sockaddr and
1425 * possibly with no sctp_ifa available. This is only called by the routine
1426 * that checks the addresses in an INIT-ACK against the current address list.
1427 * returns 0 if completed, non-zero if not completed.
1428 * NOTE: if an add is already scheduled (and not yet sent out), simply
1429 * remove it from queue. If a duplicate operation is found, ignore the
1430 * new one.
1431 */
1432 static int
sctp_asconf_queue_sa_delete(struct sctp_tcb * stcb,struct sockaddr * sa)1433 sctp_asconf_queue_sa_delete(struct sctp_tcb *stcb, struct sockaddr *sa)
1434 {
1435 struct sctp_ifa *ifa;
1436 struct sctp_asconf_addr *aa, *aa_next;
1437 uint32_t vrf_id;
1438
1439 if (stcb == NULL) {
1440 return (-1);
1441 }
1442 /* see if peer supports ASCONF */
1443 if (stcb->asoc.peer_supports_asconf == 0) {
1444 return (-1);
1445 }
1446 /* make sure the request isn't already in the queue */
1447 TAILQ_FOREACH_SAFE(aa, &stcb->asoc.asconf_queue, next, aa_next) {
1448 /* address match? */
1449 if (sctp_asconf_addr_match(aa, sa) == 0)
1450 continue;
1451 /* is the request already in queue (sent or not) */
1452 if (aa->ap.aph.ph.param_type == SCTP_DEL_IP_ADDRESS) {
1453 return (-1);
1454 }
1455 /* is the negative request already in queue, and not sent */
1456 if (aa->sent == 1)
1457 continue;
1458 if (aa->ap.aph.ph.param_type == SCTP_ADD_IP_ADDRESS) {
1459 /* add already queued, so remove existing entry */
1460 TAILQ_REMOVE(&stcb->asoc.asconf_queue, aa, next);
1461 sctp_del_local_addr_restricted(stcb, aa->ifa);
1462 /* free the entry */
1463 SCTP_FREE(aa, SCTP_M_ASC_ADDR);
1464 return (-1);
1465 }
1466 } /* for each aa */
1467
1468 /* find any existing ifa-- NOTE ifa CAN be allowed to be NULL */
1469 if (stcb) {
1470 vrf_id = stcb->asoc.vrf_id;
1471 } else {
1472 vrf_id = SCTP_DEFAULT_VRFID;
1473 }
1474 ifa = sctp_find_ifa_by_addr(sa, vrf_id, SCTP_ADDR_NOT_LOCKED);
1475
1476 /* adding new request to the queue */
1477 SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa),
1478 SCTP_M_ASC_ADDR);
1479 if (aa == NULL) {
1480 /* didn't get memory */
1481 SCTPDBG(SCTP_DEBUG_ASCONF1,
1482 "sctp_asconf_queue_sa_delete: failed to get memory!\n");
1483 return (-1);
1484 }
1485 aa->special_del = 0;
1486 /* fill in asconf address parameter fields */
1487 /* top level elements are "networked" during send */
1488 aa->ap.aph.ph.param_type = SCTP_DEL_IP_ADDRESS;
1489 aa->ifa = ifa;
1490 if (ifa)
1491 atomic_add_int(&ifa->refcount, 1);
1492 /* correlation_id filled in during send routine later... */
1493 switch (sa->sa_family) {
1494 #ifdef INET6
1495 case AF_INET6:
1496 {
1497 /* IPv6 address */
1498 struct sockaddr_in6 *sin6;
1499
1500 sin6 = (struct sockaddr_in6 *)sa;
1501 aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS;
1502 aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv6addr_param));
1503 aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) + sizeof(struct sctp_ipv6addr_param);
1504 memcpy(&aa->ap.addrp.addr, &sin6->sin6_addr,
1505 sizeof(struct in6_addr));
1506 break;
1507 }
1508 #endif
1509 #ifdef INET
1510 case AF_INET:
1511 {
1512 /* IPv4 address */
1513 struct sockaddr_in *sin = (struct sockaddr_in *)sa;
1514
1515 aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS;
1516 aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv4addr_param));
1517 aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) + sizeof(struct sctp_ipv4addr_param);
1518 memcpy(&aa->ap.addrp.addr, &sin->sin_addr,
1519 sizeof(struct in_addr));
1520 break;
1521 }
1522 #endif
1523 default:
1524 /* invalid family! */
1525 SCTP_FREE(aa, SCTP_M_ASC_ADDR);
1526 if (ifa)
1527 sctp_free_ifa(ifa);
1528 return (-1);
1529 }
1530 aa->sent = 0; /* clear sent flag */
1531
1532 /* delete goes to the back of the queue */
1533 TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next);
1534
1535 /* sa_ignore MEMLEAK {memory is put on the tailq} */
1536 return (0);
1537 }
1538
1539 /*
1540 * find a specific asconf param on our "sent" queue
1541 */
1542 static struct sctp_asconf_addr *
sctp_asconf_find_param(struct sctp_tcb * stcb,uint32_t correlation_id)1543 sctp_asconf_find_param(struct sctp_tcb *stcb, uint32_t correlation_id)
1544 {
1545 struct sctp_asconf_addr *aa;
1546
1547 TAILQ_FOREACH(aa, &stcb->asoc.asconf_queue, next) {
1548 if (aa->ap.aph.correlation_id == correlation_id &&
1549 aa->sent == 1) {
1550 /* found it */
1551 return (aa);
1552 }
1553 }
1554 /* didn't find it */
1555 return (NULL);
1556 }
1557
1558 /*
1559 * process an SCTP_ERROR_CAUSE_IND for a ASCONF-ACK parameter and do
1560 * notifications based on the error response
1561 */
1562 static void
sctp_asconf_process_error(struct sctp_tcb * stcb,struct sctp_asconf_paramhdr * aph)1563 sctp_asconf_process_error(struct sctp_tcb *stcb,
1564 struct sctp_asconf_paramhdr *aph)
1565 {
1566 struct sctp_error_cause *eh;
1567 struct sctp_paramhdr *ph;
1568 uint16_t param_type;
1569 uint16_t error_code;
1570
1571 eh = (struct sctp_error_cause *)(aph + 1);
1572 ph = (struct sctp_paramhdr *)(eh + 1);
1573 /* validate lengths */
1574 if (htons(eh->length) + sizeof(struct sctp_error_cause) >
1575 htons(aph->ph.param_length)) {
1576 /* invalid error cause length */
1577 SCTPDBG(SCTP_DEBUG_ASCONF1,
1578 "asconf_process_error: cause element too long\n");
1579 return;
1580 }
1581 if (htons(ph->param_length) + sizeof(struct sctp_paramhdr) >
1582 htons(eh->length)) {
1583 /* invalid included TLV length */
1584 SCTPDBG(SCTP_DEBUG_ASCONF1,
1585 "asconf_process_error: included TLV too long\n");
1586 return;
1587 }
1588 /* which error code ? */
1589 error_code = ntohs(eh->code);
1590 param_type = ntohs(aph->ph.param_type);
1591 /* FIX: this should go back up the REMOTE_ERROR ULP notify */
1592 switch (error_code) {
1593 case SCTP_CAUSE_RESOURCE_SHORTAGE:
1594 /* we allow ourselves to "try again" for this error */
1595 break;
1596 default:
1597 /* peer can't handle it... */
1598 switch (param_type) {
1599 case SCTP_ADD_IP_ADDRESS:
1600 case SCTP_DEL_IP_ADDRESS:
1601 stcb->asoc.peer_supports_asconf = 0;
1602 break;
1603 case SCTP_SET_PRIM_ADDR:
1604 stcb->asoc.peer_supports_asconf = 0;
1605 break;
1606 default:
1607 break;
1608 }
1609 }
1610 }
1611
1612 /*
1613 * process an asconf queue param.
1614 * aparam: parameter to process, will be removed from the queue.
1615 * flag: 1=success case, 0=failure case
1616 */
1617 static void
sctp_asconf_process_param_ack(struct sctp_tcb * stcb,struct sctp_asconf_addr * aparam,uint32_t flag)1618 sctp_asconf_process_param_ack(struct sctp_tcb *stcb,
1619 struct sctp_asconf_addr *aparam, uint32_t flag)
1620 {
1621 uint16_t param_type;
1622
1623 /* process this param */
1624 param_type = aparam->ap.aph.ph.param_type;
1625 switch (param_type) {
1626 case SCTP_ADD_IP_ADDRESS:
1627 SCTPDBG(SCTP_DEBUG_ASCONF1,
1628 "process_param_ack: added IP address\n");
1629 sctp_asconf_addr_mgmt_ack(stcb, aparam->ifa, flag);
1630 break;
1631 case SCTP_DEL_IP_ADDRESS:
1632 SCTPDBG(SCTP_DEBUG_ASCONF1,
1633 "process_param_ack: deleted IP address\n");
1634 /* nothing really to do... lists already updated */
1635 break;
1636 case SCTP_SET_PRIM_ADDR:
1637 SCTPDBG(SCTP_DEBUG_ASCONF1,
1638 "process_param_ack: set primary IP address\n");
1639 /* nothing to do... peer may start using this addr */
1640 if (flag == 0)
1641 stcb->asoc.peer_supports_asconf = 0;
1642 break;
1643 default:
1644 /* should NEVER happen */
1645 break;
1646 }
1647
1648 /* remove the param and free it */
1649 TAILQ_REMOVE(&stcb->asoc.asconf_queue, aparam, next);
1650 if (aparam->ifa)
1651 sctp_free_ifa(aparam->ifa);
1652 SCTP_FREE(aparam, SCTP_M_ASC_ADDR);
1653 }
1654
1655 /*
1656 * cleanup from a bad asconf ack parameter
1657 */
1658 static void
sctp_asconf_ack_clear(struct sctp_tcb * stcb)1659 sctp_asconf_ack_clear(struct sctp_tcb *stcb)
1660 {
1661 /* assume peer doesn't really know how to do asconfs */
1662 stcb->asoc.peer_supports_asconf = 0;
1663 /* XXX we could free the pending queue here */
1664 }
1665
1666 void
sctp_handle_asconf_ack(struct mbuf * m,int offset,struct sctp_asconf_ack_chunk * cp,struct sctp_tcb * stcb,struct sctp_nets * net,int * abort_no_unlock)1667 sctp_handle_asconf_ack(struct mbuf *m, int offset,
1668 struct sctp_asconf_ack_chunk *cp, struct sctp_tcb *stcb,
1669 struct sctp_nets *net, int *abort_no_unlock)
1670 {
1671 struct sctp_association *asoc;
1672 uint32_t serial_num;
1673 uint16_t ack_length;
1674 struct sctp_asconf_paramhdr *aph;
1675 struct sctp_asconf_addr *aa, *aa_next;
1676 uint32_t last_error_id = 0; /* last error correlation id */
1677 uint32_t id;
1678 struct sctp_asconf_addr *ap;
1679
1680 /* asconf param buffer */
1681 uint8_t aparam_buf[SCTP_PARAM_BUFFER_SIZE];
1682
1683 /* verify minimum length */
1684 if (ntohs(cp->ch.chunk_length) < sizeof(struct sctp_asconf_ack_chunk)) {
1685 SCTPDBG(SCTP_DEBUG_ASCONF1,
1686 "handle_asconf_ack: chunk too small = %xh\n",
1687 ntohs(cp->ch.chunk_length));
1688 return;
1689 }
1690 asoc = &stcb->asoc;
1691 serial_num = ntohl(cp->serial_number);
1692
1693 /*
1694 * NOTE: we may want to handle this differently- currently, we will
1695 * abort when we get an ack for the expected serial number + 1 (eg.
1696 * we didn't send it), process an ack normally if it is the expected
1697 * serial number, and re-send the previous ack for *ALL* other
1698 * serial numbers
1699 */
1700
1701 /*
1702 * if the serial number is the next expected, but I didn't send it,
1703 * abort the asoc, since someone probably just hijacked us...
1704 */
1705 if (serial_num == (asoc->asconf_seq_out + 1)) {
1706 SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf_ack: got unexpected next serial number! Aborting asoc!\n");
1707 sctp_abort_an_association(stcb->sctp_ep, stcb, NULL, SCTP_SO_NOT_LOCKED);
1708 *abort_no_unlock = 1;
1709 return;
1710 }
1711 if (serial_num != asoc->asconf_seq_out_acked + 1) {
1712 /* got a duplicate/unexpected ASCONF-ACK */
1713 SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf_ack: got duplicate/unexpected serial number = %xh (expected = %xh)\n",
1714 serial_num, asoc->asconf_seq_out_acked + 1);
1715 return;
1716 }
1717
1718 if (serial_num == asoc->asconf_seq_out - 1) {
1719 /* stop our timer */
1720 sctp_timer_stop(SCTP_TIMER_TYPE_ASCONF, stcb->sctp_ep, stcb, net,
1721 SCTP_FROM_SCTP_ASCONF+SCTP_LOC_3);
1722 }
1723
1724 /* process the ASCONF-ACK contents */
1725 ack_length = ntohs(cp->ch.chunk_length) -
1726 sizeof(struct sctp_asconf_ack_chunk);
1727 offset += sizeof(struct sctp_asconf_ack_chunk);
1728 /* process through all parameters */
1729 while (ack_length >= sizeof(struct sctp_asconf_paramhdr)) {
1730 unsigned int param_length, param_type;
1731
1732 /* get pointer to next asconf parameter */
1733 aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(m, offset,
1734 sizeof(struct sctp_asconf_paramhdr), aparam_buf);
1735 if (aph == NULL) {
1736 /* can't get an asconf paramhdr */
1737 sctp_asconf_ack_clear(stcb);
1738 return;
1739 }
1740 param_type = ntohs(aph->ph.param_type);
1741 param_length = ntohs(aph->ph.param_length);
1742 if (param_length > ack_length) {
1743 sctp_asconf_ack_clear(stcb);
1744 return;
1745 }
1746 if (param_length < sizeof(struct sctp_paramhdr)) {
1747 sctp_asconf_ack_clear(stcb);
1748 return;
1749 }
1750 /* get the complete parameter... */
1751 if (param_length > sizeof(aparam_buf)) {
1752 SCTPDBG(SCTP_DEBUG_ASCONF1,
1753 "param length (%u) larger than buffer size!\n", param_length);
1754 sctp_asconf_ack_clear(stcb);
1755 return;
1756 }
1757 aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(m, offset, param_length, aparam_buf);
1758 if (aph == NULL) {
1759 sctp_asconf_ack_clear(stcb);
1760 return;
1761 }
1762 /* correlation_id is transparent to peer, no ntohl needed */
1763 id = aph->correlation_id;
1764
1765 switch (param_type) {
1766 case SCTP_ERROR_CAUSE_IND:
1767 last_error_id = id;
1768 /* find the corresponding asconf param in our queue */
1769 ap = sctp_asconf_find_param(stcb, id);
1770 if (ap == NULL) {
1771 /* hmm... can't find this in our queue! */
1772 break;
1773 }
1774 /* process the parameter, failed flag */
1775 sctp_asconf_process_param_ack(stcb, ap, 0);
1776 /* process the error response */
1777 sctp_asconf_process_error(stcb, aph);
1778 break;
1779 case SCTP_SUCCESS_REPORT:
1780 /* find the corresponding asconf param in our queue */
1781 ap = sctp_asconf_find_param(stcb, id);
1782 if (ap == NULL) {
1783 /* hmm... can't find this in our queue! */
1784 break;
1785 }
1786 /* process the parameter, success flag */
1787 sctp_asconf_process_param_ack(stcb, ap, 1);
1788 break;
1789 default:
1790 break;
1791 } /* switch */
1792
1793 /* update remaining ASCONF-ACK message length to process */
1794 ack_length -= SCTP_SIZE32(param_length);
1795 if (ack_length <= 0) {
1796 /* no more data in the mbuf chain */
1797 break;
1798 }
1799 offset += SCTP_SIZE32(param_length);
1800 } /* while */
1801
1802 /*
1803 * if there are any "sent" params still on the queue, these are
1804 * implicitly "success", or "failed" (if we got an error back) ...
1805 * so process these appropriately
1806 *
1807 * we assume that the correlation_id's are monotonically increasing
1808 * beginning from 1 and that we don't have *that* many outstanding
1809 * at any given time
1810 */
1811 if (last_error_id == 0)
1812 last_error_id--; /* set to "max" value */
1813 TAILQ_FOREACH_SAFE(aa, &stcb->asoc.asconf_queue, next, aa_next) {
1814 if (aa->sent == 1) {
1815 /*
1816 * implicitly successful or failed if correlation_id
1817 * < last_error_id, then success else, failure
1818 */
1819 if (aa->ap.aph.correlation_id < last_error_id)
1820 sctp_asconf_process_param_ack(stcb, aa, 1);
1821 else
1822 sctp_asconf_process_param_ack(stcb, aa, 0);
1823 } else {
1824 /*
1825 * since we always process in order (FIFO queue) if
1826 * we reach one that hasn't been sent, the rest
1827 * should not have been sent either. so, we're
1828 * done...
1829 */
1830 break;
1831 }
1832 }
1833
1834 /* update the next sequence number to use */
1835 asoc->asconf_seq_out_acked++;
1836 /* remove the old ASCONF on our outbound queue */
1837 sctp_toss_old_asconf(stcb);
1838 if (!TAILQ_EMPTY(&stcb->asoc.asconf_queue)) {
1839 #ifdef SCTP_TIMER_BASED_ASCONF
1840 /* we have more params, so restart our timer */
1841 sctp_timer_start(SCTP_TIMER_TYPE_ASCONF, stcb->sctp_ep,
1842 stcb, net);
1843 #else
1844 /* we have more params, so send out more */
1845 sctp_send_asconf(stcb, net, SCTP_ADDR_NOT_LOCKED);
1846 #endif
1847 }
1848 }
1849
1850 #ifdef INET6
1851 static uint32_t
sctp_is_scopeid_in_nets(struct sctp_tcb * stcb,struct sockaddr * sa)1852 sctp_is_scopeid_in_nets(struct sctp_tcb *stcb, struct sockaddr *sa)
1853 {
1854 struct sockaddr_in6 *sin6, *net6;
1855 struct sctp_nets *net;
1856
1857 if (sa->sa_family != AF_INET6) {
1858 /* wrong family */
1859 return (0);
1860 }
1861 sin6 = (struct sockaddr_in6 *)sa;
1862 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) == 0) {
1863 /* not link local address */
1864 return (0);
1865 }
1866 /* hunt through our destination nets list for this scope_id */
1867 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
1868 if (((struct sockaddr *)(&net->ro._l_addr))->sa_family !=
1869 AF_INET6)
1870 continue;
1871 net6 = (struct sockaddr_in6 *)&net->ro._l_addr;
1872 if (IN6_IS_ADDR_LINKLOCAL(&net6->sin6_addr) == 0)
1873 continue;
1874 if (sctp_is_same_scope(sin6, net6)) {
1875 /* found one */
1876 return (1);
1877 }
1878 }
1879 /* didn't find one */
1880 return (0);
1881 }
1882 #endif
1883
1884 /*
1885 * address management functions
1886 */
1887 static void
sctp_addr_mgmt_assoc(struct sctp_inpcb * inp,struct sctp_tcb * stcb,struct sctp_ifa * ifa,uint16_t type,int addr_locked)1888 sctp_addr_mgmt_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
1889 struct sctp_ifa *ifa, uint16_t type, int addr_locked)
1890 {
1891 int status;
1892
1893 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0 ||
1894 sctp_is_feature_off(inp, SCTP_PCB_FLAGS_DO_ASCONF)) {
1895 /* subset bound, no ASCONF allowed case, so ignore */
1896 return;
1897 }
1898 /*
1899 * note: we know this is not the subset bound, no ASCONF case eg.
1900 * this is boundall or subset bound w/ASCONF allowed
1901 */
1902
1903 /* first, make sure it's a good address family */
1904 switch (ifa->address.sa.sa_family) {
1905 #ifdef INET6
1906 case AF_INET6:
1907 break;
1908 #endif
1909 #ifdef INET
1910 case AF_INET:
1911 break;
1912 #endif
1913 default:
1914 return;
1915 }
1916 #ifdef INET6
1917 /* make sure we're "allowed" to add this type of addr */
1918 if (ifa->address.sa.sa_family == AF_INET6) {
1919 /* invalid if we're not a v6 endpoint */
1920 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0)
1921 return;
1922 /* is the v6 addr really valid ? */
1923 if (ifa->localifa_flags & SCTP_ADDR_IFA_UNUSEABLE) {
1924 return;
1925 }
1926 }
1927 #endif
1928 /* put this address on the "pending/do not use yet" list */
1929 sctp_add_local_addr_restricted(stcb, ifa);
1930 /*
1931 * check address scope if address is out of scope, don't queue
1932 * anything... note: this would leave the address on both inp and
1933 * asoc lists
1934 */
1935 switch (ifa->address.sa.sa_family) {
1936 #ifdef INET6
1937 case AF_INET6:
1938 {
1939 struct sockaddr_in6 *sin6;
1940
1941 sin6 = (struct sockaddr_in6 *)&ifa->address.sin6;
1942 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
1943 /* we skip unspecifed addresses */
1944 return;
1945 }
1946 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
1947 if (stcb->asoc.scope.local_scope == 0) {
1948 return;
1949 }
1950 /* is it the right link local scope? */
1951 if (sctp_is_scopeid_in_nets(stcb, &ifa->address.sa) == 0) {
1952 return;
1953 }
1954 }
1955 if (stcb->asoc.scope.site_scope == 0 &&
1956 IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr)) {
1957 return;
1958 }
1959 break;
1960 }
1961 #endif
1962 #ifdef INET
1963 case AF_INET:
1964 {
1965 struct sockaddr_in *sin;
1966 struct in6pcb *inp6;
1967
1968 inp6 = (struct in6pcb *)&inp->ip_inp.inp;
1969 /* invalid if we are a v6 only endpoint */
1970 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
1971 SCTP_IPV6_V6ONLY(inp6))
1972 return;
1973
1974 sin = (struct sockaddr_in *)&ifa->address.sa;
1975 if (sin->sin_addr.s_addr == 0) {
1976 /* we skip unspecifed addresses */
1977 return;
1978 }
1979 if (stcb->asoc.scope.ipv4_local_scope == 0 &&
1980 IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) {
1981 return;
1982 }
1983 break;
1984 }
1985 #endif
1986 default:
1987 /* else, not AF_INET or AF_INET6, so skip */
1988 return;
1989 }
1990
1991 /* queue an asconf for this address add/delete */
1992 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_DO_ASCONF)) {
1993 /* does the peer do asconf? */
1994 if (stcb->asoc.peer_supports_asconf) {
1995 /* queue an asconf for this addr */
1996 status = sctp_asconf_queue_add(stcb, ifa, type);
1997
1998 /*
1999 * if queued ok, and in the open state, send out the
2000 * ASCONF. If in the non-open state, these will be
2001 * sent when the state goes open.
2002 */
2003 if (status == 0 &&
2004 SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) {
2005 #ifdef SCTP_TIMER_BASED_ASCONF
2006 sctp_timer_start(SCTP_TIMER_TYPE_ASCONF, inp,
2007 stcb, stcb->asoc.primary_destination);
2008 #else
2009 sctp_send_asconf(stcb, NULL, addr_locked);
2010 #endif
2011 }
2012 }
2013 }
2014 }
2015
2016
2017 int
sctp_asconf_iterator_ep(struct sctp_inpcb * inp,void * ptr,uint32_t val SCTP_UNUSED)2018 sctp_asconf_iterator_ep(struct sctp_inpcb *inp, void *ptr, uint32_t val SCTP_UNUSED)
2019 {
2020 struct sctp_asconf_iterator *asc;
2021 struct sctp_ifa *ifa;
2022 struct sctp_laddr *l;
2023 int cnt_invalid = 0;
2024
2025 asc = (struct sctp_asconf_iterator *)ptr;
2026 LIST_FOREACH(l, &asc->list_of_work, sctp_nxt_addr) {
2027 ifa = l->ifa;
2028 switch (ifa->address.sa.sa_family) {
2029 #ifdef INET6
2030 case AF_INET6:
2031 /* invalid if we're not a v6 endpoint */
2032 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) {
2033 cnt_invalid++;
2034 if (asc->cnt == cnt_invalid)
2035 return (1);
2036 }
2037 break;
2038 #endif
2039 #ifdef INET
2040 case AF_INET:
2041 {
2042 /* invalid if we are a v6 only endpoint */
2043 struct in6pcb *inp6;
2044 inp6 = (struct in6pcb *)&inp->ip_inp.inp;
2045 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
2046 SCTP_IPV6_V6ONLY(inp6)) {
2047 cnt_invalid++;
2048 if (asc->cnt == cnt_invalid)
2049 return (1);
2050 }
2051 break;
2052 }
2053 #endif
2054 default:
2055 /* invalid address family */
2056 cnt_invalid++;
2057 if (asc->cnt == cnt_invalid)
2058 return (1);
2059 }
2060 }
2061 return (0);
2062 }
2063
2064 static int
sctp_asconf_iterator_ep_end(struct sctp_inpcb * inp,void * ptr,uint32_t val SCTP_UNUSED)2065 sctp_asconf_iterator_ep_end(struct sctp_inpcb *inp, void *ptr, uint32_t val SCTP_UNUSED)
2066 {
2067 struct sctp_ifa *ifa;
2068 struct sctp_asconf_iterator *asc;
2069 struct sctp_laddr *laddr, *nladdr, *l;
2070
2071 /* Only for specific case not bound all */
2072 asc = (struct sctp_asconf_iterator *)ptr;
2073 LIST_FOREACH(l, &asc->list_of_work, sctp_nxt_addr) {
2074 ifa = l->ifa;
2075 if (l->action == SCTP_ADD_IP_ADDRESS) {
2076 LIST_FOREACH(laddr, &inp->sctp_addr_list,
2077 sctp_nxt_addr) {
2078 if (laddr->ifa == ifa) {
2079 laddr->action = 0;
2080 break;
2081 }
2082
2083 }
2084 } else if (l->action == SCTP_DEL_IP_ADDRESS) {
2085 LIST_FOREACH_SAFE(laddr, &inp->sctp_addr_list, sctp_nxt_addr, nladdr) {
2086 /* remove only after all guys are done */
2087 if (laddr->ifa == ifa) {
2088 sctp_del_local_addr_ep(inp, ifa);
2089 }
2090 }
2091 }
2092 }
2093 return (0);
2094 }
2095
2096 void
sctp_asconf_iterator_stcb(struct sctp_inpcb * inp,struct sctp_tcb * stcb,void * ptr,uint32_t val SCTP_UNUSED)2097 sctp_asconf_iterator_stcb(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
2098 void *ptr, uint32_t val SCTP_UNUSED)
2099 {
2100 struct sctp_asconf_iterator *asc;
2101 struct sctp_ifa *ifa;
2102 struct sctp_laddr *l;
2103 int cnt_invalid = 0;
2104 int type, status;
2105 int num_queued = 0;
2106
2107 asc = (struct sctp_asconf_iterator *)ptr;
2108 LIST_FOREACH(l, &asc->list_of_work, sctp_nxt_addr) {
2109 ifa = l->ifa;
2110 type = l->action;
2111
2112 /* address's vrf_id must be the vrf_id of the assoc */
2113 if (ifa->vrf_id != stcb->asoc.vrf_id) {
2114 continue;
2115 }
2116
2117 /* Same checks again for assoc */
2118 switch (ifa->address.sa.sa_family) {
2119 #ifdef INET6
2120 case AF_INET6:
2121 {
2122 /* invalid if we're not a v6 endpoint */
2123 struct sockaddr_in6 *sin6;
2124
2125 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) {
2126 cnt_invalid++;
2127 if (asc->cnt == cnt_invalid)
2128 return;
2129 else
2130 continue;
2131 }
2132 sin6 = (struct sockaddr_in6 *)&ifa->address.sin6;
2133 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
2134 /* we skip unspecifed addresses */
2135 continue;
2136 }
2137 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
2138 if (stcb->asoc.scope.local_scope == 0) {
2139 continue;
2140 }
2141 /* is it the right link local scope? */
2142 if (sctp_is_scopeid_in_nets(stcb, &ifa->address.sa) == 0) {
2143 continue;
2144 }
2145 }
2146 break;
2147 }
2148 #endif
2149 #ifdef INET
2150 case AF_INET:
2151 {
2152 /* invalid if we are a v6 only endpoint */
2153 struct in6pcb *inp6;
2154 struct sockaddr_in *sin;
2155
2156 inp6 = (struct in6pcb *)&inp->ip_inp.inp;
2157 /* invalid if we are a v6 only endpoint */
2158 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
2159 SCTP_IPV6_V6ONLY(inp6))
2160 continue;
2161
2162 sin = (struct sockaddr_in *)&ifa->address.sa;
2163 if (sin->sin_addr.s_addr == 0) {
2164 /* we skip unspecifed addresses */
2165 continue;
2166 }
2167 if (stcb->asoc.scope.ipv4_local_scope == 0 &&
2168 IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) {
2169 continue;
2170 }
2171 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
2172 SCTP_IPV6_V6ONLY(inp6)) {
2173 cnt_invalid++;
2174 if (asc->cnt == cnt_invalid)
2175 return;
2176 else
2177 continue;
2178 }
2179 break;
2180 }
2181 #endif
2182 default:
2183 /* invalid address family */
2184 cnt_invalid++;
2185 if (asc->cnt == cnt_invalid)
2186 return;
2187 else
2188 continue;
2189 break;
2190 }
2191
2192 if (type == SCTP_ADD_IP_ADDRESS) {
2193 /* prevent this address from being used as a source */
2194 sctp_add_local_addr_restricted(stcb, ifa);
2195 } else if (type == SCTP_DEL_IP_ADDRESS) {
2196 struct sctp_nets *net;
2197 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
2198 sctp_rtentry_t *rt;
2199
2200 /* delete this address if cached */
2201 if (net->ro._s_addr == ifa) {
2202 sctp_free_ifa(net->ro._s_addr);
2203 net->ro._s_addr = NULL;
2204 net->src_addr_selected = 0;
2205 rt = net->ro.ro_rt;
2206 if (rt) {
2207 RTFREE(rt);
2208 net->ro.ro_rt = NULL;
2209 }
2210 /*
2211 * Now we deleted our src address,
2212 * should we not also now reset the
2213 * cwnd/rto to start as if its a new
2214 * address?
2215 */
2216 stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb, net);
2217 net->RTO = 0;
2218
2219 }
2220 }
2221 } else if (type == SCTP_SET_PRIM_ADDR) {
2222 if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) {
2223 /* must validate the ifa is in the ep */
2224 if (sctp_is_addr_in_ep(stcb->sctp_ep,ifa) == 0) {
2225 continue;
2226 }
2227 } else {
2228 /* Need to check scopes for this guy */
2229 if (sctp_is_address_in_scope(ifa, &stcb->asoc.scope, 0) == 0) {
2230 continue;
2231 }
2232 }
2233 }
2234 /* queue an asconf for this address add/delete */
2235 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_DO_ASCONF) &&
2236 stcb->asoc.peer_supports_asconf) {
2237 /* queue an asconf for this addr */
2238 status = sctp_asconf_queue_add(stcb, ifa, type);
2239 /*
2240 * if queued ok, and in the open state, update the
2241 * count of queued params. If in the non-open state,
2242 * these get sent when the assoc goes open.
2243 */
2244 if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) {
2245 if (status >= 0) {
2246 num_queued++;
2247 }
2248 }
2249 }
2250 }
2251 /*
2252 * If we have queued params in the open state, send out an ASCONF.
2253 */
2254 if (num_queued > 0) {
2255 sctp_send_asconf(stcb, NULL, SCTP_ADDR_NOT_LOCKED);
2256 }
2257 }
2258
2259 void
sctp_asconf_iterator_end(void * ptr,uint32_t val SCTP_UNUSED)2260 sctp_asconf_iterator_end(void *ptr, uint32_t val SCTP_UNUSED)
2261 {
2262 struct sctp_asconf_iterator *asc;
2263 struct sctp_ifa *ifa;
2264 struct sctp_laddr *l, *nl;
2265
2266 asc = (struct sctp_asconf_iterator *)ptr;
2267 LIST_FOREACH_SAFE(l, &asc->list_of_work, sctp_nxt_addr, nl) {
2268 ifa = l->ifa;
2269 if (l->action == SCTP_ADD_IP_ADDRESS) {
2270 /* Clear the defer use flag */
2271 ifa->localifa_flags &= ~SCTP_ADDR_DEFER_USE;
2272 }
2273 sctp_free_ifa(ifa);
2274 SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_laddr), l);
2275 SCTP_DECR_LADDR_COUNT();
2276 }
2277 SCTP_FREE(asc, SCTP_M_ASC_IT);
2278 }
2279
2280 /*
2281 * sa is the sockaddr to ask the peer to set primary to.
2282 * returns: 0 = completed, -1 = error
2283 */
2284 int32_t
sctp_set_primary_ip_address_sa(struct sctp_tcb * stcb,struct sockaddr * sa)2285 sctp_set_primary_ip_address_sa(struct sctp_tcb *stcb, struct sockaddr *sa)
2286 {
2287 uint32_t vrf_id;
2288 struct sctp_ifa *ifa;
2289
2290 /* find the ifa for the desired set primary */
2291 vrf_id = stcb->asoc.vrf_id;
2292 ifa = sctp_find_ifa_by_addr(sa, vrf_id, SCTP_ADDR_NOT_LOCKED);
2293 if (ifa == NULL) {
2294 /* Invalid address */
2295 return (-1);
2296 }
2297
2298 /* queue an ASCONF:SET_PRIM_ADDR to be sent */
2299 if (!sctp_asconf_queue_add(stcb, ifa, SCTP_SET_PRIM_ADDR)) {
2300 /* set primary queuing succeeded */
2301 SCTPDBG(SCTP_DEBUG_ASCONF1,
2302 "set_primary_ip_address_sa: queued on tcb=%p, ",
2303 (void *)stcb);
2304 SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa);
2305 if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) {
2306 #ifdef SCTP_TIMER_BASED_ASCONF
2307 sctp_timer_start(SCTP_TIMER_TYPE_ASCONF,
2308 stcb->sctp_ep, stcb,
2309 stcb->asoc.primary_destination);
2310 #else
2311 sctp_send_asconf(stcb, NULL, SCTP_ADDR_NOT_LOCKED);
2312 #endif
2313 }
2314 } else {
2315 SCTPDBG(SCTP_DEBUG_ASCONF1, "set_primary_ip_address_sa: failed to add to queue on tcb=%p, ",
2316 (void *)stcb);
2317 SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa);
2318 return (-1);
2319 }
2320 return (0);
2321 }
2322
2323 void
sctp_set_primary_ip_address(struct sctp_ifa * ifa)2324 sctp_set_primary_ip_address(struct sctp_ifa *ifa)
2325 {
2326 struct sctp_inpcb *inp;
2327
2328 /* go through all our PCB's */
2329 LIST_FOREACH(inp, &SCTP_BASE_INFO(listhead), sctp_list) {
2330 struct sctp_tcb *stcb;
2331
2332 /* process for all associations for this endpoint */
2333 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
2334 /* queue an ASCONF:SET_PRIM_ADDR to be sent */
2335 if (!sctp_asconf_queue_add(stcb, ifa,
2336 SCTP_SET_PRIM_ADDR)) {
2337 /* set primary queuing succeeded */
2338 SCTPDBG(SCTP_DEBUG_ASCONF1, "set_primary_ip_address: queued on stcb=%p, ",
2339 (void *)stcb);
2340 SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, &ifa->address.sa);
2341 if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) {
2342 #ifdef SCTP_TIMER_BASED_ASCONF
2343 sctp_timer_start(SCTP_TIMER_TYPE_ASCONF,
2344 stcb->sctp_ep, stcb,
2345 stcb->asoc.primary_destination);
2346 #else
2347 sctp_send_asconf(stcb, NULL, SCTP_ADDR_NOT_LOCKED);
2348 #endif
2349 }
2350 }
2351 } /* for each stcb */
2352 } /* for each inp */
2353 }
2354
2355 int
sctp_is_addr_pending(struct sctp_tcb * stcb,struct sctp_ifa * sctp_ifa)2356 sctp_is_addr_pending(struct sctp_tcb *stcb, struct sctp_ifa *sctp_ifa)
2357 {
2358 struct sctp_tmit_chunk *chk, *nchk;
2359 unsigned int offset, asconf_limit;
2360 struct sctp_asconf_chunk *acp;
2361 struct sctp_asconf_paramhdr *aph;
2362 uint8_t aparam_buf[SCTP_PARAM_BUFFER_SIZE];
2363 struct sctp_paramhdr *ph;
2364 int add_cnt, del_cnt;
2365 uint16_t last_param_type;
2366
2367 add_cnt = del_cnt = 0;
2368 last_param_type = 0;
2369 TAILQ_FOREACH_SAFE(chk, &stcb->asoc.asconf_send_queue, sctp_next, nchk) {
2370 if (chk->data == NULL) {
2371 SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: No mbuf data?\n");
2372 continue;
2373 }
2374 offset = 0;
2375 acp = mtod(chk->data, struct sctp_asconf_chunk *);
2376 offset += sizeof(struct sctp_asconf_chunk);
2377 asconf_limit = ntohs(acp->ch.chunk_length);
2378 ph = (struct sctp_paramhdr *)sctp_m_getptr(chk->data, offset, sizeof(struct sctp_paramhdr), aparam_buf);
2379 if (ph == NULL) {
2380 SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: couldn't get lookup addr!\n");
2381 continue;
2382 }
2383 offset += ntohs(ph->param_length);
2384
2385 aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(chk->data, offset, sizeof(struct sctp_asconf_paramhdr), aparam_buf);
2386 if (aph == NULL) {
2387 SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: Empty ASCONF will be sent?\n");
2388 continue;
2389 }
2390 while (aph != NULL) {
2391 unsigned int param_length, param_type;
2392
2393 param_type = ntohs(aph->ph.param_type);
2394 param_length = ntohs(aph->ph.param_length);
2395 if (offset + param_length > asconf_limit) {
2396 /* parameter goes beyond end of chunk! */
2397 break;
2398 }
2399 if (param_length > sizeof(aparam_buf)) {
2400 SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: param length (%u) larger than buffer size!\n", param_length);
2401 break;
2402 }
2403 if (param_length <= sizeof(struct sctp_paramhdr)) {
2404 SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: param length(%u) too short\n", param_length);
2405 break;
2406 }
2407
2408 aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(chk->data, offset, param_length, aparam_buf);
2409 if (aph == NULL) {
2410 SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: couldn't get entire param\n");
2411 break;
2412 }
2413
2414 ph = (struct sctp_paramhdr *)(aph + 1);
2415 if (sctp_addr_match(ph, &sctp_ifa->address.sa) != 0) {
2416 switch (param_type) {
2417 case SCTP_ADD_IP_ADDRESS:
2418 add_cnt++;
2419 break;
2420 case SCTP_DEL_IP_ADDRESS:
2421 del_cnt++;
2422 break;
2423 default:
2424 break;
2425 }
2426 last_param_type = param_type;
2427 }
2428
2429 offset += SCTP_SIZE32(param_length);
2430 if (offset >= asconf_limit) {
2431 /* no more data in the mbuf chain */
2432 break;
2433 }
2434 /* get pointer to next asconf param */
2435 aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(chk->data, offset, sizeof(struct sctp_asconf_paramhdr), aparam_buf);
2436 }
2437 }
2438
2439 /* we want to find the sequences which consist of ADD -> DEL -> ADD or DEL -> ADD */
2440 if (add_cnt > del_cnt ||
2441 (add_cnt == del_cnt && last_param_type == SCTP_ADD_IP_ADDRESS)) {
2442 return (1);
2443 }
2444 return (0);
2445 }
2446
2447 static struct sockaddr *
sctp_find_valid_localaddr(struct sctp_tcb * stcb,int addr_locked)2448 sctp_find_valid_localaddr(struct sctp_tcb *stcb, int addr_locked)
2449 {
2450 struct sctp_vrf *vrf = NULL;
2451 struct sctp_ifn *sctp_ifn;
2452 struct sctp_ifa *sctp_ifa;
2453
2454 if (addr_locked == SCTP_ADDR_NOT_LOCKED)
2455 SCTP_IPI_ADDR_RLOCK();
2456 vrf = sctp_find_vrf(stcb->asoc.vrf_id);
2457 if (vrf == NULL) {
2458 if (addr_locked == SCTP_ADDR_NOT_LOCKED)
2459 SCTP_IPI_ADDR_RUNLOCK();
2460 return (NULL);
2461 }
2462 LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
2463 if (stcb->asoc.scope.loopback_scope == 0 &&
2464 SCTP_IFN_IS_IFT_LOOP(sctp_ifn)) {
2465 /* Skip if loopback_scope not set */
2466 continue;
2467 }
2468 LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
2469 switch (sctp_ifa->address.sa.sa_family) {
2470 #ifdef INET
2471 case AF_INET:
2472 if (stcb->asoc.scope.ipv4_addr_legal) {
2473 struct sockaddr_in *sin;
2474
2475 sin = (struct sockaddr_in *)&sctp_ifa->address.sa;
2476 if (sin->sin_addr.s_addr == 0) {
2477 /* skip unspecifed addresses */
2478 continue;
2479 }
2480 if (stcb->asoc.scope.ipv4_local_scope == 0 &&
2481 IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))
2482 continue;
2483
2484 if (sctp_is_addr_restricted(stcb, sctp_ifa) &&
2485 (!sctp_is_addr_pending(stcb, sctp_ifa)))
2486 continue;
2487 /* found a valid local v4 address to use */
2488 if (addr_locked == SCTP_ADDR_NOT_LOCKED)
2489 SCTP_IPI_ADDR_RUNLOCK();
2490 return (&sctp_ifa->address.sa);
2491 }
2492 break;
2493 #endif
2494 #ifdef INET6
2495 case AF_INET6:
2496 if (stcb->asoc.scope.ipv6_addr_legal) {
2497 struct sockaddr_in6 *sin6;
2498
2499 if (sctp_ifa->localifa_flags & SCTP_ADDR_IFA_UNUSEABLE) {
2500 continue;
2501 }
2502
2503 sin6 = (struct sockaddr_in6 *)&sctp_ifa->address.sa;
2504 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
2505 /* we skip unspecifed addresses */
2506 continue;
2507 }
2508 if (stcb->asoc.scope.local_scope == 0 &&
2509 IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
2510 continue;
2511 if (stcb->asoc.scope.site_scope == 0 &&
2512 IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))
2513 continue;
2514
2515 if (sctp_is_addr_restricted(stcb, sctp_ifa) &&
2516 (!sctp_is_addr_pending(stcb, sctp_ifa)))
2517 continue;
2518 /* found a valid local v6 address to use */
2519 if (addr_locked == SCTP_ADDR_NOT_LOCKED)
2520 SCTP_IPI_ADDR_RUNLOCK();
2521 return (&sctp_ifa->address.sa);
2522 }
2523 break;
2524 #endif
2525 default:
2526 break;
2527 }
2528 }
2529 }
2530 /* no valid addresses found */
2531 if (addr_locked == SCTP_ADDR_NOT_LOCKED)
2532 SCTP_IPI_ADDR_RUNLOCK();
2533 return (NULL);
2534 }
2535
2536 static struct sockaddr *
sctp_find_valid_localaddr_ep(struct sctp_tcb * stcb)2537 sctp_find_valid_localaddr_ep(struct sctp_tcb *stcb)
2538 {
2539 struct sctp_laddr *laddr;
2540
2541 LIST_FOREACH(laddr, &stcb->sctp_ep->sctp_addr_list, sctp_nxt_addr) {
2542 if (laddr->ifa == NULL) {
2543 continue;
2544 }
2545 /* is the address restricted ? */
2546 if (sctp_is_addr_restricted(stcb, laddr->ifa) &&
2547 (!sctp_is_addr_pending(stcb, laddr->ifa)))
2548 continue;
2549
2550 /* found a valid local address to use */
2551 return (&laddr->ifa->address.sa);
2552 }
2553 /* no valid addresses found */
2554 return (NULL);
2555 }
2556
2557 /*
2558 * builds an ASCONF chunk from queued ASCONF params.
2559 * returns NULL on error (no mbuf, no ASCONF params queued, etc).
2560 */
2561 struct mbuf *
sctp_compose_asconf(struct sctp_tcb * stcb,int * retlen,int addr_locked)2562 sctp_compose_asconf(struct sctp_tcb *stcb, int *retlen, int addr_locked)
2563 {
2564 struct mbuf *m_asconf, *m_asconf_chk;
2565 struct sctp_asconf_addr *aa;
2566 struct sctp_asconf_chunk *acp;
2567 struct sctp_asconf_paramhdr *aph;
2568 struct sctp_asconf_addr_param *aap;
2569 uint32_t p_length;
2570 uint32_t correlation_id = 1; /* 0 is reserved... */
2571 caddr_t ptr, lookup_ptr;
2572 uint8_t lookup_used = 0;
2573
2574 /* are there any asconf params to send? */
2575 TAILQ_FOREACH(aa, &stcb->asoc.asconf_queue, next) {
2576 if (aa->sent == 0)
2577 break;
2578 }
2579 if (aa == NULL)
2580 return (NULL);
2581
2582 /*
2583 * get a chunk header mbuf and a cluster for the asconf params since
2584 * it's simpler to fill in the asconf chunk header lookup address on
2585 * the fly
2586 */
2587 m_asconf_chk = sctp_get_mbuf_for_msg(sizeof(struct sctp_asconf_chunk), 0, M_NOWAIT, 1, MT_DATA);
2588 if (m_asconf_chk == NULL) {
2589 /* no mbuf's */
2590 SCTPDBG(SCTP_DEBUG_ASCONF1,
2591 "compose_asconf: couldn't get chunk mbuf!\n");
2592 return (NULL);
2593 }
2594 m_asconf = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_NOWAIT, 1, MT_DATA);
2595 if (m_asconf == NULL) {
2596 /* no mbuf's */
2597 SCTPDBG(SCTP_DEBUG_ASCONF1,
2598 "compose_asconf: couldn't get mbuf!\n");
2599 sctp_m_freem(m_asconf_chk);
2600 return (NULL);
2601 }
2602 SCTP_BUF_LEN(m_asconf_chk) = sizeof(struct sctp_asconf_chunk);
2603 SCTP_BUF_LEN(m_asconf) = 0;
2604 acp = mtod(m_asconf_chk, struct sctp_asconf_chunk *);
2605 bzero(acp, sizeof(struct sctp_asconf_chunk));
2606 /* save pointers to lookup address and asconf params */
2607 lookup_ptr = (caddr_t)(acp + 1); /* after the header */
2608 ptr = mtod(m_asconf, caddr_t); /* beginning of cluster */
2609
2610 /* fill in chunk header info */
2611 acp->ch.chunk_type = SCTP_ASCONF;
2612 acp->ch.chunk_flags = 0;
2613 acp->serial_number = htonl(stcb->asoc.asconf_seq_out);
2614 stcb->asoc.asconf_seq_out++;
2615
2616 /* add parameters... up to smallest MTU allowed */
2617 TAILQ_FOREACH(aa, &stcb->asoc.asconf_queue, next) {
2618 if (aa->sent)
2619 continue;
2620 /* get the parameter length */
2621 p_length = SCTP_SIZE32(aa->ap.aph.ph.param_length);
2622 /* will it fit in current chunk? */
2623 if ((SCTP_BUF_LEN(m_asconf) + p_length > stcb->asoc.smallest_mtu) ||
2624 (SCTP_BUF_LEN(m_asconf) + p_length > MCLBYTES)) {
2625 /* won't fit, so we're done with this chunk */
2626 break;
2627 }
2628 /* assign (and store) a correlation id */
2629 aa->ap.aph.correlation_id = correlation_id++;
2630
2631 /*
2632 * fill in address if we're doing a delete this is a simple
2633 * way for us to fill in the correlation address, which
2634 * should only be used by the peer if we're deleting our
2635 * source address and adding a new address (e.g. renumbering
2636 * case)
2637 */
2638 if (lookup_used == 0 &&
2639 (aa->special_del == 0) &&
2640 aa->ap.aph.ph.param_type == SCTP_DEL_IP_ADDRESS) {
2641 struct sctp_ipv6addr_param *lookup;
2642 uint16_t p_size, addr_size;
2643
2644 lookup = (struct sctp_ipv6addr_param *)lookup_ptr;
2645 lookup->ph.param_type =
2646 htons(aa->ap.addrp.ph.param_type);
2647 if (aa->ap.addrp.ph.param_type == SCTP_IPV6_ADDRESS) {
2648 /* copy IPv6 address */
2649 p_size = sizeof(struct sctp_ipv6addr_param);
2650 addr_size = sizeof(struct in6_addr);
2651 } else {
2652 /* copy IPv4 address */
2653 p_size = sizeof(struct sctp_ipv4addr_param);
2654 addr_size = sizeof(struct in_addr);
2655 }
2656 lookup->ph.param_length = htons(SCTP_SIZE32(p_size));
2657 memcpy(lookup->addr, &aa->ap.addrp.addr, addr_size);
2658 SCTP_BUF_LEN(m_asconf_chk) += SCTP_SIZE32(p_size);
2659 lookup_used = 1;
2660 }
2661 /* copy into current space */
2662 memcpy(ptr, &aa->ap, p_length);
2663
2664 /* network elements and update lengths */
2665 aph = (struct sctp_asconf_paramhdr *)ptr;
2666 aap = (struct sctp_asconf_addr_param *)ptr;
2667 /* correlation_id is transparent to peer, no htonl needed */
2668 aph->ph.param_type = htons(aph->ph.param_type);
2669 aph->ph.param_length = htons(aph->ph.param_length);
2670 aap->addrp.ph.param_type = htons(aap->addrp.ph.param_type);
2671 aap->addrp.ph.param_length = htons(aap->addrp.ph.param_length);
2672
2673 SCTP_BUF_LEN(m_asconf) += SCTP_SIZE32(p_length);
2674 ptr += SCTP_SIZE32(p_length);
2675
2676 /*
2677 * these params are removed off the pending list upon
2678 * getting an ASCONF-ACK back from the peer, just set flag
2679 */
2680 aa->sent = 1;
2681 }
2682 /* check to see if the lookup addr has been populated yet */
2683 if (lookup_used == 0) {
2684 /* NOTE: if the address param is optional, can skip this... */
2685 /* add any valid (existing) address... */
2686 struct sctp_ipv6addr_param *lookup;
2687 uint16_t p_size, addr_size;
2688 struct sockaddr *found_addr;
2689 caddr_t addr_ptr;
2690
2691 if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL)
2692 found_addr = sctp_find_valid_localaddr(stcb,
2693 addr_locked);
2694 else
2695 found_addr = sctp_find_valid_localaddr_ep(stcb);
2696
2697 lookup = (struct sctp_ipv6addr_param *)lookup_ptr;
2698 if (found_addr != NULL) {
2699 switch (found_addr->sa_family) {
2700 #ifdef INET6
2701 case AF_INET6:
2702 /* copy IPv6 address */
2703 lookup->ph.param_type =
2704 htons(SCTP_IPV6_ADDRESS);
2705 p_size = sizeof(struct sctp_ipv6addr_param);
2706 addr_size = sizeof(struct in6_addr);
2707 addr_ptr = (caddr_t)&((struct sockaddr_in6 *)
2708 found_addr)->sin6_addr;
2709 break;
2710 #endif
2711 #ifdef INET
2712 case AF_INET:
2713 /* copy IPv4 address */
2714 lookup->ph.param_type =
2715 htons(SCTP_IPV4_ADDRESS);
2716 p_size = sizeof(struct sctp_ipv4addr_param);
2717 addr_size = sizeof(struct in_addr);
2718 addr_ptr = (caddr_t)&((struct sockaddr_in *)
2719 found_addr)->sin_addr;
2720 break;
2721 #endif
2722 default:
2723 p_size = 0;
2724 addr_size = 0;
2725 addr_ptr = NULL;
2726 break;
2727 }
2728 lookup->ph.param_length = htons(SCTP_SIZE32(p_size));
2729 memcpy(lookup->addr, addr_ptr, addr_size);
2730 SCTP_BUF_LEN(m_asconf_chk) += SCTP_SIZE32(p_size);
2731 } else {
2732 /* uh oh... don't have any address?? */
2733 SCTPDBG(SCTP_DEBUG_ASCONF1,
2734 "compose_asconf: no lookup addr!\n");
2735 /* XXX for now, we send a IPv4 address of 0.0.0.0 */
2736 lookup->ph.param_type = htons(SCTP_IPV4_ADDRESS);
2737 lookup->ph.param_length = htons(SCTP_SIZE32(sizeof(struct sctp_ipv4addr_param)));
2738 bzero(lookup->addr, sizeof(struct in_addr));
2739 SCTP_BUF_LEN(m_asconf_chk) += SCTP_SIZE32(sizeof(struct sctp_ipv4addr_param));
2740 }
2741 }
2742 /* chain it all together */
2743 SCTP_BUF_NEXT(m_asconf_chk) = m_asconf;
2744 *retlen = SCTP_BUF_LEN(m_asconf_chk) + SCTP_BUF_LEN(m_asconf);
2745 acp->ch.chunk_length = htons(*retlen);
2746
2747 return (m_asconf_chk);
2748 }
2749
2750 /*
2751 * section to handle address changes before an association is up eg. changes
2752 * during INIT/INIT-ACK/COOKIE-ECHO handshake
2753 */
2754
2755 /*
2756 * processes the (local) addresses in the INIT-ACK chunk
2757 */
2758 static void
sctp_process_initack_addresses(struct sctp_tcb * stcb,struct mbuf * m,unsigned int offset,unsigned int length)2759 sctp_process_initack_addresses(struct sctp_tcb *stcb, struct mbuf *m,
2760 unsigned int offset, unsigned int length)
2761 {
2762 struct sctp_paramhdr tmp_param, *ph;
2763 uint16_t plen, ptype;
2764 struct sctp_ifa *sctp_ifa;
2765 #ifdef INET6
2766 struct sctp_ipv6addr_param addr6_store;
2767 struct sockaddr_in6 sin6;
2768 #endif
2769 #ifdef INET
2770 struct sctp_ipv4addr_param addr4_store;
2771 struct sockaddr_in sin;
2772 #endif
2773 struct sockaddr *sa;
2774 uint32_t vrf_id;
2775
2776 SCTPDBG(SCTP_DEBUG_ASCONF2, "processing init-ack addresses\n");
2777 if (stcb == NULL) /* Un-needed check for SA */
2778 return;
2779
2780 /* convert to upper bound */
2781 length += offset;
2782
2783 if ((offset + sizeof(struct sctp_paramhdr)) > length) {
2784 return;
2785 }
2786 /* init the addresses */
2787 #ifdef INET6
2788 bzero(&sin6, sizeof(sin6));
2789 sin6.sin6_family = AF_INET6;
2790 #ifdef HAVE_SIN6_LEN
2791 sin6.sin6_len = sizeof(sin6);
2792 #endif
2793 sin6.sin6_port = stcb->rport;
2794 #endif
2795
2796 #ifdef INET
2797 bzero(&sin, sizeof(sin));
2798 sin.sin_family = AF_INET;
2799 #ifdef HAVE_SIN_LEN
2800 sin.sin_len = sizeof(sin);
2801 #endif
2802 sin.sin_port = stcb->rport;
2803 #endif
2804
2805 /* go through the addresses in the init-ack */
2806 ph = (struct sctp_paramhdr *)
2807 sctp_m_getptr(m, offset, sizeof(struct sctp_paramhdr),
2808 (uint8_t *)&tmp_param);
2809 while (ph != NULL) {
2810 ptype = ntohs(ph->param_type);
2811 plen = ntohs(ph->param_length);
2812 switch (ptype) {
2813 #ifdef INET6
2814 case SCTP_IPV6_ADDRESS:
2815 {
2816 struct sctp_ipv6addr_param *a6p;
2817
2818 /* get the entire IPv6 address param */
2819 a6p = (struct sctp_ipv6addr_param *)
2820 sctp_m_getptr(m, offset,
2821 sizeof(struct sctp_ipv6addr_param),
2822 (uint8_t *)&addr6_store);
2823 if (plen != sizeof(struct sctp_ipv6addr_param) ||
2824 a6p == NULL) {
2825 return;
2826 }
2827 memcpy(&sin6.sin6_addr, a6p->addr,
2828 sizeof(struct in6_addr));
2829 sa = (struct sockaddr *)&sin6;
2830 break;
2831 }
2832 #endif
2833 #ifdef INET
2834 case SCTP_IPV4_ADDRESS:
2835 {
2836 struct sctp_ipv4addr_param *a4p;
2837
2838 /* get the entire IPv4 address param */
2839 a4p = (struct sctp_ipv4addr_param *)sctp_m_getptr(m, offset,
2840 sizeof(struct sctp_ipv4addr_param),
2841 (uint8_t *)&addr4_store);
2842 if (plen != sizeof(struct sctp_ipv4addr_param) ||
2843 a4p == NULL) {
2844 return;
2845 }
2846 sin.sin_addr.s_addr = a4p->addr;
2847 sa = (struct sockaddr *)&sin;
2848 break;
2849 }
2850 #endif
2851 default:
2852 goto next_addr;
2853 }
2854
2855 /* see if this address really (still) exists */
2856 if (stcb) {
2857 vrf_id = stcb->asoc.vrf_id;
2858 } else {
2859 vrf_id = SCTP_DEFAULT_VRFID;
2860 }
2861 sctp_ifa = sctp_find_ifa_by_addr(sa, vrf_id,
2862 SCTP_ADDR_NOT_LOCKED);
2863 if (sctp_ifa == NULL) {
2864 /* address doesn't exist anymore */
2865 int status;
2866
2867 /* are ASCONFs allowed ? */
2868 if ((sctp_is_feature_on(stcb->sctp_ep,
2869 SCTP_PCB_FLAGS_DO_ASCONF)) &&
2870 stcb->asoc.peer_supports_asconf) {
2871 /* queue an ASCONF DEL_IP_ADDRESS */
2872 status = sctp_asconf_queue_sa_delete(stcb, sa);
2873 /*
2874 * if queued ok, and in correct state, send
2875 * out the ASCONF.
2876 */
2877 if (status == 0 &&
2878 SCTP_GET_STATE(&stcb->asoc) ==
2879 SCTP_STATE_OPEN) {
2880 #ifdef SCTP_TIMER_BASED_ASCONF
2881 sctp_timer_start(SCTP_TIMER_TYPE_ASCONF,
2882 stcb->sctp_ep, stcb,
2883 stcb->asoc.primary_destination);
2884 #else
2885 sctp_send_asconf(stcb, NULL, SCTP_ADDR_NOT_LOCKED);
2886 #endif
2887 }
2888 }
2889 }
2890
2891 next_addr:
2892 /*
2893 * Sanity check: Make sure the length isn't 0, otherwise
2894 * we'll be stuck in this loop for a long time...
2895 */
2896 if (SCTP_SIZE32(plen) == 0) {
2897 SCTP_PRINTF("process_initack_addrs: bad len (%d) type=%xh\n",
2898 plen, ptype);
2899 return;
2900 }
2901 /* get next parameter */
2902 offset += SCTP_SIZE32(plen);
2903 if ((offset + sizeof(struct sctp_paramhdr)) > length)
2904 return;
2905 ph = (struct sctp_paramhdr *)sctp_m_getptr(m, offset,
2906 sizeof(struct sctp_paramhdr), (uint8_t *) & tmp_param);
2907 } /* while */
2908 }
2909
2910 /* FIX ME: need to verify return result for v6 address type if v6 disabled */
2911 /*
2912 * checks to see if a specific address is in the initack address list returns
2913 * 1 if found, 0 if not
2914 */
2915 static uint32_t
sctp_addr_in_initack(struct mbuf * m,uint32_t offset,uint32_t length,struct sockaddr * sa)2916 sctp_addr_in_initack(struct mbuf *m, uint32_t offset, uint32_t length, struct sockaddr *sa)
2917 {
2918 struct sctp_paramhdr tmp_param, *ph;
2919 uint16_t plen, ptype;
2920 #ifdef INET
2921 struct sockaddr_in *sin;
2922 struct sctp_ipv4addr_param *a4p;
2923 struct sctp_ipv6addr_param addr4_store;
2924 #endif
2925 #ifdef INET6
2926 struct sockaddr_in6 *sin6;
2927 struct sctp_ipv6addr_param *a6p;
2928 struct sctp_ipv6addr_param addr6_store;
2929 #ifdef SCTP_EMBEDDED_V6_SCOPE
2930 struct sockaddr_in6 sin6_tmp;
2931 #endif
2932 #endif
2933
2934 switch (sa->sa_family) {
2935 #ifdef INET
2936 case AF_INET:
2937 break;
2938 #endif
2939 #ifdef INET6
2940 case AF_INET6:
2941 break;
2942 #endif
2943 default:
2944 return (0);
2945 }
2946
2947 SCTPDBG(SCTP_DEBUG_ASCONF2, "find_initack_addr: starting search for ");
2948 SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, sa);
2949 /* convert to upper bound */
2950 length += offset;
2951
2952 if ((offset + sizeof(struct sctp_paramhdr)) > length) {
2953 SCTPDBG(SCTP_DEBUG_ASCONF1,
2954 "find_initack_addr: invalid offset?\n");
2955 return (0);
2956 }
2957 /* go through the addresses in the init-ack */
2958 ph = (struct sctp_paramhdr *)sctp_m_getptr(m, offset,
2959 sizeof(struct sctp_paramhdr), (uint8_t *) & tmp_param);
2960 while (ph != NULL) {
2961 ptype = ntohs(ph->param_type);
2962 plen = ntohs(ph->param_length);
2963 switch (ptype) {
2964 #ifdef INET6
2965 case SCTP_IPV6_ADDRESS:
2966 if (sa->sa_family == AF_INET6) {
2967 /* get the entire IPv6 address param */
2968 if (plen != sizeof(struct sctp_ipv6addr_param)) {
2969 break;
2970 }
2971 /* get the entire IPv6 address param */
2972 a6p = (struct sctp_ipv6addr_param *)
2973 sctp_m_getptr(m, offset,
2974 sizeof(struct sctp_ipv6addr_param),
2975 (uint8_t *)&addr6_store);
2976 if (a6p == NULL) {
2977 return (0);
2978 }
2979 sin6 = (struct sockaddr_in6 *)sa;
2980 #ifdef SCTP_EMBEDDED_V6_SCOPE
2981 if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr)) {
2982 /* create a copy and clear scope */
2983 memcpy(&sin6_tmp, sin6,
2984 sizeof(struct sockaddr_in6));
2985 sin6 = &sin6_tmp;
2986 in6_clearscope(&sin6->sin6_addr);
2987 }
2988 #endif /* SCTP_EMBEDDED_V6_SCOPE */
2989 if (memcmp(&sin6->sin6_addr, a6p->addr,
2990 sizeof(struct in6_addr)) == 0) {
2991 /* found it */
2992 return (1);
2993 }
2994 }
2995 break;
2996 #endif /* INET6 */
2997 #ifdef INET
2998 case SCTP_IPV4_ADDRESS:
2999 if (sa->sa_family == AF_INET) {
3000 if (plen != sizeof(struct sctp_ipv4addr_param)) {
3001 break;
3002 }
3003 /* get the entire IPv4 address param */
3004 a4p = (struct sctp_ipv4addr_param *)
3005 sctp_m_getptr(m, offset,
3006 sizeof(struct sctp_ipv4addr_param),
3007 (uint8_t *)&addr4_store);
3008 if (a4p == NULL) {
3009 return (0);
3010 }
3011 sin = (struct sockaddr_in *)sa;
3012 if (sin->sin_addr.s_addr == a4p->addr) {
3013 /* found it */
3014 return (1);
3015 }
3016 }
3017 break;
3018 #endif
3019 default:
3020 break;
3021 }
3022 /* get next parameter */
3023 offset += SCTP_SIZE32(plen);
3024 if (offset + sizeof(struct sctp_paramhdr) > length) {
3025 return (0);
3026 }
3027 ph = (struct sctp_paramhdr *)
3028 sctp_m_getptr(m, offset, sizeof(struct sctp_paramhdr),
3029 (uint8_t *) & tmp_param);
3030 } /* while */
3031 /* not found! */
3032 return (0);
3033 }
3034
3035 /*
3036 * makes sure that the current endpoint local addr list is consistent with
3037 * the new association (eg. subset bound, asconf allowed) adds addresses as
3038 * necessary
3039 */
3040 static void
sctp_check_address_list_ep(struct sctp_tcb * stcb,struct mbuf * m,int offset,int length,struct sockaddr * init_addr)3041 sctp_check_address_list_ep(struct sctp_tcb *stcb, struct mbuf *m, int offset,
3042 int length, struct sockaddr *init_addr)
3043 {
3044 struct sctp_laddr *laddr;
3045
3046 /* go through the endpoint list */
3047 LIST_FOREACH(laddr, &stcb->sctp_ep->sctp_addr_list, sctp_nxt_addr) {
3048 /* be paranoid and validate the laddr */
3049 if (laddr->ifa == NULL) {
3050 SCTPDBG(SCTP_DEBUG_ASCONF1,
3051 "check_addr_list_ep: laddr->ifa is NULL");
3052 continue;
3053 }
3054 if (laddr->ifa == NULL) {
3055 SCTPDBG(SCTP_DEBUG_ASCONF1, "check_addr_list_ep: laddr->ifa->ifa_addr is NULL");
3056 continue;
3057 }
3058 /* do i have it implicitly? */
3059 if (sctp_cmpaddr(&laddr->ifa->address.sa, init_addr)) {
3060 continue;
3061 }
3062 /* check to see if in the init-ack */
3063 if (!sctp_addr_in_initack(m, offset, length, &laddr->ifa->address.sa)) {
3064 /* try to add it */
3065 sctp_addr_mgmt_assoc(stcb->sctp_ep, stcb, laddr->ifa,
3066 SCTP_ADD_IP_ADDRESS, SCTP_ADDR_NOT_LOCKED);
3067 }
3068 }
3069 }
3070
3071 /*
3072 * makes sure that the current kernel address list is consistent with the new
3073 * association (with all addrs bound) adds addresses as necessary
3074 */
3075 static void
sctp_check_address_list_all(struct sctp_tcb * stcb,struct mbuf * m,int offset,int length,struct sockaddr * init_addr,uint16_t local_scope,uint16_t site_scope,uint16_t ipv4_scope,uint16_t loopback_scope)3076 sctp_check_address_list_all(struct sctp_tcb *stcb, struct mbuf *m, int offset,
3077 int length, struct sockaddr *init_addr,
3078 uint16_t local_scope, uint16_t site_scope,
3079 uint16_t ipv4_scope, uint16_t loopback_scope)
3080 {
3081 struct sctp_vrf *vrf = NULL;
3082 struct sctp_ifn *sctp_ifn;
3083 struct sctp_ifa *sctp_ifa;
3084 uint32_t vrf_id;
3085 #ifdef INET
3086 struct sockaddr_in *sin;
3087 #endif
3088 #ifdef INET6
3089 struct sockaddr_in6 *sin6;
3090 #endif
3091
3092 if (stcb) {
3093 vrf_id = stcb->asoc.vrf_id;
3094 } else {
3095 return;
3096 }
3097 SCTP_IPI_ADDR_RLOCK();
3098 vrf = sctp_find_vrf(vrf_id);
3099 if (vrf == NULL) {
3100 SCTP_IPI_ADDR_RUNLOCK();
3101 return;
3102 }
3103 /* go through all our known interfaces */
3104 LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
3105 if (loopback_scope == 0 && SCTP_IFN_IS_IFT_LOOP(sctp_ifn)) {
3106 /* skip loopback interface */
3107 continue;
3108 }
3109 /* go through each interface address */
3110 LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
3111 /* do i have it implicitly? */
3112 if (sctp_cmpaddr(&sctp_ifa->address.sa, init_addr)) {
3113 continue;
3114 }
3115 switch (sctp_ifa->address.sa.sa_family) {
3116 #ifdef INET
3117 case AF_INET:
3118 sin = (struct sockaddr_in *)&sctp_ifa->address.sin;
3119 if ((ipv4_scope == 0) &&
3120 (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))) {
3121 /* private address not in scope */
3122 continue;
3123 }
3124 break;
3125 #endif
3126 #ifdef INET6
3127 case AF_INET6:
3128 sin6 = (struct sockaddr_in6 *)&sctp_ifa->address.sin6;
3129 if ((local_scope == 0) &&
3130 (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))) {
3131 continue;
3132 }
3133 if ((site_scope == 0) &&
3134 (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))) {
3135 continue;
3136 }
3137 break;
3138 #endif
3139 default:
3140 break;
3141 }
3142 /* check to see if in the init-ack */
3143 if (!sctp_addr_in_initack(m, offset, length, &sctp_ifa->address.sa)) {
3144 /* try to add it */
3145 sctp_addr_mgmt_assoc(stcb->sctp_ep, stcb,
3146 sctp_ifa, SCTP_ADD_IP_ADDRESS,
3147 SCTP_ADDR_LOCKED);
3148 }
3149 } /* end foreach ifa */
3150 } /* end foreach ifn */
3151 SCTP_IPI_ADDR_RUNLOCK();
3152 }
3153
3154 /*
3155 * validates an init-ack chunk (from a cookie-echo) with current addresses
3156 * adds addresses from the init-ack into our local address list, if needed
3157 * queues asconf adds/deletes addresses as needed and makes appropriate list
3158 * changes for source address selection m, offset: points to the start of the
3159 * address list in an init-ack chunk length: total length of the address
3160 * params only init_addr: address where my INIT-ACK was sent from
3161 */
3162 void
sctp_check_address_list(struct sctp_tcb * stcb,struct mbuf * m,int offset,int length,struct sockaddr * init_addr,uint16_t local_scope,uint16_t site_scope,uint16_t ipv4_scope,uint16_t loopback_scope)3163 sctp_check_address_list(struct sctp_tcb *stcb, struct mbuf *m, int offset,
3164 int length, struct sockaddr *init_addr,
3165 uint16_t local_scope, uint16_t site_scope,
3166 uint16_t ipv4_scope, uint16_t loopback_scope)
3167 {
3168 /* process the local addresses in the initack */
3169 sctp_process_initack_addresses(stcb, m, offset, length);
3170
3171 if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
3172 /* bound all case */
3173 sctp_check_address_list_all(stcb, m, offset, length, init_addr,
3174 local_scope, site_scope, ipv4_scope, loopback_scope);
3175 } else {
3176 /* subset bound case */
3177 if (sctp_is_feature_on(stcb->sctp_ep,
3178 SCTP_PCB_FLAGS_DO_ASCONF)) {
3179 /* asconf's allowed */
3180 sctp_check_address_list_ep(stcb, m, offset, length,
3181 init_addr);
3182 }
3183 /* else, no asconfs allowed, so what we sent is what we get */
3184 }
3185 }
3186
3187 /*
3188 * sctp_bindx() support
3189 */
3190 uint32_t
sctp_addr_mgmt_ep_sa(struct sctp_inpcb * inp,struct sockaddr * sa,uint32_t type,uint32_t vrf_id,struct sctp_ifa * sctp_ifap)3191 sctp_addr_mgmt_ep_sa(struct sctp_inpcb *inp, struct sockaddr *sa,
3192 uint32_t type, uint32_t vrf_id, struct sctp_ifa *sctp_ifap)
3193 {
3194 struct sctp_ifa *ifa;
3195 struct sctp_laddr *laddr, *nladdr;
3196
3197 #ifdef HAVE_SA_LEN
3198 if (sa->sa_len == 0) {
3199 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_ASCONF, EINVAL);
3200 return (EINVAL);
3201 }
3202 #endif
3203 if (sctp_ifap) {
3204 ifa = sctp_ifap;
3205 } else if (type == SCTP_ADD_IP_ADDRESS) {
3206 /* For an add the address MUST be on the system */
3207 ifa = sctp_find_ifa_by_addr(sa, vrf_id, SCTP_ADDR_NOT_LOCKED);
3208 } else if (type == SCTP_DEL_IP_ADDRESS) {
3209 /* For a delete we need to find it in the inp */
3210 ifa = sctp_find_ifa_in_ep(inp, sa, SCTP_ADDR_NOT_LOCKED);
3211 } else {
3212 ifa = NULL;
3213 }
3214 if (ifa != NULL) {
3215 if (type == SCTP_ADD_IP_ADDRESS) {
3216 sctp_add_local_addr_ep(inp, ifa, type);
3217 } else if (type == SCTP_DEL_IP_ADDRESS) {
3218 if (inp->laddr_count < 2) {
3219 /* can't delete the last local address */
3220 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_ASCONF, EINVAL);
3221 return (EINVAL);
3222 }
3223 LIST_FOREACH(laddr, &inp->sctp_addr_list,
3224 sctp_nxt_addr) {
3225 if (ifa == laddr->ifa) {
3226 /* Mark in the delete */
3227 laddr->action = type;
3228 }
3229 }
3230 }
3231 if (LIST_EMPTY(&inp->sctp_asoc_list)) {
3232 /*
3233 * There is no need to start the iterator if
3234 * the inp has no associations.
3235 */
3236 if (type == SCTP_DEL_IP_ADDRESS) {
3237 LIST_FOREACH_SAFE(laddr, &inp->sctp_addr_list, sctp_nxt_addr, nladdr) {
3238 if (laddr->ifa == ifa) {
3239 sctp_del_local_addr_ep(inp, ifa);
3240 }
3241 }
3242 }
3243 } else {
3244 struct sctp_asconf_iterator *asc;
3245 struct sctp_laddr *wi;
3246
3247 SCTP_MALLOC(asc, struct sctp_asconf_iterator *,
3248 sizeof(struct sctp_asconf_iterator),
3249 SCTP_M_ASC_IT);
3250 if (asc == NULL) {
3251 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_ASCONF, ENOMEM);
3252 return (ENOMEM);
3253 }
3254 wi = SCTP_ZONE_GET(SCTP_BASE_INFO(ipi_zone_laddr), struct sctp_laddr);
3255 if (wi == NULL) {
3256 SCTP_FREE(asc, SCTP_M_ASC_IT);
3257 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_ASCONF, ENOMEM);
3258 return (ENOMEM);
3259 }
3260 LIST_INIT(&asc->list_of_work);
3261 asc->cnt = 1;
3262 SCTP_INCR_LADDR_COUNT();
3263 wi->ifa = ifa;
3264 wi->action = type;
3265 atomic_add_int(&ifa->refcount, 1);
3266 LIST_INSERT_HEAD(&asc->list_of_work, wi, sctp_nxt_addr);
3267 (void)sctp_initiate_iterator(sctp_asconf_iterator_ep,
3268 sctp_asconf_iterator_stcb,
3269 sctp_asconf_iterator_ep_end,
3270 SCTP_PCB_ANY_FLAGS,
3271 SCTP_PCB_ANY_FEATURES,
3272 SCTP_ASOC_ANY_STATE,
3273 (void *)asc, 0,
3274 sctp_asconf_iterator_end, inp, 0);
3275 }
3276 return (0);
3277 } else {
3278 /* invalid address! */
3279 SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_ASCONF, EADDRNOTAVAIL);
3280 return (EADDRNOTAVAIL);
3281 }
3282 }
3283
3284 void
sctp_asconf_send_nat_state_update(struct sctp_tcb * stcb,struct sctp_nets * net)3285 sctp_asconf_send_nat_state_update(struct sctp_tcb *stcb,
3286 struct sctp_nets *net)
3287 {
3288 struct sctp_asconf_addr *aa;
3289 struct sctp_ifa *sctp_ifap;
3290 struct sctp_asconf_tag_param *vtag;
3291 #ifdef INET
3292 struct sockaddr_in *to;
3293 #endif
3294 #ifdef INET6
3295 struct sockaddr_in6 *to6;
3296 #endif
3297 if (net == NULL) {
3298 SCTPDBG(SCTP_DEBUG_ASCONF1, "sctp_asconf_send_nat_state_update: Missing net\n");
3299 return;
3300 }
3301 if (stcb == NULL) {
3302 SCTPDBG(SCTP_DEBUG_ASCONF1, "sctp_asconf_send_nat_state_update: Missing stcb\n");
3303 return;
3304 }
3305 /* Need to have in the asconf:
3306 * - vtagparam(my_vtag/peer_vtag)
3307 * - add(0.0.0.0)
3308 * - del(0.0.0.0)
3309 * - Any global addresses add(addr)
3310 */
3311 SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa),
3312 SCTP_M_ASC_ADDR);
3313 if (aa == NULL) {
3314 /* didn't get memory */
3315 SCTPDBG(SCTP_DEBUG_ASCONF1,
3316 "sctp_asconf_send_nat_state_update: failed to get memory!\n");
3317 return;
3318 }
3319 aa->special_del = 0;
3320 /* fill in asconf address parameter fields */
3321 /* top level elements are "networked" during send */
3322 aa->ifa = NULL;
3323 aa->sent = 0; /* clear sent flag */
3324 vtag = (struct sctp_asconf_tag_param *)&aa->ap.aph;
3325 vtag->aph.ph.param_type = SCTP_NAT_VTAGS;
3326 vtag->aph.ph.param_length = sizeof(struct sctp_asconf_tag_param);
3327 vtag->local_vtag = htonl(stcb->asoc.my_vtag);
3328 vtag->remote_vtag = htonl(stcb->asoc.peer_vtag);
3329 TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next);
3330
3331 SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa),
3332 SCTP_M_ASC_ADDR);
3333 if (aa == NULL) {
3334 /* didn't get memory */
3335 SCTPDBG(SCTP_DEBUG_ASCONF1,
3336 "sctp_asconf_send_nat_state_update: failed to get memory!\n");
3337 return;
3338 }
3339 memset(aa, 0, sizeof(struct sctp_asconf_addr));
3340 /* fill in asconf address parameter fields */
3341 /* ADD(0.0.0.0) */
3342 switch (net->ro._l_addr.sa.sa_family) {
3343 #ifdef INET
3344 case AF_INET:
3345 aa->ap.aph.ph.param_type = SCTP_ADD_IP_ADDRESS;
3346 aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_addrv4_param);
3347 aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS;
3348 aa->ap.addrp.ph.param_length = sizeof (struct sctp_ipv4addr_param);
3349 /* No need to add an address, we are using 0.0.0.0 */
3350 TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next);
3351 break;
3352 #endif
3353 #ifdef INET6
3354 case AF_INET6:
3355 aa->ap.aph.ph.param_type = SCTP_ADD_IP_ADDRESS;
3356 aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_addr_param);
3357 aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS;
3358 aa->ap.addrp.ph.param_length = sizeof (struct sctp_ipv6addr_param);
3359 /* No need to add an address, we are using 0.0.0.0 */
3360 TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next);
3361 break;
3362 #endif
3363 }
3364 SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa),
3365 SCTP_M_ASC_ADDR);
3366 if (aa == NULL) {
3367 /* didn't get memory */
3368 SCTPDBG(SCTP_DEBUG_ASCONF1,
3369 "sctp_asconf_send_nat_state_update: failed to get memory!\n");
3370 return;
3371 }
3372 memset(aa, 0, sizeof(struct sctp_asconf_addr));
3373 /* fill in asconf address parameter fields */
3374 /* ADD(0.0.0.0) */
3375 switch (net->ro._l_addr.sa.sa_family) {
3376 #ifdef INET
3377 case AF_INET:
3378 aa->ap.aph.ph.param_type = SCTP_ADD_IP_ADDRESS;
3379 aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_addrv4_param);
3380 aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS;
3381 aa->ap.addrp.ph.param_length = sizeof (struct sctp_ipv4addr_param);
3382 /* No need to add an address, we are using 0.0.0.0 */
3383 TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next);
3384 break;
3385 #endif
3386 #ifdef INET6
3387 case AF_INET6:
3388 aa->ap.aph.ph.param_type = SCTP_DEL_IP_ADDRESS;
3389 aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_addr_param);
3390 aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS;
3391 aa->ap.addrp.ph.param_length = sizeof (struct sctp_ipv6addr_param);
3392 /* No need to add an address, we are using 0.0.0.0 */
3393 TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next);
3394 break;
3395 #endif
3396 }
3397 /* Now we must hunt the addresses and add all global addresses */
3398 if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
3399 struct sctp_vrf *vrf = NULL;
3400 struct sctp_ifn *sctp_ifnp;
3401 uint32_t vrf_id;
3402
3403 vrf_id = stcb->sctp_ep->def_vrf_id;
3404 vrf = sctp_find_vrf(vrf_id);
3405 if (vrf == NULL) {
3406 goto skip_rest;
3407 }
3408
3409 SCTP_IPI_ADDR_RLOCK();
3410 LIST_FOREACH(sctp_ifnp, &vrf->ifnlist, next_ifn) {
3411 LIST_FOREACH(sctp_ifap, &sctp_ifnp->ifalist, next_ifa) {
3412 switch (sctp_ifap->address.sa.sa_family) {
3413 #ifdef INET
3414 case AF_INET:
3415 to = &sctp_ifap->address.sin;
3416 if (IN4_ISPRIVATE_ADDRESS(&to->sin_addr)) {
3417 continue;
3418 }
3419 if (IN4_ISLOOPBACK_ADDRESS(&to->sin_addr)) {
3420 continue;
3421 }
3422 break;
3423 #endif
3424 #ifdef INET6
3425 case AF_INET6:
3426 to6 = &sctp_ifap->address.sin6;
3427 if (IN6_IS_ADDR_LOOPBACK(&to6->sin6_addr)) {
3428 continue;
3429 }
3430 if (IN6_IS_ADDR_LINKLOCAL(&to6->sin6_addr)) {
3431 continue;
3432 }
3433 break;
3434 #endif
3435 default:
3436 continue;
3437 }
3438 sctp_asconf_queue_mgmt(stcb, sctp_ifap, SCTP_ADD_IP_ADDRESS);
3439 }
3440 }
3441 SCTP_IPI_ADDR_RUNLOCK();
3442 } else {
3443 struct sctp_laddr *laddr;
3444
3445 LIST_FOREACH(laddr, &stcb->sctp_ep->sctp_addr_list, sctp_nxt_addr) {
3446 if (laddr->ifa == NULL) {
3447 continue;
3448 }
3449 if (laddr->ifa->localifa_flags & SCTP_BEING_DELETED)
3450 /* Address being deleted by the system, dont
3451 * list.
3452 */
3453 continue;
3454 if (laddr->action == SCTP_DEL_IP_ADDRESS) {
3455 /* Address being deleted on this ep
3456 * don't list.
3457 */
3458 continue;
3459 }
3460 sctp_ifap = laddr->ifa;
3461 switch (sctp_ifap->address.sa.sa_family) {
3462 #ifdef INET
3463 case AF_INET:
3464 to = &sctp_ifap->address.sin;
3465 if (IN4_ISPRIVATE_ADDRESS(&to->sin_addr)) {
3466 continue;
3467 }
3468 if (IN4_ISLOOPBACK_ADDRESS(&to->sin_addr)) {
3469 continue;
3470 }
3471 break;
3472 #endif
3473 #ifdef INET6
3474 case AF_INET6:
3475 to6 = &sctp_ifap->address.sin6;
3476 if (IN6_IS_ADDR_LOOPBACK(&to6->sin6_addr)) {
3477 continue;
3478 }
3479 if (IN6_IS_ADDR_LINKLOCAL(&to6->sin6_addr)) {
3480 continue;
3481 }
3482 break;
3483 #endif
3484 default:
3485 continue;
3486 }
3487 sctp_asconf_queue_mgmt(stcb, sctp_ifap, SCTP_ADD_IP_ADDRESS);
3488 }
3489 }
3490 skip_rest:
3491 /* Now we must send the asconf into the queue */
3492 sctp_send_asconf(stcb, net, SCTP_ADDR_NOT_LOCKED);
3493 }
3494