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