diff options
Diffstat (limited to 'sys/netinet/sctp_asconf.c')
-rw-r--r-- | sys/netinet/sctp_asconf.c | 302 |
1 files changed, 203 insertions, 99 deletions
diff --git a/sys/netinet/sctp_asconf.c b/sys/netinet/sctp_asconf.c index 461637c..a091011 100644 --- a/sys/netinet/sctp_asconf.c +++ b/sys/netinet/sctp_asconf.c @@ -295,8 +295,7 @@ sctp_process_asconf_add_ip(struct mbuf *m, struct sctp_asconf_paramhdr *aph, } static int -sctp_asconf_del_remote_addrs_except(struct sctp_tcb *stcb, - struct sockaddr *src) +sctp_asconf_del_remote_addrs_except(struct sctp_tcb *stcb, struct sockaddr *src) { struct sctp_nets *src_net, *net; @@ -459,8 +458,8 @@ sctp_process_asconf_delete_ip(struct mbuf *m, struct sctp_asconf_paramhdr *aph, static struct mbuf * sctp_process_asconf_set_primary(struct mbuf *m, - struct sctp_asconf_paramhdr *aph, struct sctp_tcb *stcb, - int response_required) + struct sctp_asconf_paramhdr *aph, + struct sctp_tcb *stcb, int response_required) { struct mbuf *m_reply = NULL; struct sockaddr_storage sa_source, sa_store; @@ -874,7 +873,7 @@ sctp_asconf_cleanup(struct sctp_tcb *stcb, struct sctp_nets *net) /* * process an ADD/DELETE IP ack from peer. - * addr corresponding sctp_ifa to the address being added/deleted. + * addr: corresponding sctp_ifa to the address being added/deleted. * type: SCTP_ADD_IP_ADDRESS or SCTP_DEL_IP_ADDRESS. * flag: 1=success, 0=failure. */ @@ -892,31 +891,28 @@ sctp_asconf_addr_mgmt_ack(struct sctp_tcb *stcb, struct sctp_ifa *addr, * DEL_IP_ADDRESS is never actually added to the list... */ if (flag) { - /* success case, so remove from the list */ - sctp_del_local_addr_assoc(stcb, addr); + /* success case, so remove from the restricted list */ + sctp_del_local_addr_restricted(stcb, addr); } /* else, leave it on the list */ } /* - * add an asconf add/delete IP address parameter to the queue. + * add an asconf add/delete/set primary IP address parameter to the queue. * type = SCTP_ADD_IP_ADDRESS, SCTP_DEL_IP_ADDRESS, SCTP_SET_PRIM_ADDR. - * returns 0 if completed, non-zero if not completed. - * NOTE: if adding, but delete already scheduled (and not yet sent out), - * simply remove from queue. Same for deleting an address already scheduled - * for add. If a duplicate operation is found, ignore the new one. + * returns 0 if queued, -1 if not queued/removed. + * NOTE: if adding, but a delete for the same address is already scheduled + * (and not yet sent out), simply remove it from queue. Same for deleting + * an address already scheduled for add. If a duplicate operation is found, + * ignore the new one. */ -static uint32_t -sctp_asconf_queue_add(struct sctp_tcb *stcb, struct sctp_ifa *ifa, +static int +sctp_asconf_queue_mgmt(struct sctp_tcb *stcb, struct sctp_ifa *ifa, uint16_t type) { struct sctp_asconf_addr *aa, *aa_next; struct sockaddr *sa; - /* see if peer supports ASCONF */ - if (stcb->asoc.peer_supports_asconf == 0) { - return (-1); - } /* make sure the request isn't already in the queue */ for (aa = TAILQ_FIRST(&stcb->asoc.asconf_queue); aa != NULL; aa = aa_next) { @@ -929,30 +925,36 @@ sctp_asconf_queue_add(struct sctp_tcb *stcb, struct sctp_ifa *ifa, return (-1); } /* is the negative request already in queue, and not sent */ - if (aa->sent == 0 && - /* add requested, delete already queued */ - ((type == SCTP_ADD_IP_ADDRESS && - aa->ap.aph.ph.param_type == SCTP_DEL_IP_ADDRESS) || - /* delete requested, add already queued */ - (type == SCTP_DEL_IP_ADDRESS && - aa->ap.aph.ph.param_type == SCTP_ADD_IP_ADDRESS))) { - /* delete the existing entry in the queue */ + if ((aa->sent == 0) && (type == SCTP_ADD_IP_ADDRESS) && + (aa->ap.aph.ph.param_type == SCTP_DEL_IP_ADDRESS)) { + /* add requested, delete already queued */ TAILQ_REMOVE(&stcb->asoc.asconf_queue, aa, next); - /* take the entry off the appropriate list */ - sctp_asconf_addr_mgmt_ack(stcb, aa->ifa, type, 1); - /* free the entry */ - sctp_free_ifa(aa->ifa); + /* remove the ifa from the restricted list */ + sctp_del_local_addr_restricted(stcb, ifa); + /* free the asconf param */ SCTP_FREE(aa, SCTP_M_ASC_ADDR); + SCTPDBG(SCTP_DEBUG_ASCONF2, "asconf_queue_mgmt: add removes queued entry\n"); + return (-1); + } + if ((aa->sent == 0) && (type == SCTP_DEL_IP_ADDRESS) && + (aa->ap.aph.ph.param_type == SCTP_ADD_IP_ADDRESS)) { + /* delete requested, add already queued */ + TAILQ_REMOVE(&stcb->asoc.asconf_queue, aa, next); + /* remove the aa->ifa from the restricted list */ + sctp_del_local_addr_restricted(stcb, aa->ifa); + /* free the asconf param */ + SCTP_FREE(aa, SCTP_M_ASC_ADDR); + SCTPDBG(SCTP_DEBUG_ASCONF2, "asconf_queue_mgmt: delete removes queued entry\n"); return (-1); } } /* for each aa */ /* adding new request to the queue */ - SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa), SCTP_M_ASC_ADDR); + SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa), + SCTP_M_ASC_ADDR); if (aa == NULL) { /* didn't get memory */ - SCTPDBG(SCTP_DEBUG_ASCONF1, - "asconf_queue_add: failed to get memory!\n"); + SCTPDBG(SCTP_DEBUG_ASCONF1, "asconf_queue_mgmt: failed to get memory!\n"); return (-1); } /* fill in asconf address parameter fields */ @@ -969,20 +971,19 @@ sctp_asconf_queue_add(struct sctp_tcb *stcb, struct sctp_ifa *ifa, sa = (struct sockaddr *)sin6; aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS; aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv6addr_param)); - aa->ap.aph.ph.param_length = - sizeof(struct sctp_asconf_paramhdr) + + aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) + sizeof(struct sctp_ipv6addr_param); memcpy(&aa->ap.addrp.addr, &sin6->sin6_addr, sizeof(struct in6_addr)); } else if (ifa->address.sa.sa_family == AF_INET) { /* IPv4 address */ - struct sockaddr_in *sin = (struct sockaddr_in *)&ifa->address.sa; + struct sockaddr_in *sin; + sin = (struct sockaddr_in *)&ifa->address.sa; sa = (struct sockaddr *)sin; aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS; aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv4addr_param)); - aa->ap.aph.ph.param_length = - sizeof(struct sctp_asconf_paramhdr) + + aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) + sizeof(struct sctp_ipv4addr_param); memcpy(&aa->ap.addrp.addr, &sin->sin_addr, sizeof(struct in_addr)); @@ -1001,7 +1002,7 @@ sctp_asconf_queue_add(struct sctp_tcb *stcb, struct sctp_ifa *ifa, /* add goes to the front of the queue */ TAILQ_INSERT_HEAD(&stcb->asoc.asconf_queue, aa, next); SCTPDBG(SCTP_DEBUG_ASCONF2, - "asconf_queue_add: appended asconf ADD_IP_ADDRESS: "); + "asconf_queue_mgmt: inserted asconf ADD_IP_ADDRESS: "); SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, sa); } else { /* delete and set primary goes to the back of the queue */ @@ -1009,10 +1010,10 @@ sctp_asconf_queue_add(struct sctp_tcb *stcb, struct sctp_ifa *ifa, #ifdef SCTP_DEBUG if (sctp_debug_on && SCTP_DEBUG_ASCONF2) { if (type == SCTP_DEL_IP_ADDRESS) { - SCTP_PRINTF("asconf_queue_add: inserted asconf DEL_IP_ADDRESS: "); + SCTP_PRINTF("asconf_queue_mgmt: appended asconf DEL_IP_ADDRESS: "); SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, sa); } else { - SCTP_PRINTF("asconf_queue_add: inserted asconf SET_PRIM_ADDR: "); + SCTP_PRINTF("asconf_queue_mgmt: appended asconf SET_PRIM_ADDR: "); SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, sa); } } @@ -1022,6 +1023,84 @@ sctp_asconf_queue_add(struct sctp_tcb *stcb, struct sctp_ifa *ifa, return (0); } + +/* + * add an asconf operation for the given ifa and type. + * type = SCTP_ADD_IP_ADDRESS, SCTP_DEL_IP_ADDRESS, SCTP_SET_PRIM_ADDR. + * returns 0 if completed, -1 if not completed, 1 if immediate send is + * advisable. + */ +static int +sctp_asconf_queue_add(struct sctp_tcb *stcb, struct sctp_ifa *ifa, + uint16_t type) +{ + uint32_t status; + int pending_delete_queued = 0; + + /* see if peer supports ASCONF */ + if (stcb->asoc.peer_supports_asconf == 0) { + return (-1); + } + /* + * if this is deleting the last address from the assoc, mark it as + * pending. + */ + if ((type == SCTP_DEL_IP_ADDRESS) && !stcb->asoc.asconf_del_pending && + (sctp_local_addr_count(stcb) < 2)) { + /* set the pending delete info only */ + stcb->asoc.asconf_del_pending = 1; + stcb->asoc.asconf_addr_del_pending = ifa; + atomic_add_int(&ifa->refcount, 1); + SCTPDBG(SCTP_DEBUG_ASCONF2, + "asconf_queue_add: mark delete last address pending\n"); + return (-1); + } + /* + * if this is an add, and there is a delete also pending (i.e. the + * last local address is being changed), queue the pending delete + * too. + */ + if ((type == SCTP_ADD_IP_ADDRESS) && stcb->asoc.asconf_del_pending) { + /* queue in the pending delete */ + if (sctp_asconf_queue_mgmt(stcb, + stcb->asoc.asconf_addr_del_pending, + SCTP_DEL_IP_ADDRESS) == 0) { + SCTPDBG(SCTP_DEBUG_ASCONF2, "asconf_queue_add: queing pending delete\n"); + pending_delete_queued = 1; + /* clear out the pending delete info */ + stcb->asoc.asconf_del_pending = 0; + sctp_free_ifa(stcb->asoc.asconf_addr_del_pending); + stcb->asoc.asconf_addr_del_pending = NULL; + } + } + /* queue an asconf parameter */ + status = sctp_asconf_queue_mgmt(stcb, ifa, type); + + if (pending_delete_queued && (status == 0)) { + struct sctp_nets *net; + + /* + * since we know that the only/last address is now being + * changed in this case, reset the cwnd/rto on all nets to + * start as a new address and path. Also clear the error + * counts to give the assoc the best chance to complete the + * address change. + */ + TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { + stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb, + net); + net->RTO = 0; + net->error_count = 0; + } + stcb->asoc.overall_error_count = 0; + /* queue in an advisory set primary too */ + (void)sctp_asconf_queue_mgmt(stcb, ifa, SCTP_SET_PRIM_ADDR); + /* let caller know we should send this out immediately */ + status = 1; + } + return (status); +} + /* * add an asconf add/delete IP address parameter to the queue by addr. * type = SCTP_ADD_IP_ADDRESS, SCTP_DEL_IP_ADDRESS, SCTP_SET_PRIM_ADDR. @@ -1030,7 +1109,7 @@ sctp_asconf_queue_add(struct sctp_tcb *stcb, struct sctp_ifa *ifa, * simply remove from queue. Same for deleting an address already scheduled * for add. If a duplicate operation is found, ignore the new one. */ -static uint32_t +static int sctp_asconf_queue_add_sa(struct sctp_tcb *stcb, struct sockaddr *sa, uint16_t type) { @@ -1065,8 +1144,8 @@ sctp_asconf_queue_add_sa(struct sctp_tcb *stcb, struct sockaddr *sa, /* delete the existing entry in the queue */ TAILQ_REMOVE(&stcb->asoc.asconf_queue, aa, next); - /* free the entry */ sctp_free_ifa(aa->ifa); + /* free the entry */ SCTP_FREE(aa, SCTP_M_ASC_ADDR); return (-1); } else if (type == SCTP_DEL_IP_ADDRESS && @@ -1075,10 +1154,8 @@ sctp_asconf_queue_add_sa(struct sctp_tcb *stcb, struct sockaddr *sa, /* delete the existing entry in the queue */ TAILQ_REMOVE(&stcb->asoc.asconf_queue, aa, next); - /* take the entry off the appropriate list */ - sctp_asconf_addr_mgmt_ack(stcb, aa->ifa, type, 1); + sctp_del_local_addr_restricted(stcb, aa->ifa); /* free the entry */ - sctp_free_ifa(aa->ifa); SCTP_FREE(aa, SCTP_M_ASC_ADDR); return (-1); } @@ -1095,7 +1172,8 @@ sctp_asconf_queue_add_sa(struct sctp_tcb *stcb, struct sockaddr *sa, return (-1); } /* adding new request to the queue */ - SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa), SCTP_M_ASC_ADDR); + SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa), + SCTP_M_ASC_ADDR); if (aa == NULL) { /* didn't get memory */ SCTPDBG(SCTP_DEBUG_ASCONF1, @@ -1454,9 +1532,14 @@ sctp_handle_asconf_ack(struct mbuf *m, int offset, /* clear the sent flag to allow new ASCONFs */ asoc->asconf_sent = 0; if (!TAILQ_EMPTY(&stcb->asoc.asconf_queue)) { +#ifdef SCTP_TIMER_BASED_ASCONF /* we have more params, so restart our timer */ sctp_timer_start(SCTP_TIMER_TYPE_ASCONF, stcb->sctp_ep, stcb, net); +#else + /* we have more params, so send out more */ + sctp_send_asconf(stcb, net); +#endif } } @@ -1528,7 +1611,7 @@ sctp_addr_mgmt_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, } } /* put this address on the "pending/do not use yet" list */ - sctp_add_local_addr_assoc(stcb, ifa, 1); + sctp_add_local_addr_restricted(stcb, ifa); /* * check address scope if address is out of scope, don't queue * anything... note: this would leave the address on both inp and @@ -1585,16 +1668,20 @@ sctp_addr_mgmt_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, if (stcb->asoc.peer_supports_asconf) { /* queue an asconf for this addr */ status = sctp_asconf_queue_add(stcb, ifa, type); + /* - * if queued ok, and in correct state, set the - * ASCONF timer if in non-open state, we will set - * this timer when the state does go open and do all - * the asconf's + * if queued ok, and in the open state, send out the + * ASCONF. If in the non-open state, these will be + * sent when the state goes open. */ if (status == 0 && SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) { +#ifdef SCTP_TIMER_BASED_ASCONF sctp_timer_start(SCTP_TIMER_TYPE_ASCONF, inp, stcb, stcb->asoc.primary_destination); +#else + sctp_send_asconf(stcb, stcb->asoc.primary_destination); +#endif } } } @@ -1602,7 +1689,7 @@ sctp_addr_mgmt_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int -sctp_iterator_ep(struct sctp_inpcb *inp, void *ptr, uint32_t val) +sctp_asconf_iterator_ep(struct sctp_inpcb *inp, void *ptr, uint32_t val) { struct sctp_asconf_iterator *asc; struct sctp_ifa *ifa; @@ -1648,8 +1735,8 @@ sctp_iterator_ep(struct sctp_inpcb *inp, void *ptr, uint32_t val) return (0); } -int -sctp_iterator_ep_end(struct sctp_inpcb *inp, void *ptr, uint32_t val) +static int +sctp_asconf_iterator_ep_end(struct sctp_inpcb *inp, void *ptr, uint32_t val) { struct sctp_ifa *ifa; struct sctp_asconf_iterator *asc; @@ -1683,14 +1770,15 @@ sctp_iterator_ep_end(struct sctp_inpcb *inp, void *ptr, uint32_t val) } void -sctp_iterator_stcb(struct sctp_inpcb *inp, struct sctp_tcb *stcb, void *ptr, - uint32_t val) +sctp_asconf_iterator_stcb(struct sctp_inpcb *inp, struct sctp_tcb *stcb, + void *ptr, uint32_t val) { struct sctp_asconf_iterator *asc; struct sctp_ifa *ifa; struct sctp_laddr *l; int cnt_invalid = 0; int type, status; + int num_queued = 0; asc = (struct sctp_asconf_iterator *)ptr; LIST_FOREACH(l, &asc->list_of_work, sctp_nxt_addr) { @@ -1764,9 +1852,9 @@ sctp_iterator_stcb(struct sctp_inpcb *inp, struct sctp_tcb *stcb, void *ptr, continue; } - /* put this address on the "pending/do not use yet" list */ if (type == SCTP_ADD_IP_ADDRESS) { - sctp_add_local_addr_assoc(stcb, ifa, 1); + /* prevent this address from being used as a source */ + sctp_add_local_addr_restricted(stcb, ifa); } else if (type == SCTP_DEL_IP_ADDRESS) { struct sctp_nets *net; @@ -1797,10 +1885,7 @@ sctp_iterator_stcb(struct sctp_inpcb *inp, struct sctp_tcb *stcb, void *ptr, } } else if (type == SCTP_SET_PRIM_ADDR) { if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) { - /* - * must validate the ifa in question is in - * the ep - */ + /* must validate the ifa is in the ep */ if (sctp_is_addr_in_ep(stcb->sctp_ep, ifa) == 0) { continue; } @@ -1818,29 +1903,32 @@ sctp_iterator_stcb(struct sctp_inpcb *inp, struct sctp_tcb *stcb, void *ptr, } } /* queue an asconf for this address add/delete */ - if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_DO_ASCONF)) { - /* does the peer do asconf? */ - if (stcb->asoc.peer_supports_asconf) { - /* queue an asconf for this addr */ - status = sctp_asconf_queue_add(stcb, ifa, type); - /* - * if queued ok, and in correct state, set - * the ASCONF timer if in non-open state, we - * will set this timer when the state does - * go open and do all the asconf's - */ - if (status == 0 && - SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) { - sctp_timer_start(SCTP_TIMER_TYPE_ASCONF, inp, - stcb, stcb->asoc.primary_destination); + if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_DO_ASCONF) && + stcb->asoc.peer_supports_asconf) { + /* queue an asconf for this addr */ + status = sctp_asconf_queue_add(stcb, ifa, type); + /* + * if queued ok, and in the open state, update the + * count of queued params. If in the non-open + * state, these get sent when the assoc goes open. + */ + if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) { + if (status >= 0) { + num_queued++; } } } } + /* + * If we have queued params in the open state, send out an ASCONF. + */ + if (num_queued > 0) { + sctp_send_asconf(stcb, stcb->asoc.primary_destination); + } } -void -sctp_iterator_end(void *ptr, uint32_t val) +void +sctp_asconf_iterator_end(void *ptr, uint32_t val) { struct sctp_asconf_iterator *asc; struct sctp_ifa *ifa; @@ -1864,10 +1952,10 @@ sctp_iterator_end(void *ptr, uint32_t val) } /* - * sa is the sockaddr to ask the peer to set primary to returns: 0 = - * completed, -1 = error + * sa is the sockaddr to ask the peer to set primary to. + * returns: 0 = completed, -1 = error */ -int32_t +int sctp_set_primary_ip_address_sa(struct sctp_tcb *stcb, struct sockaddr *sa) { /* NOTE: we currently don't check the validity of the address! */ @@ -1875,15 +1963,19 @@ sctp_set_primary_ip_address_sa(struct sctp_tcb *stcb, struct sockaddr *sa) /* queue an ASCONF:SET_PRIM_ADDR to be sent */ if (!sctp_asconf_queue_add_sa(stcb, sa, SCTP_SET_PRIM_ADDR)) { /* set primary queuing succeeded */ + SCTPDBG(SCTP_DEBUG_ASCONF1, + "set_primary_ip_address_sa: queued on tcb=%p, ", + stcb); + SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa); if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) { +#ifdef SCTP_TIMER_BASED_ASCONF sctp_timer_start(SCTP_TIMER_TYPE_ASCONF, stcb->sctp_ep, stcb, stcb->asoc.primary_destination); +#else + sctp_send_asconf(stcb, stcb->asoc.primary_destination); +#endif } - SCTPDBG(SCTP_DEBUG_ASCONF1, - "set_primary_ip_address_sa: queued on tcb=%p, ", - stcb); - SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa); } else { SCTPDBG(SCTP_DEBUG_ASCONF1, "set_primary_ip_address_sa: failed to add to queue on tcb=%p, ", stcb); @@ -1908,15 +2000,18 @@ sctp_set_primary_ip_address(struct sctp_ifa *ifa) if (!sctp_asconf_queue_add(stcb, ifa, SCTP_SET_PRIM_ADDR)) { /* set primary queuing succeeded */ - if (SCTP_GET_STATE(&stcb->asoc) == - SCTP_STATE_OPEN) { + SCTPDBG(SCTP_DEBUG_ASCONF1, "set_primary_ip_address: queued on stcb=%p, ", + stcb); + SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, &ifa->address.sa); + if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) { +#ifdef SCTP_TIMER_BASED_ASCONF sctp_timer_start(SCTP_TIMER_TYPE_ASCONF, stcb->sctp_ep, stcb, stcb->asoc.primary_destination); +#else + sctp_send_asconf(stcb, stcb->asoc.primary_destination); +#endif } - SCTPDBG(SCTP_DEBUG_ASCONF1, "set_primary_ip_address: queued on stcb=%p, ", - stcb); - SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, &ifa->address.sa); } } /* for each stcb */ } /* for each inp */ @@ -2026,6 +2121,10 @@ sctp_compose_asconf(struct sctp_tcb *stcb, int *retlen) if (TAILQ_EMPTY(&stcb->asoc.asconf_queue)) { return (NULL); } + /* can't send a new one if there is one in flight already */ + if (stcb->asoc.asconf_sent > 0) { + return (NULL); + } /* * get a chunk header mbuf and a cluster for the asconf params since * it's simpler to fill in the asconf chunk header lookup address on @@ -2281,15 +2380,19 @@ sctp_process_initack_addresses(struct sctp_tcb *stcb, struct mbuf *m, status = sctp_asconf_queue_add_sa(stcb, sa, SCTP_DEL_IP_ADDRESS); /* - * if queued ok, and in correct state, set - * the ASCONF timer + * if queued ok, and in correct state, send + * out the ASCONF. */ if (status == 0 && SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) { +#ifdef SCTP_TIMER_BASED_ASCONF sctp_timer_start(SCTP_TIMER_TYPE_ASCONF, stcb->sctp_ep, stcb, stcb->asoc.primary_destination); +#else + sctp_send_asconf(stcb, stcb->asoc.primary_destination); +#endif } } } @@ -2597,13 +2700,14 @@ sctp_addr_mgmt_ep_sa(struct sctp_inpcb *inp, struct sockaddr *sa, wi->action = type; atomic_add_int(&ifa->refcount, 1); LIST_INSERT_HEAD(&asc->list_of_work, wi, sctp_nxt_addr); - (void)sctp_initiate_iterator(sctp_iterator_ep, - sctp_iterator_stcb, - sctp_iterator_ep_end, + (void)sctp_initiate_iterator(sctp_asconf_iterator_ep, + sctp_asconf_iterator_stcb, + sctp_asconf_iterator_ep_end, SCTP_PCB_ANY_FLAGS, SCTP_PCB_ANY_FEATURES, - SCTP_ASOC_ANY_STATE, (void *)asc, 0, - sctp_iterator_end, inp, 0); + SCTP_ASOC_ANY_STATE, + (void *)asc, 0, + sctp_asconf_iterator_end, inp, 0); } else { /* invalid address! */ return (EADDRNOTAVAIL); |