]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/netinet/sctp_asconf.c
This commit was generated by cvs2svn to compensate for changes in r168433,
[FreeBSD/FreeBSD.git] / sys / netinet / sctp_asconf.c
1 /*-
2  * Copyright (c) 2001-2007, Cisco Systems, Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  * a) Redistributions of source code must retain the above copyright notice,
8  *   this list of conditions and the following disclaimer.
9  *
10  * b) Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in
12  *   the documentation and/or other materials provided with the distribution.
13  *
14  * c) Neither the name of Cisco Systems, Inc. nor the names of its
15  *    contributors may be used to endorse or promote products derived
16  *    from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
20  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
28  * THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 /* $KAME: sctp_asconf.c,v 1.24 2005/03/06 16:04:16 itojun Exp $  */
32
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
35 #include <netinet/sctp_os.h>
36 #include <netinet/sctp_var.h>
37 #include <netinet/sctp_sysctl.h>
38 #include <netinet/sctp_pcb.h>
39 #include <netinet/sctp_header.h>
40 #include <netinet/sctputil.h>
41 #include <netinet/sctp_output.h>
42 #include <netinet/sctp_asconf.h>
43
44 /*
45  * debug flags:
46  * SCTP_DEBUG_ASCONF1: protocol info, general info and errors
47  * SCTP_DEBUG_ASCONF2: detailed info
48  */
49 #ifdef SCTP_DEBUG
50 #endif                          /* SCTP_DEBUG */
51
52
53 static int
54 sctp_asconf_get_source_ip(struct mbuf *m, struct sockaddr *sa)
55 {
56         struct ip *iph;
57         struct sockaddr_in *sin;
58
59 #ifdef INET6
60         struct sockaddr_in6 *sin6;
61
62 #endif
63
64         iph = mtod(m, struct ip *);
65         if (iph->ip_v == IPVERSION) {
66                 /* IPv4 source */
67                 sin = (struct sockaddr_in *)sa;
68                 bzero(sin, sizeof(*sin));
69                 sin->sin_family = AF_INET;
70                 sin->sin_len = sizeof(struct sockaddr_in);
71                 sin->sin_port = 0;
72                 sin->sin_addr.s_addr = iph->ip_src.s_addr;
73                 return 0;
74         }
75 #ifdef INET6
76         else if (iph->ip_v == (IPV6_VERSION >> 4)) {
77                 /* IPv6 source */
78                 struct ip6_hdr *ip6;
79
80                 sin6 = (struct sockaddr_in6 *)sa;
81                 bzero(sin6, sizeof(*sin6));
82                 sin6->sin6_family = AF_INET6;
83                 sin6->sin6_len = sizeof(struct sockaddr_in6);
84                 sin6->sin6_port = 0;
85                 ip6 = mtod(m, struct ip6_hdr *);
86                 sin6->sin6_addr = ip6->ip6_src;
87                 return 0;
88         }
89 #endif                          /* INET6 */
90         else
91                 return -1;
92 }
93
94 /*
95  * draft-ietf-tsvwg-addip-sctp
96  *
97  * Address management only currently supported For the bound all case: the asoc
98  * local addr list is always a "DO NOT USE" list For the subset bound case:
99  * If ASCONFs are allowed: the endpoint local addr list is the usable address
100  * list the asoc local addr list is the "DO NOT USE" list If ASCONFs are not
101  * allowed: the endpoint local addr list is the default usable list the asoc
102  * local addr list is the usable address list
103  *
104  * An ASCONF parameter queue exists per asoc which holds the pending address
105  * operations.  Lists are updated upon receipt of ASCONF-ACK.
106  *
107  * Deleted addresses are always immediately removed from the lists as they will
108  * (shortly) no longer exist in the kernel.  We send ASCONFs as a courtesy,
109  * only if allowed.
110  */
111
112 /*
113  * ASCONF parameter processing response_required: set if a reply is required
114  * (eg. SUCCESS_REPORT) returns a mbuf to an "error" response parameter or
115  * NULL/"success" if ok FIX: allocating this many mbufs on the fly is pretty
116  * inefficient...
117  */
118 static struct mbuf *
119 sctp_asconf_success_response(uint32_t id)
120 {
121         struct mbuf *m_reply = NULL;
122         struct sctp_asconf_paramhdr *aph;
123
124         m_reply = sctp_get_mbuf_for_msg(sizeof(struct sctp_asconf_paramhdr),
125             0, M_DONTWAIT, 1, MT_DATA);
126         if (m_reply == NULL) {
127 #ifdef SCTP_DEBUG
128                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
129                         printf("asconf_success_response: couldn't get mbuf!\n");
130                 }
131 #endif                          /* SCTP_DEBUG */
132                 return NULL;
133         }
134         aph = mtod(m_reply, struct sctp_asconf_paramhdr *);
135         aph->correlation_id = id;
136         aph->ph.param_type = htons(SCTP_SUCCESS_REPORT);
137         aph->ph.param_length = sizeof(struct sctp_asconf_paramhdr);
138         SCTP_BUF_LEN(m_reply) = aph->ph.param_length;
139         aph->ph.param_length = htons(aph->ph.param_length);
140
141         return m_reply;
142 }
143
144 static struct mbuf *
145 sctp_asconf_error_response(uint32_t id, uint16_t cause, uint8_t * error_tlv,
146     uint16_t tlv_length)
147 {
148         struct mbuf *m_reply = NULL;
149         struct sctp_asconf_paramhdr *aph;
150         struct sctp_error_cause *error;
151         uint8_t *tlv;
152
153         m_reply = sctp_get_mbuf_for_msg((sizeof(struct sctp_asconf_paramhdr) +
154             tlv_length +
155             sizeof(struct sctp_error_cause)),
156             0, M_DONTWAIT, 1, MT_DATA);
157         if (m_reply == NULL) {
158 #ifdef SCTP_DEBUG
159                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
160                         printf("asconf_error_response: couldn't get mbuf!\n");
161                 }
162 #endif                          /* SCTP_DEBUG */
163                 return NULL;
164         }
165         aph = mtod(m_reply, struct sctp_asconf_paramhdr *);
166         error = (struct sctp_error_cause *)(aph + 1);
167
168         aph->correlation_id = id;
169         aph->ph.param_type = htons(SCTP_ERROR_CAUSE_IND);
170         error->code = htons(cause);
171         error->length = tlv_length + sizeof(struct sctp_error_cause);
172         aph->ph.param_length = error->length +
173             sizeof(struct sctp_asconf_paramhdr);
174
175         if (aph->ph.param_length > MLEN) {
176 #ifdef SCTP_DEBUG
177                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
178                         printf("asconf_error_response: tlv_length (%xh) too big\n",
179                             tlv_length);
180                 }
181 #endif                          /* SCTP_DEBUG */
182                 sctp_m_freem(m_reply);  /* discard */
183                 return NULL;
184         }
185         if (error_tlv != NULL) {
186                 tlv = (uint8_t *) (error + 1);
187                 memcpy(tlv, error_tlv, tlv_length);
188         }
189         SCTP_BUF_LEN(m_reply) = aph->ph.param_length;
190         error->length = htons(error->length);
191         aph->ph.param_length = htons(aph->ph.param_length);
192
193         return m_reply;
194 }
195
196 static struct mbuf *
197 sctp_process_asconf_add_ip(struct mbuf *m, struct sctp_asconf_paramhdr *aph,
198     struct sctp_tcb *stcb, int response_required)
199 {
200         struct mbuf *m_reply = NULL;
201         struct sockaddr_storage sa_source, sa_store;
202         struct sctp_ipv4addr_param *v4addr;
203         uint16_t param_type, param_length, aparam_length;
204         struct sockaddr *sa;
205         struct sockaddr_in *sin;
206         int zero_address = 0;
207
208 #ifdef INET6
209         struct sockaddr_in6 *sin6;
210         struct sctp_ipv6addr_param *v6addr;
211
212 #endif                          /* INET6 */
213
214         aparam_length = ntohs(aph->ph.param_length);
215         v4addr = (struct sctp_ipv4addr_param *)(aph + 1);
216 #ifdef INET6
217         v6addr = (struct sctp_ipv6addr_param *)(aph + 1);
218 #endif                          /* INET6 */
219         param_type = ntohs(v4addr->ph.param_type);
220         param_length = ntohs(v4addr->ph.param_length);
221
222         sa = (struct sockaddr *)&sa_store;
223         switch (param_type) {
224         case SCTP_IPV4_ADDRESS:
225                 if (param_length != sizeof(struct sctp_ipv4addr_param)) {
226                         /* invalid param size */
227                         return NULL;
228                 }
229                 sin = (struct sockaddr_in *)&sa_store;
230                 bzero(sin, sizeof(*sin));
231                 sin->sin_family = AF_INET;
232                 sin->sin_len = sizeof(struct sockaddr_in);
233                 sin->sin_port = stcb->rport;
234                 sin->sin_addr.s_addr = v4addr->addr;
235                 if (sin->sin_addr.s_addr == INADDR_ANY)
236                         zero_address = 1;
237 #ifdef SCTP_DEBUG
238                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
239                         printf("process_asconf_add_ip: adding ");
240                         sctp_print_address(sa);
241                 }
242 #endif                          /* SCTP_DEBUG */
243                 break;
244         case SCTP_IPV6_ADDRESS:
245 #ifdef INET6
246                 if (param_length != sizeof(struct sctp_ipv6addr_param)) {
247                         /* invalid param size */
248                         return NULL;
249                 }
250                 sin6 = (struct sockaddr_in6 *)&sa_store;
251                 bzero(sin6, sizeof(*sin6));
252                 sin6->sin6_family = AF_INET6;
253                 sin6->sin6_len = sizeof(struct sockaddr_in6);
254                 sin6->sin6_port = stcb->rport;
255                 memcpy((caddr_t)&sin6->sin6_addr, v6addr->addr,
256                     sizeof(struct in6_addr));
257                 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))
258                         zero_address = 1;
259 #ifdef SCTP_DEBUG
260                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
261                         printf("process_asconf_add_ip: adding ");
262                         sctp_print_address(sa);
263                 }
264 #endif                          /* SCTP_DEBUG */
265 #else
266                 /* IPv6 not enabled! */
267                 /* FIX ME: currently sends back an invalid param error */
268                 m_reply = sctp_asconf_error_response(aph->correlation_id,
269                     SCTP_CAUSE_INVALID_PARAM, (uint8_t *) aph, aparam_length);
270 #ifdef SCTP_DEBUG
271                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
272                         printf("process_asconf_add_ip: v6 disabled- skipping ");
273                         sctp_print_address(sa);
274                 }
275 #endif                          /* SCTP_DEBUG */
276                 return m_reply;
277 #endif                          /* INET6 */
278                 break;
279         default:
280                 m_reply = sctp_asconf_error_response(aph->correlation_id,
281                     SCTP_CAUSE_UNRESOLVABLE_ADDR, (uint8_t *) aph,
282                     aparam_length);
283                 return m_reply;
284         }                       /* end switch */
285
286         /* if 0.0.0.0/::0, add the source address instead */
287         if (zero_address && sctp_nat_friendly) {
288                 sa = (struct sockaddr *)&sa_source;
289                 sctp_asconf_get_source_ip(m, sa);
290 #ifdef SCTP_DEBUG
291                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
292                         printf("process_asconf_add_ip: using source addr ");
293                         sctp_print_address(sa);
294                 }
295 #endif                          /* SCTP_DEBUG */
296         }
297         /* add the address */
298         if (sctp_add_remote_addr(stcb, sa, SCTP_DONOT_SETSCOPE,
299             SCTP_ADDR_DYNAMIC_ADDED) != 0) {
300 #ifdef SCTP_DEBUG
301                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
302                         printf("process_asconf_add_ip: error adding address\n");
303                 }
304 #endif                          /* SCTP_DEBUG */
305                 m_reply = sctp_asconf_error_response(aph->correlation_id,
306                     SCTP_CAUSE_RESOURCE_SHORTAGE, (uint8_t *) aph,
307                     aparam_length);
308         } else {
309                 /* notify upper layer */
310                 sctp_ulp_notify(SCTP_NOTIFY_ASCONF_ADD_IP, stcb, 0, sa);
311                 if (response_required) {
312                         m_reply =
313                             sctp_asconf_success_response(aph->correlation_id);
314                 }
315                 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, NULL, SCTP_FROM_SCTP_ASCONF + SCTP_LOC_1);
316                 sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, NULL);
317         }
318
319         return m_reply;
320 }
321
322 static int
323 sctp_asconf_del_remote_addrs_except(struct sctp_tcb *stcb,
324     struct sockaddr *src)
325 {
326         struct sctp_nets *src_net, *net;
327
328         /* make sure the source address exists as a destination net */
329         src_net = sctp_findnet(stcb, src);
330         if (src_net == NULL) {
331                 /* not found */
332                 return -1;
333         }
334         /* delete all destination addresses except the source */
335         TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
336                 if (net != src_net) {
337                         /* delete this address */
338                         sctp_remove_net(stcb, net);
339 #ifdef SCTP_DEBUG
340                         if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
341                                 printf("asconf_del_remote_addrs_except: deleting ");
342                                 sctp_print_address((struct sockaddr *)&net->ro._l_addr);
343                         }
344 #endif
345                         /* notify upper layer */
346                         sctp_ulp_notify(SCTP_NOTIFY_ASCONF_DELETE_IP, stcb, 0,
347                             (struct sockaddr *)&net->ro._l_addr);
348                 }
349         }
350         return 0;
351 }
352
353 static struct mbuf *
354 sctp_process_asconf_delete_ip(struct mbuf *m, struct sctp_asconf_paramhdr *aph,
355     struct sctp_tcb *stcb, int response_required)
356 {
357         struct mbuf *m_reply = NULL;
358         struct sockaddr_storage sa_source, sa_store;
359         struct sctp_ipv4addr_param *v4addr;
360         uint16_t param_type, param_length, aparam_length;
361         struct sockaddr *sa;
362         struct sockaddr_in *sin;
363         int zero_address = 0;
364         int result;
365
366 #ifdef INET6
367         struct sockaddr_in6 *sin6;
368         struct sctp_ipv6addr_param *v6addr;
369
370 #endif                          /* INET6 */
371
372         /* get the source IP address for src and 0.0.0.0/::0 delete checks */
373         sctp_asconf_get_source_ip(m, (struct sockaddr *)&sa_source);
374
375         aparam_length = ntohs(aph->ph.param_length);
376         v4addr = (struct sctp_ipv4addr_param *)(aph + 1);
377 #ifdef INET6
378         v6addr = (struct sctp_ipv6addr_param *)(aph + 1);
379 #endif                          /* INET6 */
380         param_type = ntohs(v4addr->ph.param_type);
381         param_length = ntohs(v4addr->ph.param_length);
382
383         sa = (struct sockaddr *)&sa_store;
384         switch (param_type) {
385         case SCTP_IPV4_ADDRESS:
386                 if (param_length != sizeof(struct sctp_ipv4addr_param)) {
387                         /* invalid param size */
388                         return NULL;
389                 }
390                 sin = (struct sockaddr_in *)&sa_store;
391                 bzero(sin, sizeof(*sin));
392                 sin->sin_family = AF_INET;
393                 sin->sin_len = sizeof(struct sockaddr_in);
394                 sin->sin_port = stcb->rport;
395                 sin->sin_addr.s_addr = v4addr->addr;
396                 if (sin->sin_addr.s_addr == INADDR_ANY)
397                         zero_address = 1;
398 #ifdef SCTP_DEBUG
399                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
400                         printf("process_asconf_delete_ip: deleting ");
401                         sctp_print_address(sa);
402                 }
403 #endif                          /* SCTP_DEBUG */
404                 break;
405         case SCTP_IPV6_ADDRESS:
406                 if (param_length != sizeof(struct sctp_ipv6addr_param)) {
407                         /* invalid param size */
408                         return NULL;
409                 }
410 #ifdef INET6
411                 sin6 = (struct sockaddr_in6 *)&sa_store;
412                 bzero(sin6, sizeof(*sin6));
413                 sin6->sin6_family = AF_INET6;
414                 sin6->sin6_len = sizeof(struct sockaddr_in6);
415                 sin6->sin6_port = stcb->rport;
416                 memcpy(&sin6->sin6_addr, v6addr->addr,
417                     sizeof(struct in6_addr));
418                 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))
419                         zero_address = 1;
420 #ifdef SCTP_DEBUG
421                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
422                         printf("process_asconf_delete_ip: deleting ");
423                         sctp_print_address(sa);
424                 }
425 #endif                          /* SCTP_DEBUG */
426 #else
427                 /* IPv6 not enabled!  No "action" needed; just ack it */
428 #ifdef SCTP_DEBUG
429                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
430                         printf("process_asconf_delete_ip: v6 disabled- ignoring: ");
431                         sctp_print_address(sa);
432                 }
433 #endif                          /* SCTP_DEBUG */
434                 /* just respond with a "success" ASCONF-ACK */
435                 return NULL;
436 #endif                          /* INET6 */
437                 break;
438         default:
439                 m_reply = sctp_asconf_error_response(aph->correlation_id,
440                     SCTP_CAUSE_UNRESOLVABLE_ADDR, (uint8_t *) aph,
441                     aparam_length);
442                 return m_reply;
443         }
444
445         /* make sure the source address is not being deleted */
446         if (sctp_cmpaddr(sa, (struct sockaddr *)&sa_source)) {
447                 /* trying to delete the source address! */
448 #ifdef SCTP_DEBUG
449                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
450                         printf("process_asconf_delete_ip: tried to delete source addr\n");
451                 }
452 #endif                          /* SCTP_DEBUG */
453                 m_reply = sctp_asconf_error_response(aph->correlation_id,
454                     SCTP_CAUSE_DELETING_SRC_ADDR, (uint8_t *) aph,
455                     aparam_length);
456                 return m_reply;
457         }
458         /* if deleting 0.0.0.0/::0, delete all addresses except src addr */
459         if (zero_address && sctp_nat_friendly) {
460                 result = sctp_asconf_del_remote_addrs_except(stcb,
461                     (struct sockaddr *)&sa_source);
462
463                 if (result) {
464                         /* src address did not exist? */
465 #ifdef SCTP_DEBUG
466                         if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
467                                 printf("process_asconf_delete_ip: src addr does not exist?\n");
468                         }
469 #endif                          /* SCTP_DEBUG */
470                         /* what error to reply with?? */
471                         m_reply =
472                             sctp_asconf_error_response(aph->correlation_id,
473                             SCTP_CAUSE_REQUEST_REFUSED, (uint8_t *) aph,
474                             aparam_length);
475                 } else if (response_required) {
476                         m_reply =
477                             sctp_asconf_success_response(aph->correlation_id);
478                 }
479                 return m_reply;
480         }
481         /* delete the address */
482         result = sctp_del_remote_addr(stcb, sa);
483         /*
484          * note if result == -2, the address doesn't exist in the asoc but
485          * since it's being deleted anyways, we just ack the delete -- but
486          * this probably means something has already gone awry
487          */
488         if (result == -1) {
489                 /* only one address in the asoc */
490 #ifdef SCTP_DEBUG
491                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
492                         printf("process_asconf_delete_ip: tried to delete last IP addr!\n");
493                 }
494 #endif                          /* SCTP_DEBUG */
495                 m_reply = sctp_asconf_error_response(aph->correlation_id,
496                     SCTP_CAUSE_DELETING_LAST_ADDR, (uint8_t *) aph,
497                     aparam_length);
498         } else {
499                 if (response_required) {
500                         m_reply = sctp_asconf_success_response(aph->correlation_id);
501                 }
502                 /* notify upper layer */
503                 sctp_ulp_notify(SCTP_NOTIFY_ASCONF_DELETE_IP, stcb, 0, sa);
504         }
505         return m_reply;
506 }
507
508 static struct mbuf *
509 sctp_process_asconf_set_primary(struct mbuf *m,
510     struct sctp_asconf_paramhdr *aph, struct sctp_tcb *stcb,
511     int response_required)
512 {
513         struct mbuf *m_reply = NULL;
514         struct sockaddr_storage sa_source, sa_store;
515         struct sctp_ipv4addr_param *v4addr;
516         uint16_t param_type, param_length, aparam_length;
517         struct sockaddr *sa;
518         struct sockaddr_in *sin;
519         int zero_address = 0;
520
521 #ifdef INET6
522         struct sockaddr_in6 *sin6;
523         struct sctp_ipv6addr_param *v6addr;
524
525 #endif                          /* INET6 */
526
527         aparam_length = ntohs(aph->ph.param_length);
528         v4addr = (struct sctp_ipv4addr_param *)(aph + 1);
529 #ifdef INET6
530         v6addr = (struct sctp_ipv6addr_param *)(aph + 1);
531 #endif                          /* INET6 */
532         param_type = ntohs(v4addr->ph.param_type);
533         param_length = ntohs(v4addr->ph.param_length);
534
535         sa = (struct sockaddr *)&sa_store;
536         switch (param_type) {
537         case SCTP_IPV4_ADDRESS:
538                 if (param_length != sizeof(struct sctp_ipv4addr_param)) {
539                         /* invalid param size */
540                         return NULL;
541                 }
542                 sin = (struct sockaddr_in *)&sa_store;
543                 bzero(sin, sizeof(*sin));
544                 sin->sin_family = AF_INET;
545                 sin->sin_len = sizeof(struct sockaddr_in);
546                 sin->sin_addr.s_addr = v4addr->addr;
547                 if (sin->sin_addr.s_addr == INADDR_ANY)
548                         zero_address = 1;
549 #ifdef SCTP_DEBUG
550                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
551                         printf("process_asconf_set_primary: ");
552                         sctp_print_address(sa);
553                 }
554 #endif                          /* SCTP_DEBUG */
555                 break;
556         case SCTP_IPV6_ADDRESS:
557                 if (param_length != sizeof(struct sctp_ipv6addr_param)) {
558                         /* invalid param size */
559                         return NULL;
560                 }
561 #ifdef INET6
562                 sin6 = (struct sockaddr_in6 *)&sa_store;
563                 bzero(sin6, sizeof(*sin6));
564                 sin6->sin6_family = AF_INET6;
565                 sin6->sin6_len = sizeof(struct sockaddr_in6);
566                 memcpy((caddr_t)&sin6->sin6_addr, v6addr->addr,
567                     sizeof(struct in6_addr));
568                 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))
569                         zero_address = 1;
570 #ifdef SCTP_DEBUG
571                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
572                         printf("process_asconf_set_primary: ");
573                         sctp_print_address(sa);
574                 }
575 #endif                          /* SCTP_DEBUG */
576 #else
577                 /* IPv6 not enabled!  No "action" needed; just ack it */
578 #ifdef SCTP_DEBUG
579                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
580                         printf("process_asconf_set_primary: v6 disabled- ignoring: ");
581                         sctp_print_address(sa);
582                 }
583 #endif                          /* SCTP_DEBUG */
584                 /* just respond with a "success" ASCONF-ACK */
585                 return NULL;
586 #endif                          /* INET6 */
587                 break;
588         default:
589                 m_reply = sctp_asconf_error_response(aph->correlation_id,
590                     SCTP_CAUSE_UNRESOLVABLE_ADDR, (uint8_t *) aph,
591                     aparam_length);
592                 return m_reply;
593         }
594
595         /* if 0.0.0.0/::0, use the source address instead */
596         if (zero_address && sctp_nat_friendly) {
597                 sa = (struct sockaddr *)&sa_source;
598                 sctp_asconf_get_source_ip(m, sa);
599 #ifdef SCTP_DEBUG
600                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
601                         printf("process_asconf_set_primary: using source addr ");
602                         sctp_print_address(sa);
603                 }
604 #endif                          /* SCTP_DEBUG */
605         }
606         /* set the primary address */
607         if (sctp_set_primary_addr(stcb, sa, NULL) == 0) {
608 #ifdef SCTP_DEBUG
609                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
610                         printf("process_asconf_set_primary: primary address set\n");
611                 }
612 #endif                          /* SCTP_DEBUG */
613                 /* notify upper layer */
614                 sctp_ulp_notify(SCTP_NOTIFY_ASCONF_SET_PRIMARY, stcb, 0, sa);
615
616                 if (response_required) {
617                         m_reply = sctp_asconf_success_response(aph->correlation_id);
618                 }
619         } else {
620                 /* couldn't set the requested primary address! */
621 #ifdef SCTP_DEBUG
622                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
623                         printf("process_asconf_set_primary: set primary failed!\n");
624                 }
625 #endif                          /* SCTP_DEBUG */
626                 /* must have been an invalid address, so report */
627                 m_reply = sctp_asconf_error_response(aph->correlation_id,
628                     SCTP_CAUSE_UNRESOLVABLE_ADDR, (uint8_t *) aph,
629                     aparam_length);
630         }
631
632         return m_reply;
633 }
634
635 /*
636  * handles an ASCONF chunk.
637  * if all parameters are processed ok, send a plain (empty) ASCONF-ACK
638  */
639 void
640 sctp_handle_asconf(struct mbuf *m, unsigned int offset,
641     struct sctp_asconf_chunk *cp, struct sctp_tcb *stcb)
642 {
643         struct sctp_association *asoc;
644         uint32_t serial_num;
645         struct mbuf *m_ack, *m_result, *m_tail;
646         struct sctp_asconf_ack_chunk *ack_cp;
647         struct sctp_asconf_paramhdr *aph, *ack_aph;
648         struct sctp_ipv6addr_param *p_addr;
649         unsigned int asconf_limit;
650         int error = 0;          /* did an error occur? */
651
652         /* asconf param buffer */
653         uint8_t aparam_buf[SCTP_PARAM_BUFFER_SIZE];
654
655         /* verify minimum length */
656         if (ntohs(cp->ch.chunk_length) < sizeof(struct sctp_asconf_chunk)) {
657 #ifdef SCTP_DEBUG
658                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
659                         printf("handle_asconf: chunk too small = %xh\n",
660                             ntohs(cp->ch.chunk_length));
661                 }
662 #endif                          /* SCTP_DEBUG */
663                 return;
664         }
665         asoc = &stcb->asoc;
666         serial_num = ntohl(cp->serial_number);
667
668         if (serial_num == asoc->asconf_seq_in) {
669                 /* got a duplicate ASCONF */
670 #ifdef SCTP_DEBUG
671                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
672                         printf("handle_asconf: got duplicate serial number = %xh\n",
673                             serial_num);
674                 }
675 #endif                          /* SCTP_DEBUG */
676                 /* resend last ASCONF-ACK... */
677                 sctp_send_asconf_ack(stcb, 1);
678                 return;
679         } else if (serial_num != (asoc->asconf_seq_in + 1)) {
680 #ifdef SCTP_DEBUG
681                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
682                         printf("handle_asconf: incorrect serial number = %xh (expected next = %xh)\n",
683                             serial_num, asoc->asconf_seq_in + 1);
684                 }
685 #endif                          /* SCTP_DEBUG */
686                 return;
687         }
688         /* it's the expected "next" sequence number, so process it */
689         asoc->asconf_seq_in = serial_num;       /* update sequence */
690         /* get length of all the param's in the ASCONF */
691         asconf_limit = offset + ntohs(cp->ch.chunk_length);
692 #ifdef SCTP_DEBUG
693         if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
694                 printf("handle_asconf: asconf_limit=%u, sequence=%xh\n",
695                     asconf_limit, serial_num);
696         }
697 #endif                          /* SCTP_DEBUG */
698         if (asoc->last_asconf_ack_sent != NULL) {
699                 /* free last ASCONF-ACK message sent */
700                 sctp_m_freem(asoc->last_asconf_ack_sent);
701                 asoc->last_asconf_ack_sent = NULL;
702         }
703         m_ack = sctp_get_mbuf_for_msg(sizeof(struct sctp_asconf_ack_chunk), 0,
704             M_DONTWAIT, 1, MT_DATA);
705         if (m_ack == NULL) {
706 #ifdef SCTP_DEBUG
707                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
708                         printf("handle_asconf: couldn't get mbuf!\n");
709                 }
710 #endif                          /* SCTP_DEBUG */
711                 return;
712         }
713         m_tail = m_ack;         /* current reply chain's tail */
714
715         /* fill in ASCONF-ACK header */
716         ack_cp = mtod(m_ack, struct sctp_asconf_ack_chunk *);
717         ack_cp->ch.chunk_type = SCTP_ASCONF_ACK;
718         ack_cp->ch.chunk_flags = 0;
719         ack_cp->serial_number = htonl(serial_num);
720         /* set initial lengths (eg. just an ASCONF-ACK), ntohx at the end! */
721         SCTP_BUF_LEN(m_ack) = sizeof(struct sctp_asconf_ack_chunk);
722         ack_cp->ch.chunk_length = sizeof(struct sctp_asconf_ack_chunk);
723
724         /* skip the lookup address parameter */
725         offset += sizeof(struct sctp_asconf_chunk);
726         p_addr = (struct sctp_ipv6addr_param *)sctp_m_getptr(m, offset, sizeof(struct sctp_paramhdr), (uint8_t *) & aparam_buf);
727         if (p_addr == NULL) {
728 #ifdef SCTP_DEBUG
729                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
730                         printf("handle_asconf: couldn't get lookup addr!\n");
731                 }
732 #endif                          /* SCTP_DEBUG */
733
734                 /* respond with a missing/invalid mandatory parameter error */
735                 return;
736         }
737         /* param_length is already validated in process_control... */
738         offset += ntohs(p_addr->ph.param_length);       /* skip lookup addr */
739
740         /* get pointer to first asconf param in ASCONF-ACK */
741         ack_aph = (struct sctp_asconf_paramhdr *)(mtod(m_ack, caddr_t)+sizeof(struct sctp_asconf_ack_chunk));
742         if (ack_aph == NULL) {
743 #ifdef SCTP_DEBUG
744                 printf("Gak in asconf2\n");
745 #endif
746                 return;
747         }
748         /* get pointer to first asconf param in ASCONF */
749         aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(m, offset, sizeof(struct sctp_asconf_paramhdr), (uint8_t *) & aparam_buf);
750         if (aph == NULL) {
751 #ifdef SCTP_DEBUG
752                 printf("Empty ASCONF received?\n");
753 #endif
754                 goto send_reply;
755         }
756         /* process through all parameters */
757         while (aph != NULL) {
758                 unsigned int param_length, param_type;
759
760                 param_type = ntohs(aph->ph.param_type);
761                 param_length = ntohs(aph->ph.param_length);
762                 if (offset + param_length > asconf_limit) {
763                         /* parameter goes beyond end of chunk! */
764                         sctp_m_freem(m_ack);
765                         return;
766                 }
767                 m_result = NULL;
768
769                 if (param_length > sizeof(aparam_buf)) {
770 #ifdef SCTP_DEBUG
771                         if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
772                                 printf("handle_asconf: param length (%u) larger than buffer size!\n", param_length);
773                         }
774 #endif                          /* SCTP_DEBUG */
775                         sctp_m_freem(m_ack);
776                         return;
777                 }
778                 if (param_length <= sizeof(struct sctp_paramhdr)) {
779 #ifdef SCTP_DEBUG
780                         if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
781                                 printf("handle_asconf: param length (%u) too short\n", param_length);
782                         }
783 #endif                          /* SCTP_DEBUG */
784                         sctp_m_freem(m_ack);
785                 }
786                 /* get the entire parameter */
787                 aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(m, offset, param_length, aparam_buf);
788                 if (aph == NULL) {
789 #ifdef SCTP_DEBUG
790                         printf("Gag\n");
791 #endif
792                         sctp_m_freem(m_ack);
793                         return;
794                 }
795                 switch (param_type) {
796                 case SCTP_ADD_IP_ADDRESS:
797                         asoc->peer_supports_asconf = 1;
798                         m_result = sctp_process_asconf_add_ip(m, aph, stcb,
799                             error);
800                         break;
801                 case SCTP_DEL_IP_ADDRESS:
802                         asoc->peer_supports_asconf = 1;
803                         m_result = sctp_process_asconf_delete_ip(m, aph, stcb,
804                             error);
805                         break;
806                 case SCTP_ERROR_CAUSE_IND:
807                         /* not valid in an ASCONF chunk */
808                         break;
809                 case SCTP_SET_PRIM_ADDR:
810                         asoc->peer_supports_asconf = 1;
811                         m_result = sctp_process_asconf_set_primary(m, aph,
812                             stcb, error);
813                         break;
814                 case SCTP_SUCCESS_REPORT:
815                         /* not valid in an ASCONF chunk */
816                         break;
817                 case SCTP_ULP_ADAPTATION:
818                         /* FIX */
819                         break;
820                 default:
821                         if ((param_type & 0x8000) == 0) {
822                                 /* Been told to STOP at this param */
823                                 asconf_limit = offset;
824                                 /*
825                                  * FIX FIX - We need to call
826                                  * sctp_arethere_unrecognized_parameters()
827                                  * to get a operr and send it for any
828                                  * param's with the 0x4000 bit set OR do it
829                                  * here ourselves... note we still must STOP
830                                  * if the 0x8000 bit is clear.
831                                  */
832                         }
833                         /* unknown/invalid param type */
834                         break;
835                 }               /* switch */
836
837                 /* add any (error) result to the reply mbuf chain */
838                 if (m_result != NULL) {
839                         SCTP_BUF_NEXT(m_tail) = m_result;
840                         m_tail = m_result;
841                         /* update lengths, make sure it's aligned too */
842                         SCTP_BUF_LEN(m_result) = SCTP_SIZE32(SCTP_BUF_LEN(m_result));
843                         ack_cp->ch.chunk_length += SCTP_BUF_LEN(m_result);
844                         /* set flag to force success reports */
845                         error = 1;
846                 }
847                 offset += SCTP_SIZE32(param_length);
848                 /* update remaining ASCONF message length to process */
849                 if (offset >= asconf_limit) {
850                         /* no more data in the mbuf chain */
851                         break;
852                 }
853                 /* get pointer to next asconf param */
854                 aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(m, offset,
855                     sizeof(struct sctp_asconf_paramhdr),
856                     (uint8_t *) & aparam_buf);
857                 if (aph == NULL) {
858                         /* can't get an asconf paramhdr */
859 #ifdef SCTP_DEBUG
860                         if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
861                                 printf("handle_asconf: can't get asconf param hdr!\n");
862                         }
863 #endif                          /* SCTP_DEBUG */
864                         /* FIX ME - add error here... */
865                 }
866         }                       /* while */
867
868 send_reply:
869         ack_cp->ch.chunk_length = htons(ack_cp->ch.chunk_length);
870         /* save the ASCONF-ACK reply */
871         asoc->last_asconf_ack_sent = m_ack;
872
873         /* see if last_control_chunk_from is set properly (use IP src addr) */
874         if (stcb->asoc.last_control_chunk_from == NULL) {
875                 /*
876                  * this could happen if the source address was just newly
877                  * added
878                  */
879                 struct ip *iph;
880                 struct sctphdr *sh;
881                 struct sockaddr_storage from_store;
882                 struct sockaddr *from = (struct sockaddr *)&from_store;
883
884 #ifdef SCTP_DEBUG
885                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1)
886                         printf("handle_asconf: looking up net for IP source address\n");
887 #endif                          /* SCTP_DEBUG */
888                 /* pullup already done, IP options already stripped */
889                 iph = mtod(m, struct ip *);
890                 sh = (struct sctphdr *)((caddr_t)iph + sizeof(*iph));
891                 if (iph->ip_v == IPVERSION) {
892                         struct sockaddr_in *from4;
893
894                         from4 = (struct sockaddr_in *)&from_store;
895                         bzero(from4, sizeof(*from4));
896                         from4->sin_family = AF_INET;
897                         from4->sin_len = sizeof(struct sockaddr_in);
898                         from4->sin_addr.s_addr = iph->ip_src.s_addr;
899                         from4->sin_port = sh->src_port;
900                 } else if (iph->ip_v == (IPV6_VERSION >> 4)) {
901                         struct ip6_hdr *ip6;
902                         struct sockaddr_in6 *from6;
903
904                         ip6 = mtod(m, struct ip6_hdr *);
905                         from6 = (struct sockaddr_in6 *)&from_store;
906                         bzero(from6, sizeof(*from6));
907                         from6->sin6_family = AF_INET6;
908                         from6->sin6_len = sizeof(struct sockaddr_in6);
909                         from6->sin6_addr = ip6->ip6_src;
910                         from6->sin6_port = sh->src_port;
911                         /* Get the scopes in properly to the sin6 addr's */
912                         /* we probably don't need these operations */
913                         (void)sa6_recoverscope(from6);
914                         sa6_embedscope(from6, ip6_use_defzone);
915                 } else {
916                         /* unknown address type */
917                         from = NULL;
918                 }
919                 if (from != NULL) {
920 #ifdef SCTP_DEBUG
921                         if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
922                                 printf("Looking for IP source: ");
923                                 sctp_print_address(from);
924                         }
925 #endif                          /* SCTP_DEBUG */
926                         /* look up the from address */
927                         stcb->asoc.last_control_chunk_from = sctp_findnet(stcb, from);
928 #ifdef SCTP_DEBUG
929                         if ((stcb->asoc.last_control_chunk_from == NULL) &&
930                             (sctp_debug_on & SCTP_DEBUG_ASCONF1))
931                                 printf("handle_asconf: IP source address not found?!\n");
932 #endif                          /* SCTP_DEBUG */
933                 }
934         }
935         /* and send it (a new one) out... */
936         sctp_send_asconf_ack(stcb, 0);
937 }
938
939 /*
940  * does the address match? returns 0 if not, 1 if so
941  */
942 static uint32_t
943 sctp_asconf_addr_match(struct sctp_asconf_addr *aa, struct sockaddr *sa)
944 {
945 #ifdef INET6
946         if (sa->sa_family == AF_INET6) {
947                 /* IPv6 sa address */
948                 /* XXX scopeid */
949                 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
950
951                 if ((aa->ap.addrp.ph.param_type == SCTP_IPV6_ADDRESS) &&
952                     (memcmp(&aa->ap.addrp.addr, &sin6->sin6_addr,
953                     sizeof(struct in6_addr)) == 0)) {
954                         return (1);
955                 }
956         } else
957 #endif                          /* INET6 */
958         if (sa->sa_family == AF_INET) {
959                 /* IPv4 sa address */
960                 struct sockaddr_in *sin = (struct sockaddr_in *)sa;
961
962                 if ((aa->ap.addrp.ph.param_type == SCTP_IPV4_ADDRESS) &&
963                     (memcmp(&aa->ap.addrp.addr, &sin->sin_addr,
964                     sizeof(struct in_addr)) == 0)) {
965                         return (1);
966                 }
967         }
968         return (0);
969 }
970
971 /*
972  * Cleanup for non-responded/OP ERR'd ASCONF
973  */
974 void
975 sctp_asconf_cleanup(struct sctp_tcb *stcb, struct sctp_nets *net)
976 {
977         /* mark peer as ASCONF incapable */
978         stcb->asoc.peer_supports_asconf = 0;
979         /*
980          * clear out any existing asconfs going out
981          */
982         sctp_timer_stop(SCTP_TIMER_TYPE_ASCONF, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_ASCONF + SCTP_LOC_2);
983         stcb->asoc.asconf_seq_out++;
984         /* remove the old ASCONF on our outbound queue */
985         sctp_toss_old_asconf(stcb);
986 }
987
988 /*
989  * process an ADD/DELETE IP ack from peer.
990  * addr  corresponding sctp_ifa to the address being added/deleted.
991  * type: SCTP_ADD_IP_ADDRESS or SCTP_DEL_IP_ADDRESS.
992  * flag: 1=success, 0=failure.
993  */
994 static void
995 sctp_asconf_addr_mgmt_ack(struct sctp_tcb *stcb, struct sctp_ifa *addr,
996     uint16_t type, uint32_t flag)
997 {
998         /*
999          * do the necessary asoc list work- if we get a failure indication,
1000          * leave the address on the "do not use" asoc list if we get a
1001          * success indication, remove the address from the list
1002          */
1003         /*
1004          * Note: this will only occur for ADD_IP_ADDRESS, since
1005          * DEL_IP_ADDRESS is never actually added to the list...
1006          */
1007         if (flag) {
1008                 /* success case, so remove from the list */
1009                 sctp_del_local_addr_assoc(stcb, addr);
1010         }
1011         /* else, leave it on the list */
1012 }
1013
1014 /*
1015  * add an asconf add/delete IP address parameter to the queue.
1016  * type = SCTP_ADD_IP_ADDRESS, SCTP_DEL_IP_ADDRESS, SCTP_SET_PRIM_ADDR.
1017  * returns 0 if completed, non-zero if not completed.
1018  * NOTE: if adding, but delete already scheduled (and not yet sent out),
1019  * simply remove from queue.  Same for deleting an address already scheduled
1020  * for add.  If a duplicate operation is found, ignore the new one.
1021  */
1022 static uint32_t
1023 sctp_asconf_queue_add(struct sctp_tcb *stcb, struct sctp_ifa *ifa, uint16_t type)
1024 {
1025         struct sctp_asconf_addr *aa, *aa_next;
1026         struct sockaddr *sa;
1027
1028         /* see if peer supports ASCONF */
1029         if (stcb->asoc.peer_supports_asconf == 0) {
1030                 return (-1);
1031         }
1032         /* make sure the request isn't already in the queue */
1033         for (aa = TAILQ_FIRST(&stcb->asoc.asconf_queue); aa != NULL;
1034             aa = aa_next) {
1035                 aa_next = TAILQ_NEXT(aa, next);
1036                 /* address match? */
1037                 if (sctp_asconf_addr_match(aa, &ifa->address.sa) == 0)
1038                         continue;
1039                 /* is the request already in queue (sent or not) */
1040                 if (aa->ap.aph.ph.param_type == type) {
1041                         return (-1);
1042                 }
1043                 /* is the negative request already in queue, and not sent */
1044                 if (aa->sent == 0 &&
1045                 /* add requested, delete already queued */
1046                     ((type == SCTP_ADD_IP_ADDRESS &&
1047                     aa->ap.aph.ph.param_type == SCTP_DEL_IP_ADDRESS) ||
1048                 /* delete requested, add already queued */
1049                     (type == SCTP_DEL_IP_ADDRESS &&
1050                     aa->ap.aph.ph.param_type == SCTP_ADD_IP_ADDRESS))) {
1051                         /* delete the existing entry in the queue */
1052                         TAILQ_REMOVE(&stcb->asoc.asconf_queue, aa, next);
1053                         /* take the entry off the appropriate list */
1054                         sctp_asconf_addr_mgmt_ack(stcb, aa->ifa, type, 1);
1055                         /* free the entry */
1056                         sctp_free_ifa(aa->ifa);
1057                         SCTP_FREE(aa);
1058                         return (-1);
1059                 }
1060         }                       /* for each aa */
1061
1062         /* adding new request to the queue */
1063         SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa), "AsconfAddr");
1064         if (aa == NULL) {
1065                 /* didn't get memory */
1066 #ifdef SCTP_DEBUG
1067                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
1068                         printf("asconf_queue_add: failed to get memory!\n");
1069                 }
1070 #endif                          /* SCTP_DEBUG */
1071                 return (-1);
1072         }
1073         /* fill in asconf address parameter fields */
1074         /* top level elements are "networked" during send */
1075         aa->ap.aph.ph.param_type = type;
1076         aa->ifa = ifa;
1077         atomic_add_int(&ifa->refcount, 1);
1078         /* correlation_id filled in during send routine later... */
1079         if (ifa->address.sa.sa_family == AF_INET6) {
1080                 /* IPv6 address */
1081                 struct sockaddr_in6 *sin6;
1082
1083                 sin6 = (struct sockaddr_in6 *)&ifa->address.sa;
1084                 sa = (struct sockaddr *)sin6;
1085                 aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS;
1086                 aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv6addr_param));
1087                 aa->ap.aph.ph.param_length =
1088                     sizeof(struct sctp_asconf_paramhdr) +
1089                     sizeof(struct sctp_ipv6addr_param);
1090                 memcpy(&aa->ap.addrp.addr, &sin6->sin6_addr,
1091                     sizeof(struct in6_addr));
1092         } else if (ifa->address.sa.sa_family == AF_INET) {
1093                 /* IPv4 address */
1094                 struct sockaddr_in *sin = (struct sockaddr_in *)&ifa->address.sa;
1095
1096                 sa = (struct sockaddr *)sin;
1097                 aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS;
1098                 aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv4addr_param));
1099                 aa->ap.aph.ph.param_length =
1100                     sizeof(struct sctp_asconf_paramhdr) +
1101                     sizeof(struct sctp_ipv4addr_param);
1102                 memcpy(&aa->ap.addrp.addr, &sin->sin_addr,
1103                     sizeof(struct in_addr));
1104         } else {
1105                 /* invalid family! */
1106                 return (-1);
1107         }
1108         aa->sent = 0;           /* clear sent flag */
1109
1110         /*
1111          * if we are deleting an address it should go out last otherwise,
1112          * add it to front of the pending queue
1113          */
1114         if (type == SCTP_ADD_IP_ADDRESS) {
1115                 /* add goes to the front of the queue */
1116                 TAILQ_INSERT_HEAD(&stcb->asoc.asconf_queue, aa, next);
1117 #ifdef SCTP_DEBUG
1118                 if (sctp_debug_on & SCTP_DEBUG_ASCONF2) {
1119                         printf("asconf_queue_add: appended asconf ADD_IP_ADDRESS: ");
1120                         sctp_print_address(sa);
1121                 }
1122 #endif                          /* SCTP_DEBUG */
1123         } else {
1124                 /* delete and set primary goes to the back of the queue */
1125                 TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next);
1126 #ifdef SCTP_DEBUG
1127                 if (sctp_debug_on & SCTP_DEBUG_ASCONF2) {
1128                         if (type == SCTP_DEL_IP_ADDRESS) {
1129                                 printf("asconf_queue_add: inserted asconf DEL_IP_ADDRESS: ");
1130                                 sctp_print_address(sa);
1131                         } else {
1132                                 printf("asconf_queue_add: inserted asconf SET_PRIM_ADDR: ");
1133                                 sctp_print_address(sa);
1134                         }
1135                 }
1136 #endif                          /* SCTP_DEBUG */
1137         }
1138
1139         return (0);
1140 }
1141
1142 /*
1143  * add an asconf add/delete IP address parameter to the queue by addr.
1144  * type = SCTP_ADD_IP_ADDRESS, SCTP_DEL_IP_ADDRESS, SCTP_SET_PRIM_ADDR.
1145  * returns 0 if completed, non-zero if not completed.
1146  * NOTE: if adding, but delete already scheduled (and not yet sent out),
1147  * simply remove from queue.  Same for deleting an address already scheduled
1148  * for add.  If a duplicate operation is found, ignore the new one.
1149  */
1150 static uint32_t
1151 sctp_asconf_queue_add_sa(struct sctp_tcb *stcb, struct sockaddr *sa,
1152     uint16_t type)
1153 {
1154         struct sctp_ifa *ifa;
1155         struct sctp_asconf_addr *aa, *aa_next;
1156         uint32_t vrf_id;
1157
1158         /* see if peer supports ASCONF */
1159         if (stcb->asoc.peer_supports_asconf == 0) {
1160                 return (-1);
1161         }
1162         /* make sure the request isn't already in the queue */
1163         for (aa = TAILQ_FIRST(&stcb->asoc.asconf_queue); aa != NULL;
1164             aa = aa_next) {
1165                 aa_next = TAILQ_NEXT(aa, next);
1166                 /* address match? */
1167                 if (sctp_asconf_addr_match(aa, sa) == 0)
1168                         continue;
1169                 /* is the request already in queue (sent or not) */
1170                 if (aa->ap.aph.ph.param_type == type) {
1171                         return (-1);
1172                 }
1173                 /* is the negative request already in queue, and not sent */
1174                 if (aa->sent == 1)
1175                         continue;
1176                 if (type == SCTP_ADD_IP_ADDRESS &&
1177                     aa->ap.aph.ph.param_type == SCTP_DEL_IP_ADDRESS) {
1178                         /* add requested, delete already queued */
1179
1180                         /* delete the existing entry in the queue */
1181                         TAILQ_REMOVE(&stcb->asoc.asconf_queue, aa, next);
1182                         /* free the entry */
1183                         sctp_free_ifa(aa->ifa);
1184                         SCTP_FREE(aa);
1185                         return (-1);
1186                 } else if (type == SCTP_DEL_IP_ADDRESS &&
1187                     aa->ap.aph.ph.param_type == SCTP_ADD_IP_ADDRESS) {
1188                         /* delete requested, add already queued */
1189
1190                         /* delete the existing entry in the queue */
1191                         TAILQ_REMOVE(&stcb->asoc.asconf_queue, aa, next);
1192                         /* take the entry off the appropriate list */
1193                         sctp_asconf_addr_mgmt_ack(stcb, aa->ifa, type, 1);
1194                         /* free the entry */
1195                         sctp_free_ifa(aa->ifa);
1196                         SCTP_FREE(aa);
1197                         return (-1);
1198                 }
1199         }                       /* for each aa */
1200         if (stcb) {
1201                 vrf_id = stcb->asoc.vrf_id;
1202         } else {
1203                 vrf_id = SCTP_DEFAULT_VRFID;
1204         }
1205
1206         ifa = sctp_find_ifa_by_addr(sa, vrf_id, 0);
1207         if (ifa == NULL) {
1208                 /* Invalid address */
1209                 return (-1);
1210         }
1211         /* adding new request to the queue */
1212         SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa), "AsconfAddr");
1213         if (aa == NULL) {
1214                 /* didn't get memory */
1215 #ifdef SCTP_DEBUG
1216                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
1217                         printf("asconf_queue_add_sa: failed to get memory!\n");
1218                 }
1219 #endif                          /* SCTP_DEBUG */
1220                 return (-1);
1221         }
1222         /* fill in asconf address parameter fields */
1223         /* top level elements are "networked" during send */
1224         aa->ap.aph.ph.param_type = type;
1225         aa->ifa = ifa;
1226         atomic_add_int(&ifa->refcount, 1);
1227         /* correlation_id filled in during send routine later... */
1228         if (sa->sa_family == AF_INET6) {
1229                 /* IPv6 address */
1230                 struct sockaddr_in6 *sin6;
1231
1232                 sin6 = (struct sockaddr_in6 *)sa;
1233                 aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS;
1234                 aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv6addr_param));
1235                 aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) + sizeof(struct sctp_ipv6addr_param);
1236                 memcpy(&aa->ap.addrp.addr, &sin6->sin6_addr,
1237                     sizeof(struct in6_addr));
1238         } else if (sa->sa_family == AF_INET) {
1239                 /* IPv4 address */
1240                 struct sockaddr_in *sin = (struct sockaddr_in *)sa;
1241
1242                 aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS;
1243                 aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv4addr_param));
1244                 aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) + sizeof(struct sctp_ipv4addr_param);
1245                 memcpy(&aa->ap.addrp.addr, &sin->sin_addr,
1246                     sizeof(struct in_addr));
1247         } else {
1248                 /* invalid family! */
1249                 SCTP_FREE(aa);
1250                 return (-1);
1251         }
1252         aa->sent = 0;           /* clear sent flag */
1253
1254         /*
1255          * if we are deleting an address it should go out last otherwise,
1256          * add it to front of the pending queue
1257          */
1258         if (type == SCTP_ADD_IP_ADDRESS) {
1259                 /* add goes to the front of the queue */
1260                 TAILQ_INSERT_HEAD(&stcb->asoc.asconf_queue, aa, next);
1261         } else {
1262                 /* delete and set primary goes to the back of the queue */
1263                 TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next);
1264         }
1265
1266         return (0);
1267 }
1268
1269 /*
1270  * find a specific asconf param on our "sent" queue
1271  */
1272 static struct sctp_asconf_addr *
1273 sctp_asconf_find_param(struct sctp_tcb *stcb, uint32_t correlation_id)
1274 {
1275         struct sctp_asconf_addr *aa;
1276
1277         TAILQ_FOREACH(aa, &stcb->asoc.asconf_queue, next) {
1278                 if (aa->ap.aph.correlation_id == correlation_id &&
1279                     aa->sent == 1) {
1280                         /* found it */
1281                         return (aa);
1282                 }
1283         }
1284         /* didn't find it */
1285         return (NULL);
1286 }
1287
1288 /*
1289  * process an SCTP_ERROR_CAUSE_IND for a ASCONF-ACK parameter and do
1290  * notifications based on the error response
1291  */
1292 static void
1293 sctp_asconf_process_error(struct sctp_tcb *stcb,
1294     struct sctp_asconf_paramhdr *aph)
1295 {
1296         struct sctp_error_cause *eh;
1297         struct sctp_paramhdr *ph;
1298         uint16_t param_type;
1299         uint16_t error_code;
1300
1301         eh = (struct sctp_error_cause *)(aph + 1);
1302         ph = (struct sctp_paramhdr *)(eh + 1);
1303         /* validate lengths */
1304         if (htons(eh->length) + sizeof(struct sctp_error_cause) >
1305             htons(aph->ph.param_length)) {
1306                 /* invalid error cause length */
1307 #ifdef SCTP_DEBUG
1308                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
1309                         printf("asconf_process_error: cause element too long\n");
1310                 }
1311 #endif                          /* SCTP_DEBUG */
1312                 return;
1313         }
1314         if (htons(ph->param_length) + sizeof(struct sctp_paramhdr) >
1315             htons(eh->length)) {
1316                 /* invalid included TLV length */
1317 #ifdef SCTP_DEBUG
1318                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
1319                         printf("asconf_process_error: included TLV too long\n");
1320                 }
1321 #endif                          /* SCTP_DEBUG */
1322                 return;
1323         }
1324         /* which error code ? */
1325         error_code = ntohs(eh->code);
1326         param_type = ntohs(aph->ph.param_type);
1327         /* FIX: this should go back up the REMOTE_ERROR ULP notify */
1328         switch (error_code) {
1329         case SCTP_CAUSE_RESOURCE_SHORTAGE:
1330                 /* we allow ourselves to "try again" for this error */
1331                 break;
1332         default:
1333                 /* peer can't handle it... */
1334                 switch (param_type) {
1335                 case SCTP_ADD_IP_ADDRESS:
1336                 case SCTP_DEL_IP_ADDRESS:
1337                         stcb->asoc.peer_supports_asconf = 0;
1338                         break;
1339                 case SCTP_SET_PRIM_ADDR:
1340                         stcb->asoc.peer_supports_asconf = 0;
1341                         break;
1342                 default:
1343                         break;
1344                 }
1345         }
1346 }
1347
1348 /*
1349  * process an asconf queue param aparam: parameter to process, will be
1350  * removed from the queue flag: 1=success, 0=failure
1351  */
1352 static void
1353 sctp_asconf_process_param_ack(struct sctp_tcb *stcb,
1354     struct sctp_asconf_addr *aparam, uint32_t flag)
1355 {
1356         uint16_t param_type;
1357
1358         /* process this param */
1359         param_type = aparam->ap.aph.ph.param_type;
1360         switch (param_type) {
1361         case SCTP_ADD_IP_ADDRESS:
1362 #ifdef SCTP_DEBUG
1363                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
1364                         printf("process_param_ack: added IP address\n");
1365                 }
1366 #endif                          /* SCTP_DEBUG */
1367                 sctp_asconf_addr_mgmt_ack(stcb, aparam->ifa, param_type, flag);
1368                 break;
1369         case SCTP_DEL_IP_ADDRESS:
1370 #ifdef SCTP_DEBUG
1371                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
1372                         printf("process_param_ack: deleted IP address\n");
1373                 }
1374 #endif                          /* SCTP_DEBUG */
1375                 /* nothing really to do... lists already updated */
1376                 break;
1377         case SCTP_SET_PRIM_ADDR:
1378                 /* nothing to do... peer may start using this addr */
1379                 if (flag == 0)
1380                         stcb->asoc.peer_supports_asconf = 0;
1381                 break;
1382         default:
1383                 /* should NEVER happen */
1384                 break;
1385         }
1386
1387         /* remove the param and free it */
1388         TAILQ_REMOVE(&stcb->asoc.asconf_queue, aparam, next);
1389         sctp_free_ifa(aparam->ifa);
1390         SCTP_FREE(aparam);
1391 }
1392
1393 /*
1394  * cleanup from a bad asconf ack parameter
1395  */
1396 static void
1397 sctp_asconf_ack_clear(struct sctp_tcb *stcb)
1398 {
1399         /* assume peer doesn't really know how to do asconfs */
1400         stcb->asoc.peer_supports_asconf = 0;
1401         /* XXX we could free the pending queue here */
1402 }
1403
1404 void
1405 sctp_handle_asconf_ack(struct mbuf *m, int offset,
1406     struct sctp_asconf_ack_chunk *cp, struct sctp_tcb *stcb,
1407     struct sctp_nets *net)
1408 {
1409         struct sctp_association *asoc;
1410         uint32_t serial_num;
1411         uint16_t ack_length;
1412         struct sctp_asconf_paramhdr *aph;
1413         struct sctp_asconf_addr *aa, *aa_next;
1414         uint32_t last_error_id = 0;     /* last error correlation id */
1415         uint32_t id;
1416         struct sctp_asconf_addr *ap;
1417
1418         /* asconf param buffer */
1419         uint8_t aparam_buf[SCTP_PARAM_BUFFER_SIZE];
1420
1421         /* verify minimum length */
1422         if (ntohs(cp->ch.chunk_length) < sizeof(struct sctp_asconf_ack_chunk)) {
1423 #ifdef SCTP_DEBUG
1424                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
1425                         printf("handle_asconf_ack: chunk too small = %xh\n",
1426                             ntohs(cp->ch.chunk_length));
1427                 }
1428 #endif                          /* SCTP_DEBUG */
1429                 return;
1430         }
1431         asoc = &stcb->asoc;
1432         serial_num = ntohl(cp->serial_number);
1433
1434         /*
1435          * NOTE: we may want to handle this differently- currently, we will
1436          * abort when we get an ack for the expected serial number + 1 (eg.
1437          * we didn't send it), process an ack normally if it is the expected
1438          * serial number, and re-send the previous ack for *ALL* other
1439          * serial numbers
1440          */
1441
1442         /*
1443          * if the serial number is the next expected, but I didn't send it,
1444          * abort the asoc, since someone probably just hijacked us...
1445          */
1446         if (serial_num == (asoc->asconf_seq_out + 1)) {
1447 #ifdef SCTP_DEBUG
1448                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
1449                         printf("handle_asconf_ack: got unexpected next serial number! Aborting asoc!\n");
1450                 }
1451 #endif                          /* SCTP_DEBUG */
1452                 sctp_abort_an_association(stcb->sctp_ep, stcb,
1453                     SCTP_CAUSE_ILLEGAL_ASCONF_ACK, NULL);
1454                 return;
1455         }
1456         if (serial_num != asoc->asconf_seq_out) {
1457                 /* got a duplicate/unexpected ASCONF-ACK */
1458 #ifdef SCTP_DEBUG
1459                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
1460                         printf("handle_asconf_ack: got duplicate/unexpected serial number = %xh (expected = %xh)\n", serial_num, asoc->asconf_seq_out);
1461                 }
1462 #endif                          /* SCTP_DEBUG */
1463                 return;
1464         }
1465         if (stcb->asoc.asconf_sent == 0) {
1466                 /* got a unexpected ASCONF-ACK for serial not in flight */
1467 #ifdef SCTP_DEBUG
1468                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
1469                         printf("handle_asconf_ack: got serial number = %xh but not in flight\n", serial_num);
1470                 }
1471 #endif                          /* SCTP_DEBUG */
1472                 /* nothing to do... duplicate ACK received */
1473                 return;
1474         }
1475         /* stop our timer */
1476         sctp_timer_stop(SCTP_TIMER_TYPE_ASCONF, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_ASCONF + SCTP_LOC_3);
1477
1478         /* process the ASCONF-ACK contents */
1479         ack_length = ntohs(cp->ch.chunk_length) -
1480             sizeof(struct sctp_asconf_ack_chunk);
1481         offset += sizeof(struct sctp_asconf_ack_chunk);
1482         /* process through all parameters */
1483         while (ack_length >= sizeof(struct sctp_asconf_paramhdr)) {
1484                 unsigned int param_length, param_type;
1485
1486                 /* get pointer to next asconf parameter */
1487                 aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(m, offset,
1488                     sizeof(struct sctp_asconf_paramhdr), aparam_buf);
1489                 if (aph == NULL) {
1490                         /* can't get an asconf paramhdr */
1491                         sctp_asconf_ack_clear(stcb);
1492                         return;
1493                 }
1494                 param_type = ntohs(aph->ph.param_type);
1495                 param_length = ntohs(aph->ph.param_length);
1496                 if (param_length > ack_length) {
1497                         sctp_asconf_ack_clear(stcb);
1498                         return;
1499                 }
1500                 if (param_length < sizeof(struct sctp_paramhdr)) {
1501                         sctp_asconf_ack_clear(stcb);
1502                         return;
1503                 }
1504                 /* get the complete parameter... */
1505                 if (param_length > sizeof(aparam_buf)) {
1506 #ifdef SCTP_DEBUG
1507                         if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
1508                                 printf("param length (%u) larger than buffer size!\n", param_length);
1509                         }
1510 #endif                          /* SCTP_DEBUG */
1511                         sctp_asconf_ack_clear(stcb);
1512                         return;
1513                 }
1514                 aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(m, offset, param_length, aparam_buf);
1515                 if (aph == NULL) {
1516                         sctp_asconf_ack_clear(stcb);
1517                         return;
1518                 }
1519                 /* correlation_id is transparent to peer, no ntohl needed */
1520                 id = aph->correlation_id;
1521
1522                 switch (param_type) {
1523                 case SCTP_ERROR_CAUSE_IND:
1524                         last_error_id = id;
1525                         /* find the corresponding asconf param in our queue */
1526                         ap = sctp_asconf_find_param(stcb, id);
1527                         if (ap == NULL) {
1528                                 /* hmm... can't find this in our queue! */
1529                                 break;
1530                         }
1531                         /* process the parameter, failed flag */
1532                         sctp_asconf_process_param_ack(stcb, ap, 0);
1533                         /* process the error response */
1534                         sctp_asconf_process_error(stcb, aph);
1535                         break;
1536                 case SCTP_SUCCESS_REPORT:
1537                         /* find the corresponding asconf param in our queue */
1538                         ap = sctp_asconf_find_param(stcb, id);
1539                         if (ap == NULL) {
1540                                 /* hmm... can't find this in our queue! */
1541                                 break;
1542                         }
1543                         /* process the parameter, success flag */
1544                         sctp_asconf_process_param_ack(stcb, ap, 1);
1545                         break;
1546                 default:
1547                         break;
1548                 }               /* switch */
1549
1550                 /* update remaining ASCONF-ACK message length to process */
1551                 ack_length -= SCTP_SIZE32(param_length);
1552                 if (ack_length <= 0) {
1553                         /* no more data in the mbuf chain */
1554                         break;
1555                 }
1556                 offset += SCTP_SIZE32(param_length);
1557         }                       /* while */
1558
1559         /*
1560          * if there are any "sent" params still on the queue, these are
1561          * implicitly "success", or "failed" (if we got an error back) ...
1562          * so process these appropriately
1563          * 
1564          * we assume that the correlation_id's are monotonically increasing
1565          * beginning from 1 and that we don't have *that* many outstanding
1566          * at any given time
1567          */
1568         if (last_error_id == 0)
1569                 last_error_id--;/* set to "max" value */
1570         for (aa = TAILQ_FIRST(&stcb->asoc.asconf_queue); aa != NULL;
1571             aa = aa_next) {
1572                 aa_next = TAILQ_NEXT(aa, next);
1573                 if (aa->sent == 1) {
1574                         /*
1575                          * implicitly successful or failed if correlation_id
1576                          * < last_error_id, then success else, failure
1577                          */
1578                         if (aa->ap.aph.correlation_id < last_error_id)
1579                                 sctp_asconf_process_param_ack(stcb, aa,
1580                                     SCTP_SUCCESS_REPORT);
1581                         else
1582                                 sctp_asconf_process_param_ack(stcb, aa,
1583                                     SCTP_ERROR_CAUSE_IND);
1584                 } else {
1585                         /*
1586                          * since we always process in order (FIFO queue) if
1587                          * we reach one that hasn't been sent, the rest
1588                          * should not have been sent either. so, we're
1589                          * done...
1590                          */
1591                         break;
1592                 }
1593         }
1594
1595         /* update the next sequence number to use */
1596         asoc->asconf_seq_out++;
1597         /* remove the old ASCONF on our outbound queue */
1598         sctp_toss_old_asconf(stcb);
1599         /* clear the sent flag to allow new ASCONFs */
1600         asoc->asconf_sent = 0;
1601         if (!TAILQ_EMPTY(&stcb->asoc.asconf_queue)) {
1602                 /* we have more params, so restart our timer */
1603                 sctp_timer_start(SCTP_TIMER_TYPE_ASCONF, stcb->sctp_ep,
1604                     stcb, net);
1605         }
1606 }
1607
1608 static uint32_t
1609 sctp_is_scopeid_in_nets(struct sctp_tcb *stcb, struct sockaddr *sa)
1610 {
1611         struct sockaddr_in6 *sin6, *net6;
1612         struct sctp_nets *net;
1613
1614         if (sa->sa_family != AF_INET6) {
1615                 /* wrong family */
1616                 return (0);
1617         }
1618         sin6 = (struct sockaddr_in6 *)sa;
1619         if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) == 0) {
1620                 /* not link local address */
1621                 return (0);
1622         }
1623         /* hunt through our destination nets list for this scope_id */
1624         TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
1625                 if (((struct sockaddr *)(&net->ro._l_addr))->sa_family !=
1626                     AF_INET6)
1627                         continue;
1628                 net6 = (struct sockaddr_in6 *)&net->ro._l_addr;
1629                 if (IN6_IS_ADDR_LINKLOCAL(&net6->sin6_addr) == 0)
1630                         continue;
1631                 if (sctp_is_same_scope(sin6, net6)) {
1632                         /* found one */
1633                         return (1);
1634                 }
1635         }
1636         /* didn't find one */
1637         return (0);
1638 }
1639
1640 /*
1641  * address management functions
1642  */
1643 static void
1644 sctp_addr_mgmt_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
1645     struct sctp_ifa *ifa, uint16_t type)
1646 {
1647         int status;
1648
1649
1650         if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0 &&
1651             sctp_is_feature_off(inp, SCTP_PCB_FLAGS_DO_ASCONF)) {
1652                 /* subset bound, no ASCONF allowed case, so ignore */
1653                 return;
1654         }
1655         /*
1656          * note: we know this is not the subset bound, no ASCONF case eg.
1657          * this is boundall or subset bound w/ASCONF allowed
1658          */
1659
1660         /* first, make sure it's a good address family */
1661         if (ifa->address.sa.sa_family != AF_INET6 &&
1662             ifa->address.sa.sa_family != AF_INET) {
1663                 return;
1664         }
1665         /* make sure we're "allowed" to add this type of addr */
1666         if (ifa->address.sa.sa_family == AF_INET6) {
1667                 /* invalid if we're not a v6 endpoint */
1668                 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0)
1669                         return;
1670                 /* is the v6 addr really valid ? */
1671                 if (ifa->localifa_flags & SCTP_ADDR_IFA_UNUSEABLE) {
1672                         return;
1673                 }
1674         }
1675         /* put this address on the "pending/do not use yet" list */
1676         /*
1677          * Note: we do this primarily for the subset bind case We don't have
1678          * scoping flags at the EP level, so we must add link local/site
1679          * local addresses to the EP, then need to "negate" them here.
1680          * Recall that this routine is only called for the subset bound
1681          * w/ASCONF allowed case.
1682          */
1683         sctp_add_local_addr_assoc(stcb, ifa, 1);
1684         /*
1685          * check address scope if address is out of scope, don't queue
1686          * anything... note: this would leave the address on both inp and
1687          * asoc lists
1688          */
1689         if (ifa->address.sa.sa_family == AF_INET6) {
1690                 struct sockaddr_in6 *sin6;
1691
1692                 sin6 = (struct sockaddr_in6 *)&ifa->address.sin6;
1693                 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
1694                         /* we skip unspecifed addresses */
1695                         return;
1696                 }
1697                 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
1698                         if (stcb->asoc.local_scope == 0) {
1699                                 return;
1700                         }
1701                         /* is it the right link local scope? */
1702                         if (sctp_is_scopeid_in_nets(stcb, &ifa->address.sa) == 0) {
1703                                 return;
1704                         }
1705                 }
1706                 if (stcb->asoc.site_scope == 0 &&
1707                     IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr)) {
1708                         return;
1709                 }
1710         } else if (ifa->address.sa.sa_family == AF_INET) {
1711                 struct sockaddr_in *sin;
1712                 struct in6pcb *inp6;
1713
1714                 inp6 = (struct in6pcb *)&inp->ip_inp.inp;
1715                 /* invalid if we are a v6 only endpoint */
1716                 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
1717                     SCTP_IPV6_V6ONLY(inp6))
1718                         return;
1719
1720                 sin = (struct sockaddr_in *)&ifa->address.sa;
1721                 if (sin->sin_addr.s_addr == 0) {
1722                         /* we skip unspecifed addresses */
1723                         return;
1724                 }
1725                 if (stcb->asoc.ipv4_local_scope == 0 &&
1726                     IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) {
1727                         return;
1728                 }
1729         } else {
1730                 /* else, not AF_INET or AF_INET6, so skip */
1731                 return;
1732         }
1733
1734         /* queue an asconf for this address add/delete */
1735         if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_DO_ASCONF)) {
1736                 /* does the peer do asconf? */
1737                 if (stcb->asoc.peer_supports_asconf) {
1738                         /* queue an asconf for this addr */
1739                         status = sctp_asconf_queue_add(stcb, ifa, type);
1740                         /*
1741                          * if queued ok, and in correct state, set the
1742                          * ASCONF timer if in non-open state, we will set
1743                          * this timer when the state does go open and do all
1744                          * the asconf's
1745                          */
1746                         if (status == 0 &&
1747                             SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) {
1748                                 sctp_timer_start(SCTP_TIMER_TYPE_ASCONF, inp,
1749                                     stcb, stcb->asoc.primary_destination);
1750                         }
1751                 }
1752         }
1753 }
1754
1755
1756 int
1757 sctp_iterator_ep(struct sctp_inpcb *inp, void *ptr, uint32_t val)
1758 {
1759         struct sctp_asconf_iterator *asc;
1760         struct sctp_ifa *ifa;
1761         struct sctp_laddr *l;
1762         int type;
1763         int cnt_invalid = 0;
1764
1765         asc = (struct sctp_asconf_iterator *)ptr;
1766         LIST_FOREACH(l, &asc->list_of_work, sctp_nxt_addr) {
1767                 ifa = l->ifa;
1768                 type = l->action;
1769                 if (ifa->address.sa.sa_family == AF_INET6) {
1770                         /* invalid if we're not a v6 endpoint */
1771                         if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) {
1772                                 cnt_invalid++;
1773                                 if (asc->cnt == cnt_invalid)
1774                                         return (1);
1775                                 else
1776                                         continue;
1777                         }
1778                 } else if (ifa->address.sa.sa_family == AF_INET) {
1779                         /* invalid if we are a v6 only endpoint */
1780                         struct in6pcb *inp6;
1781
1782                         inp6 = (struct in6pcb *)&inp->ip_inp.inp;
1783                         if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
1784                             SCTP_IPV6_V6ONLY(inp6)) {
1785                                 cnt_invalid++;
1786                                 if (asc->cnt == cnt_invalid)
1787                                         return (1);
1788                                 else
1789                                         continue;
1790                         }
1791                 } else {
1792                         /* invalid address family */
1793                         cnt_invalid++;
1794                         if (asc->cnt == cnt_invalid)
1795                                 return (1);
1796                         else
1797                                 continue;
1798                 }
1799         }
1800         return (0);
1801 }
1802
1803 int
1804 sctp_iterator_ep_end(struct sctp_inpcb *inp, void *ptr, uint32_t val)
1805 {
1806         struct sctp_ifa *ifa;
1807         struct sctp_asconf_iterator *asc;
1808         struct sctp_laddr *laddr, *nladdr, *l;
1809
1810         /* Only for specific case not bound all */
1811         asc = (struct sctp_asconf_iterator *)ptr;
1812         LIST_FOREACH(l, &asc->list_of_work, sctp_nxt_addr) {
1813                 ifa = l->ifa;
1814                 if (l->action == SCTP_ADD_IP_ADDRESS) {
1815                         LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
1816                                 if (laddr->ifa == ifa) {
1817                                         laddr->action = 0;
1818                                         break;
1819                                 }
1820                         }
1821                 } else if (l->action == SCTP_DEL_IP_ADDRESS) {
1822                         laddr = LIST_FIRST(&inp->sctp_addr_list);
1823                         while (laddr) {
1824                                 nladdr = LIST_NEXT(laddr, sctp_nxt_addr);
1825                                 /* remove only after all guys are done */
1826                                 if (laddr->ifa == ifa) {
1827                                         sctp_del_local_addr_ep(inp, ifa);
1828                                 }
1829                                 laddr = nladdr;
1830                         }
1831                 }
1832         }
1833         return (0);
1834 }
1835
1836 void
1837 sctp_iterator_stcb(struct sctp_inpcb *inp, struct sctp_tcb *stcb, void *ptr,
1838     uint32_t val)
1839 {
1840         struct sctp_asconf_iterator *asc;
1841         struct sctp_ifa *ifa;
1842         struct sctp_laddr *l;
1843         int cnt_invalid = 0;
1844         int type, status;
1845
1846         asc = (struct sctp_asconf_iterator *)ptr;
1847         LIST_FOREACH(l, &asc->list_of_work, sctp_nxt_addr) {
1848                 ifa = l->ifa;
1849                 type = l->action;
1850                 /* Same checks again for assoc */
1851                 if (ifa->address.sa.sa_family == AF_INET6) {
1852                         /* invalid if we're not a v6 endpoint */
1853                         struct sockaddr_in6 *sin6;
1854
1855                         if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) {
1856                                 cnt_invalid++;
1857                                 if (asc->cnt == cnt_invalid)
1858                                         return;
1859                                 else
1860                                         continue;
1861                         }
1862                         sin6 = (struct sockaddr_in6 *)&ifa->address.sin6;
1863                         if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
1864                                 /* we skip unspecifed addresses */
1865                                 continue;
1866                         }
1867                         if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
1868                                 if (stcb->asoc.local_scope == 0) {
1869                                         continue;
1870                                 }
1871                                 /* is it the right link local scope? */
1872                                 if (sctp_is_scopeid_in_nets(stcb, &ifa->address.sa) == 0) {
1873                                         continue;
1874                                 }
1875                         }
1876                 } else if (ifa->address.sa.sa_family == AF_INET) {
1877                         /* invalid if we are a v6 only endpoint */
1878                         struct in6pcb *inp6;
1879                         struct sockaddr_in *sin;
1880
1881                         inp6 = (struct in6pcb *)&inp->ip_inp.inp;
1882                         /* invalid if we are a v6 only endpoint */
1883                         if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
1884                             SCTP_IPV6_V6ONLY(inp6))
1885                                 continue;
1886
1887                         sin = (struct sockaddr_in *)&ifa->address.sa;
1888                         if (sin->sin_addr.s_addr == 0) {
1889                                 /* we skip unspecifed addresses */
1890                                 continue;
1891                         }
1892                         if (stcb->asoc.ipv4_local_scope == 0 &&
1893                             IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) {
1894                                 continue;;
1895                         }
1896                         if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
1897                             SCTP_IPV6_V6ONLY(inp6)) {
1898                                 cnt_invalid++;
1899                                 if (asc->cnt == cnt_invalid)
1900                                         return;
1901                                 else
1902                                         continue;
1903                         }
1904                 } else {
1905                         /* invalid address family */
1906                         cnt_invalid++;
1907                         if (asc->cnt == cnt_invalid)
1908                                 return;
1909                         else
1910                                 continue;
1911                 }
1912
1913                 /* put this address on the "pending/do not use yet" list */
1914                 if (type == SCTP_ADD_IP_ADDRESS) {
1915                         sctp_add_local_addr_assoc(stcb, ifa, 1);
1916                 } else if (type == SCTP_DEL_IP_ADDRESS) {
1917                         struct sctp_nets *net;
1918
1919                         TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
1920                                 struct rtentry *rt;
1921
1922                                 /* delete this address if cached */
1923                                 if (net->ro._s_addr &&
1924                                     (net->ro._s_addr->ifa == ifa)) {
1925                                         sctp_free_ifa(net->ro._s_addr);
1926                                         net->ro._s_addr = NULL;
1927                                         net->src_addr_selected = 0;
1928                                         rt = net->ro.ro_rt;
1929                                         if (rt) {
1930                                                 RTFREE(rt);
1931                                                 net->ro.ro_rt = NULL;
1932                                         }
1933                                         /*
1934                                          * Now we deleted our src address,
1935                                          * should we not also now reset the
1936                                          * cwnd/rto to start as if its a new
1937                                          * address?
1938                                          */
1939                                         sctp_set_initial_cc_param(stcb, net);
1940                                         net->RTO = stcb->asoc.initial_rto;
1941
1942                                 }
1943                         }
1944                 } else if (type == SCTP_SET_PRIM_ADDR) {
1945                         if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) {
1946                                 /*
1947                                  * must validate the ifa in question is in
1948                                  * the ep
1949                                  */
1950                                 if (sctp_is_addr_in_ep(stcb->sctp_ep, ifa) == 0) {
1951                                         continue;
1952                                 }
1953                         } else {
1954                                 /* Need to check scopes for this guy */
1955                                 if (sctp_is_address_in_scope(ifa,
1956                                     stcb->asoc.ipv4_addr_legal,
1957                                     stcb->asoc.ipv6_addr_legal,
1958                                     stcb->asoc.loopback_scope,
1959                                     stcb->asoc.ipv4_local_scope,
1960                                     stcb->asoc.local_scope,
1961                                     stcb->asoc.site_scope, 0) == 0) {
1962                                         continue;
1963                                 }
1964                         }
1965
1966                 }
1967                 /* queue an asconf for this address add/delete */
1968                 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_DO_ASCONF)) {
1969                         /* does the peer do asconf? */
1970                         if (stcb->asoc.peer_supports_asconf) {
1971                                 /* queue an asconf for this addr */
1972
1973                                 status = sctp_asconf_queue_add(stcb, ifa, type);
1974                                 /*
1975                                  * if queued ok, and in correct state, set
1976                                  * the ASCONF timer if in non-open state, we
1977                                  * will set this timer when the state does
1978                                  * go open and do all the asconf's
1979                                  */
1980                                 if (status == 0 &&
1981                                     SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) {
1982                                         sctp_timer_start(SCTP_TIMER_TYPE_ASCONF, inp,
1983                                             stcb, stcb->asoc.primary_destination);
1984                                 }
1985                         }
1986                 }
1987         }
1988 }
1989
1990 void 
1991 sctp_iterator_end(void *ptr, uint32_t val)
1992 {
1993         struct sctp_asconf_iterator *asc;
1994         struct sctp_ifa *ifa;
1995         struct sctp_laddr *l, *l_next;
1996
1997         asc = (struct sctp_asconf_iterator *)ptr;
1998         l = LIST_FIRST(&asc->list_of_work);
1999         while (l != NULL) {
2000                 l_next = LIST_NEXT(l, sctp_nxt_addr);
2001                 ifa = l->ifa;
2002                 if (l->action == SCTP_ADD_IP_ADDRESS) {
2003                         /* Clear the defer use flag */
2004                         ifa->localifa_flags &= ~SCTP_ADDR_DEFER_USE;
2005                 }
2006                 sctp_free_ifa(ifa);
2007                 SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_laddr, l);
2008                 SCTP_DECR_LADDR_COUNT();
2009                 l = l_next;
2010         }
2011         SCTP_FREE(asc);
2012 }
2013
2014 /*
2015  * sa is the sockaddr to ask the peer to set primary to returns: 0 =
2016  * completed, -1 = error
2017  */
2018 int32_t
2019 sctp_set_primary_ip_address_sa(struct sctp_tcb *stcb, struct sockaddr *sa)
2020 {
2021         /* NOTE: we currently don't check the validity of the address! */
2022
2023         /* queue an ASCONF:SET_PRIM_ADDR to be sent */
2024         if (!sctp_asconf_queue_add_sa(stcb, sa, SCTP_SET_PRIM_ADDR)) {
2025                 /* set primary queuing succeeded */
2026                 if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) {
2027                         sctp_timer_start(SCTP_TIMER_TYPE_ASCONF,
2028                             stcb->sctp_ep, stcb,
2029                             stcb->asoc.primary_destination);
2030                 }
2031 #ifdef SCTP_DEBUG
2032                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
2033                         printf("set_primary_ip_address_sa: queued on tcb=%p, ",
2034                             stcb);
2035                         sctp_print_address(sa);
2036                 }
2037 #endif                          /* SCTP_DEBUG */
2038         } else {
2039 #ifdef SCTP_DEBUG
2040                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
2041                         printf("set_primary_ip_address_sa: failed to add to queue on tcb=%p, ",
2042                             stcb);
2043                         sctp_print_address(sa);
2044                 }
2045 #endif                          /* SCTP_DEBUG */
2046                 return (-1);
2047         }
2048         return (0);
2049 }
2050
2051 void
2052 sctp_set_primary_ip_address(struct sctp_ifa *ifa)
2053 {
2054         struct sctp_inpcb *inp;
2055
2056         /* go through all our PCB's */
2057         LIST_FOREACH(inp, &sctppcbinfo.listhead, sctp_list) {
2058                 struct sctp_tcb *stcb;
2059
2060                 /* process for all associations for this endpoint */
2061                 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
2062                         /* queue an ASCONF:SET_PRIM_ADDR to be sent */
2063                         if (!sctp_asconf_queue_add(stcb, ifa,
2064                             SCTP_SET_PRIM_ADDR)) {
2065                                 /* set primary queuing succeeded */
2066                                 if (SCTP_GET_STATE(&stcb->asoc) ==
2067                                     SCTP_STATE_OPEN) {
2068                                         sctp_timer_start(SCTP_TIMER_TYPE_ASCONF,
2069                                             stcb->sctp_ep, stcb,
2070                                             stcb->asoc.primary_destination);
2071                                 }
2072 #ifdef SCTP_DEBUG
2073                                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
2074                                         printf("set_primary_ip_address: queued on stcb=%p, ",
2075                                             stcb);
2076                                         sctp_print_address(&ifa->address.sa);
2077                                 }
2078 #endif                          /* SCTP_DEBUG */
2079                         }
2080                 }               /* for each stcb */
2081         }                       /* for each inp */
2082 }
2083
2084 static struct sockaddr *
2085 sctp_find_valid_localaddr(struct sctp_tcb *stcb)
2086 {
2087         struct sctp_vrf *vrf = NULL;
2088         struct sctp_ifn *sctp_ifn;
2089         struct sctp_ifa *sctp_ifa;
2090
2091         vrf = sctp_find_vrf(stcb->asoc.vrf_id);
2092         LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
2093                 if (stcb->asoc.loopback_scope == 0 &&
2094                     SCTP_IFN_IS_IFT_LOOP(sctp_ifn)) {
2095                         /* Skip if loopback_scope not set */
2096                         continue;
2097                 }
2098                 LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
2099                         if (sctp_ifa->address.sa.sa_family == AF_INET &&
2100                             stcb->asoc.ipv4_addr_legal) {
2101                                 struct sockaddr_in *sin;
2102
2103                                 sin = (struct sockaddr_in *)&sctp_ifa->address.sa;
2104                                 if (sin->sin_addr.s_addr == 0) {
2105                                         /* skip unspecifed addresses */
2106                                         continue;
2107                                 }
2108                                 if (stcb->asoc.ipv4_local_scope == 0 &&
2109                                     IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))
2110                                         continue;
2111
2112                                 if (sctp_is_addr_restricted(stcb, sctp_ifa))
2113                                         continue;
2114                                 /* found a valid local v4 address to use */
2115                                 return (&sctp_ifa->address.sa);
2116                         } else if (sctp_ifa->address.sa.sa_family == AF_INET6 &&
2117                             stcb->asoc.ipv6_addr_legal) {
2118                                 struct sockaddr_in6 *sin6;
2119
2120                                 if (sctp_ifa->localifa_flags & SCTP_ADDR_IFA_UNUSEABLE) {
2121                                         continue;
2122                                 }
2123                                 sin6 = (struct sockaddr_in6 *)&sctp_ifa->address.sa;
2124                                 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
2125                                         /* we skip unspecifed addresses */
2126                                         continue;
2127                                 }
2128                                 if (stcb->asoc.local_scope == 0 &&
2129                                     IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
2130                                         continue;
2131                                 if (stcb->asoc.site_scope == 0 &&
2132                                     IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))
2133                                         continue;
2134
2135                                 /* found a valid local v6 address to use */
2136                                 return (&sctp_ifa->address.sa);
2137                         }
2138                 }
2139         }
2140         /* no valid addresses found */
2141         return (NULL);
2142 }
2143
2144 static struct sockaddr *
2145 sctp_find_valid_localaddr_ep(struct sctp_tcb *stcb)
2146 {
2147         struct sctp_laddr *laddr;
2148
2149         LIST_FOREACH(laddr, &stcb->sctp_ep->sctp_addr_list, sctp_nxt_addr) {
2150                 if (laddr->ifa == NULL) {
2151                         continue;
2152                 }
2153                 if (laddr->ifa == NULL) {
2154                         continue;
2155                 }
2156                 /* is the address restricted ? */
2157                 if (sctp_is_addr_restricted(stcb, laddr->ifa))
2158                         continue;
2159
2160                 /* found a valid local address to use */
2161                 return (&laddr->ifa->address.sa);
2162         }
2163         /* no valid addresses found */
2164         return (NULL);
2165 }
2166
2167 /*
2168  * builds an ASCONF chunk from queued ASCONF params returns NULL on error (no
2169  * mbuf, no ASCONF params queued, etc)
2170  */
2171 struct mbuf *
2172 sctp_compose_asconf(struct sctp_tcb *stcb, int *retlen)
2173 {
2174         struct mbuf *m_asconf, *m_asconf_chk;
2175         struct sctp_asconf_addr *aa;
2176         struct sctp_asconf_chunk *acp;
2177         struct sctp_asconf_paramhdr *aph;
2178         struct sctp_asconf_addr_param *aap;
2179         uint32_t p_length;
2180         uint32_t correlation_id = 1;    /* 0 is reserved... */
2181         caddr_t ptr, lookup_ptr;
2182         uint8_t lookup_used = 0;
2183
2184         /* are there any asconf params to send? */
2185         if (TAILQ_EMPTY(&stcb->asoc.asconf_queue)) {
2186                 return (NULL);
2187         }
2188         /*
2189          * get a chunk header mbuf and a cluster for the asconf params since
2190          * it's simpler to fill in the asconf chunk header lookup address on
2191          * the fly
2192          */
2193         m_asconf_chk = sctp_get_mbuf_for_msg(sizeof(struct sctp_asconf_chunk), 0, M_DONTWAIT, 1, MT_DATA);
2194         if (m_asconf_chk == NULL) {
2195                 /* no mbuf's */
2196 #ifdef SCTP_DEBUG
2197                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1)
2198                         printf("compose_asconf: couldn't get chunk mbuf!\n");
2199 #endif                          /* SCTP_DEBUG */
2200                 return (NULL);
2201         }
2202         m_asconf = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_DONTWAIT, 1, MT_DATA);
2203         if (m_asconf == NULL) {
2204                 /* no mbuf's */
2205 #ifdef SCTP_DEBUG
2206                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1)
2207                         printf("compose_asconf: couldn't get mbuf!\n");
2208 #endif                          /* SCTP_DEBUG */
2209                 sctp_m_freem(m_asconf_chk);
2210                 return (NULL);
2211         }
2212         SCTP_BUF_LEN(m_asconf_chk) = sizeof(struct sctp_asconf_chunk);
2213         SCTP_BUF_LEN(m_asconf) = 0;
2214         acp = mtod(m_asconf_chk, struct sctp_asconf_chunk *);
2215         bzero(acp, sizeof(struct sctp_asconf_chunk));
2216         /* save pointers to lookup address and asconf params */
2217         lookup_ptr = (caddr_t)(acp + 1);        /* after the header */
2218         ptr = mtod(m_asconf, caddr_t);  /* beginning of cluster */
2219
2220         /* fill in chunk header info */
2221         acp->ch.chunk_type = SCTP_ASCONF;
2222         acp->ch.chunk_flags = 0;
2223         acp->serial_number = htonl(stcb->asoc.asconf_seq_out);
2224
2225         /* add parameters... up to smallest MTU allowed */
2226         TAILQ_FOREACH(aa, &stcb->asoc.asconf_queue, next) {
2227                 /* get the parameter length */
2228                 p_length = SCTP_SIZE32(aa->ap.aph.ph.param_length);
2229                 /* will it fit in current chunk? */
2230                 if (SCTP_BUF_LEN(m_asconf) + p_length > stcb->asoc.smallest_mtu) {
2231                         /* won't fit, so we're done with this chunk */
2232                         break;
2233                 }
2234                 /* assign (and store) a correlation id */
2235                 aa->ap.aph.correlation_id = correlation_id++;
2236
2237                 /*
2238                  * fill in address if we're doing a delete this is a simple
2239                  * way for us to fill in the correlation address, which
2240                  * should only be used by the peer if we're deleting our
2241                  * source address and adding a new address (e.g. renumbering
2242                  * case)
2243                  */
2244                 if (lookup_used == 0 &&
2245                     aa->ap.aph.ph.param_type == SCTP_DEL_IP_ADDRESS) {
2246                         struct sctp_ipv6addr_param *lookup;
2247                         uint16_t p_size, addr_size;
2248
2249                         lookup = (struct sctp_ipv6addr_param *)lookup_ptr;
2250                         lookup->ph.param_type =
2251                             htons(aa->ap.addrp.ph.param_type);
2252                         if (aa->ap.addrp.ph.param_type == SCTP_IPV6_ADDRESS) {
2253                                 /* copy IPv6 address */
2254                                 p_size = sizeof(struct sctp_ipv6addr_param);
2255                                 addr_size = sizeof(struct in6_addr);
2256                         } else {
2257                                 /* copy IPv4 address */
2258                                 p_size = sizeof(struct sctp_ipv4addr_param);
2259                                 addr_size = sizeof(struct in_addr);
2260                         }
2261                         lookup->ph.param_length = htons(SCTP_SIZE32(p_size));
2262                         memcpy(lookup->addr, &aa->ap.addrp.addr, addr_size);
2263                         SCTP_BUF_LEN(m_asconf_chk) += SCTP_SIZE32(p_size);
2264                         lookup_used = 1;
2265                 }
2266                 /* copy into current space */
2267                 memcpy(ptr, &aa->ap, p_length);
2268
2269                 /* network elements and update lengths */
2270                 aph = (struct sctp_asconf_paramhdr *)ptr;
2271                 aap = (struct sctp_asconf_addr_param *)ptr;
2272                 /* correlation_id is transparent to peer, no htonl needed */
2273                 aph->ph.param_type = htons(aph->ph.param_type);
2274                 aph->ph.param_length = htons(aph->ph.param_length);
2275                 aap->addrp.ph.param_type = htons(aap->addrp.ph.param_type);
2276                 aap->addrp.ph.param_length = htons(aap->addrp.ph.param_length);
2277
2278                 SCTP_BUF_LEN(m_asconf) += SCTP_SIZE32(p_length);
2279                 ptr += SCTP_SIZE32(p_length);
2280
2281                 /*
2282                  * these params are removed off the pending list upon
2283                  * getting an ASCONF-ACK back from the peer, just set flag
2284                  */
2285                 aa->sent = 1;
2286         }
2287         /* check to see if the lookup addr has been populated yet */
2288         if (lookup_used == 0) {
2289                 /* NOTE: if the address param is optional, can skip this... */
2290                 /* add any valid (existing) address... */
2291                 struct sctp_ipv6addr_param *lookup;
2292                 uint16_t p_size, addr_size;
2293                 struct sockaddr *found_addr;
2294                 caddr_t addr_ptr;
2295
2296                 if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL)
2297                         found_addr = sctp_find_valid_localaddr(stcb);
2298                 else
2299                         found_addr = sctp_find_valid_localaddr_ep(stcb);
2300
2301                 lookup = (struct sctp_ipv6addr_param *)lookup_ptr;
2302                 if (found_addr != NULL) {
2303                         if (found_addr->sa_family == AF_INET6) {
2304                                 /* copy IPv6 address */
2305                                 lookup->ph.param_type =
2306                                     htons(SCTP_IPV6_ADDRESS);
2307                                 p_size = sizeof(struct sctp_ipv6addr_param);
2308                                 addr_size = sizeof(struct in6_addr);
2309                                 addr_ptr = (caddr_t)&((struct sockaddr_in6 *)
2310                                     found_addr)->sin6_addr;
2311                         } else {
2312                                 /* copy IPv4 address */
2313                                 lookup->ph.param_type =
2314                                     htons(SCTP_IPV4_ADDRESS);
2315                                 p_size = sizeof(struct sctp_ipv4addr_param);
2316                                 addr_size = sizeof(struct in_addr);
2317                                 addr_ptr = (caddr_t)&((struct sockaddr_in *)
2318                                     found_addr)->sin_addr;
2319                         }
2320                         lookup->ph.param_length = htons(SCTP_SIZE32(p_size));
2321                         memcpy(lookup->addr, addr_ptr, addr_size);
2322                         SCTP_BUF_LEN(m_asconf_chk) += SCTP_SIZE32(p_size);
2323                         lookup_used = 1;
2324                 } else {
2325                         /* uh oh... don't have any address?? */
2326 #ifdef SCTP_DEBUG
2327                         if (sctp_debug_on & SCTP_DEBUG_ASCONF1)
2328                                 printf("compose_asconf: no lookup addr!\n");
2329 #endif                          /* SCTP_DEBUG */
2330                         /* for now, we send a IPv4 address of 0.0.0.0 */
2331                         lookup->ph.param_type = htons(SCTP_IPV4_ADDRESS);
2332                         lookup->ph.param_length = htons(SCTP_SIZE32(sizeof(struct sctp_ipv4addr_param)));
2333                         bzero(lookup->addr, sizeof(struct in_addr));
2334                         SCTP_BUF_LEN(m_asconf_chk) += SCTP_SIZE32(sizeof(struct sctp_ipv4addr_param));
2335                         lookup_used = 1;
2336                 }
2337         }
2338         /* chain it all together */
2339         SCTP_BUF_NEXT(m_asconf_chk) = m_asconf;
2340         *retlen = acp->ch.chunk_length = ntohs(SCTP_BUF_LEN(m_asconf_chk) + SCTP_BUF_LEN(m_asconf));
2341
2342         /* update "sent" flag */
2343         stcb->asoc.asconf_sent++;
2344
2345         return (m_asconf_chk);
2346 }
2347
2348 /*
2349  * section to handle address changes before an association is up eg. changes
2350  * during INIT/INIT-ACK/COOKIE-ECHO handshake
2351  */
2352
2353 /*
2354  * processes the (local) addresses in the INIT-ACK chunk
2355  */
2356 static void
2357 sctp_process_initack_addresses(struct sctp_tcb *stcb, struct mbuf *m,
2358     unsigned int offset, unsigned int length)
2359 {
2360         struct sctp_paramhdr tmp_param, *ph;
2361         uint16_t plen, ptype;
2362         struct sctp_ifa *sctp_ifa;
2363         struct sctp_ipv6addr_param addr_store;
2364         struct sockaddr_in6 sin6;
2365         struct sockaddr_in sin;
2366         struct sockaddr *sa;
2367         uint32_t vrf_id;
2368
2369 #ifdef SCTP_DEBUG
2370         if (sctp_debug_on & SCTP_DEBUG_ASCONF2) {
2371                 printf("processing init-ack addresses\n");
2372         }
2373 #endif                          /* SCTP_DEBUG */
2374
2375         /* convert to upper bound */
2376         length += offset;
2377
2378         if ((offset + sizeof(struct sctp_paramhdr)) > length) {
2379                 return;
2380         }
2381         /* init the addresses */
2382         bzero(&sin6, sizeof(sin6));
2383         sin6.sin6_family = AF_INET6;
2384         sin6.sin6_len = sizeof(sin6);
2385         sin6.sin6_port = stcb->rport;
2386
2387         bzero(&sin, sizeof(sin));
2388         sin.sin_len = sizeof(sin);
2389         sin.sin_family = AF_INET;
2390         sin.sin_port = stcb->rport;
2391
2392         /* go through the addresses in the init-ack */
2393         ph = (struct sctp_paramhdr *)sctp_m_getptr(m, offset,
2394             sizeof(struct sctp_paramhdr), (uint8_t *) & tmp_param);
2395         while (ph != NULL) {
2396                 ptype = ntohs(ph->param_type);
2397                 plen = ntohs(ph->param_length);
2398                 if (ptype == SCTP_IPV6_ADDRESS) {
2399                         struct sctp_ipv6addr_param *a6p;
2400
2401                         /* get the entire IPv6 address param */
2402                         a6p = (struct sctp_ipv6addr_param *)
2403                             sctp_m_getptr(m, offset,
2404                             sizeof(struct sctp_ipv6addr_param),
2405                             (uint8_t *) & addr_store);
2406                         if (plen != sizeof(struct sctp_ipv6addr_param) ||
2407                             a6p == NULL) {
2408                                 return;
2409                         }
2410                         memcpy(&sin6.sin6_addr, a6p->addr,
2411                             sizeof(struct in6_addr));
2412                         sa = (struct sockaddr *)&sin6;
2413                 } else if (ptype == SCTP_IPV4_ADDRESS) {
2414                         struct sctp_ipv4addr_param *a4p;
2415
2416                         /* get the entire IPv4 address param */
2417                         a4p = (struct sctp_ipv4addr_param *)sctp_m_getptr(m, offset,
2418                             sizeof(struct sctp_ipv4addr_param),
2419                             (uint8_t *) & addr_store);
2420                         if (plen != sizeof(struct sctp_ipv4addr_param) ||
2421                             a4p == NULL) {
2422                                 return;
2423                         }
2424                         sin.sin_addr.s_addr = a4p->addr;
2425                         sa = (struct sockaddr *)&sin;
2426                 } else {
2427                         goto next_addr;
2428                 }
2429
2430                 /* see if this address really (still) exists */
2431                 if (stcb) {
2432                         vrf_id = stcb->asoc.vrf_id;
2433                 } else {
2434                         vrf_id = SCTP_DEFAULT_VRFID;
2435                 }
2436
2437                 sctp_ifa = sctp_find_ifa_by_addr(sa, vrf_id, 0);
2438                 if (sctp_ifa == NULL) {
2439                         /* address doesn't exist anymore */
2440                         int status;
2441
2442                         /* are ASCONFs allowed ? */
2443                         if ((sctp_is_feature_on(stcb->sctp_ep,
2444                             SCTP_PCB_FLAGS_DO_ASCONF)) &&
2445                             stcb->asoc.peer_supports_asconf) {
2446                                 /* queue an ASCONF DEL_IP_ADDRESS */
2447                                 status = sctp_asconf_queue_add_sa(stcb, sa,
2448                                     SCTP_DEL_IP_ADDRESS);
2449                                 /*
2450                                  * if queued ok, and in correct state, set
2451                                  * the ASCONF timer
2452                                  */
2453                                 if (status == 0 &&
2454                                     SCTP_GET_STATE(&stcb->asoc) ==
2455                                     SCTP_STATE_OPEN) {
2456                                         sctp_timer_start(SCTP_TIMER_TYPE_ASCONF,
2457                                             stcb->sctp_ep, stcb,
2458                                             stcb->asoc.primary_destination);
2459                                 }
2460                         }
2461                 }
2462 next_addr:
2463                 /*
2464                  * Sanity check:  Make sure the length isn't 0, otherwise
2465                  * we'll be stuck in this loop for a long time...
2466                  */
2467                 if (SCTP_SIZE32(plen) == 0) {
2468 #ifdef SCTP_DEBUG
2469                         printf("process_initack_addrs: bad len (%d) type=%xh\n",
2470                             plen, ptype);
2471 #endif
2472                         return;
2473                 }
2474                 /* get next parameter */
2475                 offset += SCTP_SIZE32(plen);
2476                 if ((offset + sizeof(struct sctp_paramhdr)) > length)
2477                         return;
2478                 ph = (struct sctp_paramhdr *)sctp_m_getptr(m, offset,
2479                     sizeof(struct sctp_paramhdr), (uint8_t *) & tmp_param);
2480         }                       /* while */
2481 }
2482
2483 /* FIX ME: need to verify return result for v6 address type if v6 disabled */
2484 /*
2485  * checks to see if a specific address is in the initack address list returns
2486  * 1 if found, 0 if not
2487  */
2488 static uint32_t
2489 sctp_addr_in_initack(struct sctp_tcb *stcb, struct mbuf *m, uint32_t offset,
2490     uint32_t length, struct sockaddr *sa)
2491 {
2492         struct sctp_paramhdr tmp_param, *ph;
2493         uint16_t plen, ptype;
2494         struct sctp_ipv6addr_param addr_store;
2495         struct sockaddr_in *sin;
2496         struct sctp_ipv4addr_param *a4p;
2497
2498 #ifdef INET6
2499         struct sockaddr_in6 *sin6;
2500         struct sctp_ipv6addr_param *a6p;
2501         struct sockaddr_in6 sin6_tmp;
2502
2503 #endif                          /* INET6 */
2504
2505         if (
2506 #ifdef INET6
2507             (sa->sa_family != AF_INET6) &&
2508 #endif                          /* INET6 */
2509             (sa->sa_family != AF_INET))
2510                 return (0);
2511
2512 #ifdef SCTP_DEBUG
2513         if (sctp_debug_on & SCTP_DEBUG_ASCONF2) {
2514                 printf("find_initack_addr: starting search for ");
2515                 sctp_print_address(sa);
2516         }
2517 #endif                          /* SCTP_DEBUG */
2518         /* convert to upper bound */
2519         length += offset;
2520
2521         if ((offset + sizeof(struct sctp_paramhdr)) > length) {
2522 #ifdef SCTP_DEBUG
2523                 if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
2524                         printf("find_initack_addr: invalid offset?\n");
2525                 }
2526 #endif                          /* SCTP_DEBUG */
2527                 return (0);
2528         }
2529         /* go through the addresses in the init-ack */
2530         ph = (struct sctp_paramhdr *)sctp_m_getptr(m, offset,
2531             sizeof(struct sctp_paramhdr), (uint8_t *) & tmp_param);
2532         while (ph != NULL) {
2533                 ptype = ntohs(ph->param_type);
2534                 plen = ntohs(ph->param_length);
2535 #ifdef INET6
2536                 if (ptype == SCTP_IPV6_ADDRESS && sa->sa_family == AF_INET6) {
2537                         /* get the entire IPv6 address param */
2538                         a6p = (struct sctp_ipv6addr_param *)
2539                             sctp_m_getptr(m, offset,
2540                             sizeof(struct sctp_ipv6addr_param),
2541                             (uint8_t *) & addr_store);
2542                         if (plen != sizeof(struct sctp_ipv6addr_param) ||
2543                             ph == NULL) {
2544                                 return (0);
2545                         }
2546                         sin6 = (struct sockaddr_in6 *)sa;
2547                         if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr)) {
2548                                 /* create a copy and clear scope */
2549                                 memcpy(&sin6_tmp, sin6,
2550                                     sizeof(struct sockaddr_in6));
2551                                 sin6 = &sin6_tmp;
2552                                 in6_clearscope(&sin6->sin6_addr);
2553                         }
2554                         if (memcmp(&sin6->sin6_addr, a6p->addr,
2555                             sizeof(struct in6_addr)) == 0) {
2556                                 /* found it */
2557                                 return (1);
2558                         }
2559                 } else
2560 #endif                          /* INET6 */
2561
2562                         if (ptype == SCTP_IPV4_ADDRESS &&
2563                     sa->sa_family == AF_INET) {
2564                         /* get the entire IPv4 address param */
2565                         a4p = (struct sctp_ipv4addr_param *)sctp_m_getptr(m,
2566                             offset, sizeof(struct sctp_ipv4addr_param),
2567                             (uint8_t *) & addr_store);
2568                         if (plen != sizeof(struct sctp_ipv4addr_param) ||
2569                             ph == NULL) {
2570                                 return (0);
2571                         }
2572                         sin = (struct sockaddr_in *)sa;
2573                         if (sin->sin_addr.s_addr == a4p->addr) {
2574                                 /* found it */
2575                                 return (1);
2576                         }
2577                 }
2578                 /* get next parameter */
2579                 offset += SCTP_SIZE32(plen);
2580                 if (offset + sizeof(struct sctp_paramhdr) > length)
2581                         return (0);
2582                 ph = (struct sctp_paramhdr *)
2583                     sctp_m_getptr(m, offset, sizeof(struct sctp_paramhdr),
2584                     (uint8_t *) & tmp_param);
2585         }                       /* while */
2586         /* not found! */
2587         return (0);
2588 }
2589
2590 /*
2591  * makes sure that the current endpoint local addr list is consistent with
2592  * the new association (eg. subset bound, asconf allowed) adds addresses as
2593  * necessary
2594  */
2595 static void
2596 sctp_check_address_list_ep(struct sctp_tcb *stcb, struct mbuf *m, int offset,
2597     int length, struct sockaddr *init_addr)
2598 {
2599         struct sctp_laddr *laddr;
2600
2601         /* go through the endpoint list */
2602         LIST_FOREACH(laddr, &stcb->sctp_ep->sctp_addr_list, sctp_nxt_addr) {
2603                 /* be paranoid and validate the laddr */
2604                 if (laddr->ifa == NULL) {
2605 #ifdef SCTP_DEBUG
2606                         if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
2607                                 printf("check_addr_list_ep: laddr->ifa is NULL");
2608                         }
2609 #endif                          /* SCTP_DEBUG */
2610                         continue;
2611                 }
2612                 if (laddr->ifa == NULL) {
2613 #ifdef SCTP_DEBUG
2614                         if (sctp_debug_on & SCTP_DEBUG_ASCONF1) {
2615                                 printf("check_addr_list_ep: laddr->ifa->ifa_addr is NULL");
2616                         }
2617 #endif                          /* SCTP_DEBUG */
2618                         continue;
2619                 }
2620                 /* do i have it implicitly? */
2621                 if (sctp_cmpaddr(&laddr->ifa->address.sa, init_addr)) {
2622                         continue;
2623                 }
2624                 /* check to see if in the init-ack */
2625                 if (!sctp_addr_in_initack(stcb, m, offset, length,
2626                     &laddr->ifa->address.sa)) {
2627                         /* try to add it */
2628                         sctp_addr_mgmt_assoc(stcb->sctp_ep, stcb, laddr->ifa,
2629                             SCTP_ADD_IP_ADDRESS);
2630                 }
2631         }
2632 }
2633
2634 /*
2635  * makes sure that the current kernel address list is consistent with the new
2636  * association (with all addrs bound) adds addresses as necessary
2637  */
2638 static void
2639 sctp_check_address_list_all(struct sctp_tcb *stcb, struct mbuf *m, int offset,
2640     int length, struct sockaddr *init_addr,
2641     uint16_t local_scope, uint16_t site_scope,
2642     uint16_t ipv4_scope, uint16_t loopback_scope)
2643 {
2644         struct sctp_vrf *vrf = NULL;
2645         struct sctp_ifn *sctp_ifn;
2646         struct sctp_ifa *sctp_ifa;
2647         uint32_t vrf_id;
2648
2649         if (stcb) {
2650                 vrf_id = stcb->asoc.vrf_id;
2651         } else {
2652                 vrf_id = SCTP_DEFAULT_VRFID;
2653         }
2654         vrf = sctp_find_vrf(vrf_id);
2655         if (vrf == NULL) {
2656                 return;
2657         }
2658         /* go through all our known interfaces */
2659         LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
2660                 if (loopback_scope == 0 && SCTP_IFN_IS_IFT_LOOP(sctp_ifn)) {
2661                         /* skip loopback interface */
2662                         continue;
2663                 }
2664                 /* go through each interface address */
2665                 LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
2666                         /* do i have it implicitly? */
2667                         if (sctp_cmpaddr(&sctp_ifa->address.sa, init_addr)) {
2668                                 continue;
2669                         }
2670                         /* check to see if in the init-ack */
2671                         if (!sctp_addr_in_initack(stcb, m, offset, length,
2672                             &sctp_ifa->address.sa)) {
2673                                 /* try to add it */
2674                                 sctp_addr_mgmt_assoc(stcb->sctp_ep, stcb,
2675                                     sctp_ifa, SCTP_ADD_IP_ADDRESS);
2676                         }
2677                 }               /* end foreach ifa */
2678         }                       /* end foreach ifn */
2679 }
2680
2681 /*
2682  * validates an init-ack chunk (from a cookie-echo) with current addresses
2683  * adds addresses from the init-ack into our local address list, if needed
2684  * queues asconf adds/deletes addresses as needed and makes appropriate list
2685  * changes for source address selection m, offset: points to the start of the
2686  * address list in an init-ack chunk length: total length of the address
2687  * params only init_addr: address where my INIT-ACK was sent from
2688  */
2689 void
2690 sctp_check_address_list(struct sctp_tcb *stcb, struct mbuf *m, int offset,
2691     int length, struct sockaddr *init_addr,
2692     uint16_t local_scope, uint16_t site_scope,
2693     uint16_t ipv4_scope, uint16_t loopback_scope)
2694 {
2695         /* process the local addresses in the initack */
2696         sctp_process_initack_addresses(stcb, m, offset, length);
2697
2698         if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
2699                 /* bound all case */
2700                 sctp_check_address_list_all(stcb, m, offset, length, init_addr,
2701                     local_scope, site_scope, ipv4_scope, loopback_scope);
2702         } else {
2703                 /* subset bound case */
2704                 if (sctp_is_feature_on(stcb->sctp_ep,
2705                     SCTP_PCB_FLAGS_DO_ASCONF)) {
2706                         /* asconf's allowed */
2707                         sctp_check_address_list_ep(stcb, m, offset, length,
2708                             init_addr);
2709                 }
2710                 /* else, no asconfs allowed, so what we sent is what we get */
2711         }
2712 }
2713
2714 /*
2715  * sctp_bindx() support
2716  */
2717 uint32_t
2718 sctp_addr_mgmt_ep_sa(struct sctp_inpcb *inp, struct sockaddr *sa, uint32_t type, uint32_t vrf_id)
2719 {
2720         struct sctp_ifa *ifa;
2721
2722         if (sa->sa_len == 0) {
2723                 return (EINVAL);
2724         }
2725         if (type == SCTP_ADD_IP_ADDRESS) {
2726                 /* For an add the address MUST be on the system */
2727                 ifa = sctp_find_ifa_by_addr(sa, vrf_id, 0);
2728         } else if (type == SCTP_DEL_IP_ADDRESS) {
2729                 /* For a delete we need to find it in the inp */
2730                 ifa = sctp_find_ifa_in_ep(inp, sa, 0);
2731         } else {
2732                 ifa = NULL;
2733         }
2734         if (ifa != NULL) {
2735                 /* add this address */
2736                 struct sctp_asconf_iterator *asc;
2737                 struct sctp_laddr *wi;
2738
2739                 SCTP_MALLOC(asc, struct sctp_asconf_iterator *,
2740                     sizeof(struct sctp_asconf_iterator), "SCTP_ASCONF_ITERATOR");
2741                 if (asc == NULL) {
2742                         return (ENOMEM);
2743                 }
2744                 wi = SCTP_ZONE_GET(sctppcbinfo.ipi_zone_laddr, struct sctp_laddr);
2745                 if (wi == NULL) {
2746                         SCTP_FREE(asc);
2747                         return (ENOMEM);
2748                 }
2749                 if (type == SCTP_ADD_IP_ADDRESS) {
2750                         sctp_add_local_addr_ep(inp, ifa, type);
2751                 } else if (type == SCTP_DEL_IP_ADDRESS) {
2752                         struct sctp_laddr *laddr;
2753
2754                         LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
2755                                 if (ifa == laddr->ifa) {
2756                                         /* Mark in the delete */
2757                                         laddr->action = type;
2758                                 }
2759                         }
2760                 }
2761                 LIST_INIT(&asc->list_of_work);
2762                 asc->cnt = 1;
2763                 SCTP_INCR_LADDR_COUNT();
2764                 wi->ifa = ifa;
2765                 wi->action = type;
2766                 atomic_add_int(&ifa->refcount, 1);
2767                 LIST_INSERT_HEAD(&asc->list_of_work, wi, sctp_nxt_addr);
2768                 sctp_initiate_iterator(sctp_iterator_ep,
2769                     sctp_iterator_stcb,
2770                     sctp_iterator_ep_end,
2771                     SCTP_PCB_ANY_FLAGS,
2772                     SCTP_PCB_ANY_FEATURES, SCTP_ASOC_ANY_STATE, (void *)asc, 0,
2773                     sctp_iterator_end, inp, 0);
2774         } else {
2775                 /* invalid address! */
2776                 return (EADDRNOTAVAIL);
2777         }
2778         return (0);
2779 }