34c34
< __FBSDID("$FreeBSD: head/sys/netinet/sctputil.c 166675 2007-02-12 23:24:31Z rrs $");
---
> __FBSDID("$FreeBSD: head/sys/netinet/sctputil.c 167598 2007-03-15 11:27:14Z rrs $");
39a40
> #include <netinet/sctp_sysctl.h>
50a52
> #include <netinet/sctp_bsd_addr.h>
52,53d53
< extern int sctp_warm_the_crc32_table;
<
56,57d55
< #ifdef SCTP_DEBUG
< extern uint32_t sctp_debug_on;
59,61d56
< #endif
<
<
492c487
< sctp_fill_stat_log(struct mbuf *m)
---
> sctp_fill_stat_log(void *optval, size_t *optsize)
499c494
< if (m == NULL)
---
> if (*optsize < sizeof(struct sctp_cwnd_log_req)) {
501,502c496,497
<
< size_limit = (SCTP_BUF_LEN(m) - sizeof(struct sctp_cwnd_log_req));
---
> }
> size_limit = (*optsize - sizeof(struct sctp_cwnd_log_req));
507c502
< req = mtod(m, struct sctp_cwnd_log_req *);
---
> req = (struct sctp_cwnd_log_req *)optval;
572c567
< SCTP_BUF_LEN(m) = (cnt_out * sizeof(struct sctp_cwnd_log)) + sizeof(struct sctp_cwnd_log_req);
---
> *optsize = (cnt_out * sizeof(struct sctp_cwnd_log)) + sizeof(struct sctp_cwnd_log_req);
912c907
< int for_a_init, uint32_t override_tag)
---
> int for_a_init, uint32_t override_tag, uint32_t vrf_id)
933c928
< #ifdef AF_INET
---
> #ifdef INET
939c934
< #ifdef AF_INET6
---
> #ifdef INET6
959a955
> asoc->vrf_id = vrf_id;
1007a1004
> asoc->sack_freq = m->sctp_ep.sctp_sack_freq;
1042c1039,1042
< LIST_INIT(&asoc->sctp_local_addr_list);
---
> asoc->send_sack = 1;
>
> LIST_INIT(&asoc->sctp_restricted_addrs);
>
1144c1144,1149
< extern unsigned int sctp_early_fr_msec;
---
> #if defined(SCTP_USE_THREAD_BASED_ITERATOR)
> static void
> sctp_iterator_work(struct sctp_iterator *it)
> {
> int iteration_count = 0;
> int inp_skip = 0;
1145a1151,1304
> SCTP_ITERATOR_LOCK();
> if (it->inp)
> SCTP_INP_DECR_REF(it->inp);
>
> if (it->inp == NULL) {
> /* iterator is complete */
> done_with_iterator:
> SCTP_ITERATOR_UNLOCK();
> if (it->function_atend != NULL) {
> (*it->function_atend) (it->pointer, it->val);
> }
> SCTP_FREE(it);
> return;
> }
> select_a_new_ep:
> SCTP_INP_WLOCK(it->inp);
> while (((it->pcb_flags) &&
> ((it->inp->sctp_flags & it->pcb_flags) != it->pcb_flags)) ||
> ((it->pcb_features) &&
> ((it->inp->sctp_features & it->pcb_features) != it->pcb_features))) {
> /* endpoint flags or features don't match, so keep looking */
> if (it->iterator_flags & SCTP_ITERATOR_DO_SINGLE_INP) {
> SCTP_INP_WUNLOCK(it->inp);
> goto done_with_iterator;
> }
> SCTP_INP_WUNLOCK(it->inp);
> it->inp = LIST_NEXT(it->inp, sctp_list);
> if (it->inp == NULL) {
> goto done_with_iterator;
> }
> SCTP_INP_WLOCK(it->inp);
> }
>
> /* mark the current iterator on the endpoint */
> it->inp->inp_starting_point_for_iterator = it;
> SCTP_INP_WUNLOCK(it->inp);
> SCTP_INP_RLOCK(it->inp);
>
> /* now go through each assoc which is in the desired state */
> if (it->done_current_ep == 0) {
> if (it->function_inp != NULL)
> inp_skip = (*it->function_inp) (it->inp, it->pointer, it->val);
> it->done_current_ep = 1;
> }
> if (it->stcb == NULL) {
> /* run the per instance function */
> it->stcb = LIST_FIRST(&it->inp->sctp_asoc_list);
> }
> if ((inp_skip) || it->stcb == NULL) {
> if (it->function_inp_end != NULL) {
> inp_skip = (*it->function_inp_end) (it->inp,
> it->pointer,
> it->val);
> }
> SCTP_INP_RUNLOCK(it->inp);
> goto no_stcb;
> }
> if ((it->stcb) &&
> (it->stcb->asoc.stcb_starting_point_for_iterator == it)) {
> it->stcb->asoc.stcb_starting_point_for_iterator = NULL;
> }
> while (it->stcb) {
> SCTP_TCB_LOCK(it->stcb);
> if (it->asoc_state && ((it->stcb->asoc.state & it->asoc_state) != it->asoc_state)) {
> /* not in the right state... keep looking */
> SCTP_TCB_UNLOCK(it->stcb);
> goto next_assoc;
> }
> /* mark the current iterator on the assoc */
> it->stcb->asoc.stcb_starting_point_for_iterator = it;
> /* see if we have limited out the iterator loop */
> iteration_count++;
> if (iteration_count > SCTP_ITERATOR_MAX_AT_ONCE) {
> /* Pause to let others grab the lock */
> atomic_add_int(&it->stcb->asoc.refcnt, 1);
> SCTP_TCB_UNLOCK(it->stcb);
> SCTP_INP_RUNLOCK(it->inp);
> SCTP_ITERATOR_UNLOCK();
> SCTP_ITERATOR_LOCK();
> SCTP_INP_RLOCK(it->inp);
> SCTP_TCB_LOCK(it->stcb);
> atomic_add_int(&it->stcb->asoc.refcnt, -1);
> iteration_count = 0;
> }
> /* run function on this one */
> (*it->function_assoc) (it->inp, it->stcb, it->pointer, it->val);
>
> /*
> * we lie here, it really needs to have its own type but
> * first I must verify that this won't effect things :-0
> */
> if (it->no_chunk_output == 0)
> sctp_chunk_output(it->inp, it->stcb, SCTP_OUTPUT_FROM_T3);
>
> SCTP_TCB_UNLOCK(it->stcb);
> next_assoc:
> it->stcb = LIST_NEXT(it->stcb, sctp_tcblist);
> if (it->stcb == NULL) {
> /* Run last function */
> if (it->function_inp_end != NULL) {
> inp_skip = (*it->function_inp_end) (it->inp,
> it->pointer,
> it->val);
> }
> }
> }
> SCTP_INP_RUNLOCK(it->inp);
> no_stcb:
> /* done with all assocs on this endpoint, move on to next endpoint */
> it->done_current_ep = 0;
> SCTP_INP_WLOCK(it->inp);
> it->inp->inp_starting_point_for_iterator = NULL;
> SCTP_INP_WUNLOCK(it->inp);
> if (it->iterator_flags & SCTP_ITERATOR_DO_SINGLE_INP) {
> it->inp = NULL;
> } else {
> SCTP_INP_INFO_RLOCK();
> it->inp = LIST_NEXT(it->inp, sctp_list);
> SCTP_INP_INFO_RUNLOCK();
> }
> if (it->inp == NULL) {
> goto done_with_iterator;
> }
> goto select_a_new_ep;
> }
>
> void
> sctp_iterator_worker(void)
> {
> struct sctp_iterator *it = NULL;
>
> /* This function is called with the WQ lock in place */
>
> sctppcbinfo.iterator_running = 1;
> again:
> it = TAILQ_FIRST(&sctppcbinfo.iteratorhead);
> while (it) {
> /* now lets work on this one */
> TAILQ_REMOVE(&sctppcbinfo.iteratorhead, it, sctp_nxt_itr);
> SCTP_IPI_ITERATOR_WQ_UNLOCK();
> sctp_iterator_work(it);
> SCTP_IPI_ITERATOR_WQ_LOCK();
> it = TAILQ_FIRST(&sctppcbinfo.iteratorhead);
> }
> if (TAILQ_FIRST(&sctppcbinfo.iteratorhead)) {
> goto again;
> }
> sctppcbinfo.iterator_running = 0;
> return;
> }
>
> #endif
>
>
1150a1310
> struct sctp_asconf_iterator *asc;
1152,1159c1312,1315
< SCTP_IPI_ADDR_LOCK();
< wi = LIST_FIRST(&sctppcbinfo.addr_wq);
< if (wi == NULL) {
< SCTP_IPI_ADDR_UNLOCK();
< return;
< }
< LIST_REMOVE(wi, sctp_nxt_addr);
< if (!SCTP_LIST_EMPTY(&sctppcbinfo.addr_wq)) {
---
> SCTP_MALLOC(asc, struct sctp_asconf_iterator *,
> sizeof(struct sctp_asconf_iterator), "SCTP_ASCONF_ITERATOR");
> if (asc == NULL) {
> /* Try later, no memory */
1163a1320
> return;
1165,1169c1322,1330
< SCTP_IPI_ADDR_UNLOCK();
< if (wi->action == RTM_ADD) {
< sctp_add_ip_address(wi->ifa);
< } else if (wi->action == RTM_DELETE) {
< sctp_delete_ip_address(wi->ifa);
---
> LIST_INIT(&asc->list_of_work);
> asc->cnt = 0;
> SCTP_IPI_ITERATOR_WQ_LOCK();
> wi = LIST_FIRST(&sctppcbinfo.addr_wq);
> while (wi != NULL) {
> LIST_REMOVE(wi, sctp_nxt_addr);
> LIST_INSERT_HEAD(&asc->list_of_work, wi, sctp_nxt_addr);
> asc->cnt++;
> wi = LIST_FIRST(&sctppcbinfo.addr_wq);
1171,1173c1332,1344
< IFAFREE(wi->ifa);
< SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_laddr, wi);
< SCTP_DECR_LADDR_COUNT();
---
> SCTP_IPI_ITERATOR_WQ_UNLOCK();
> if (asc->cnt == 0) {
> SCTP_FREE(asc);
> } else {
> sctp_initiate_iterator(sctp_iterator_ep,
> sctp_iterator_stcb,
> NULL, /* No ep end for boundall */
> SCTP_PCB_FLAGS_BOUNDALL,
> SCTP_PCB_ANY_FEATURES,
> SCTP_ASOC_ANY_STATE, (void *)asc, 0,
> sctp_iterator_end, NULL, 0);
> }
>
1567c1738
< to_ticks = 1;
---
> to_ticks = SCTP_ADDRESS_TICK_DELAY;
1661d1831
< this_random = stcb->asoc.hb_random_values[0];
1663,1667d1832
< stcb->asoc.hb_ect_randombit = 0;
< } else {
< this_random = stcb->asoc.hb_random_values[stcb->asoc.hb_random_idx];
< stcb->asoc.hb_random_idx++;
< stcb->asoc.hb_ect_randombit = 0;
1668a1834,1836
> this_random = stcb->asoc.hb_random_values[stcb->asoc.hb_random_idx];
> stcb->asoc.hb_random_idx++;
> stcb->asoc.hb_ect_randombit = 0;
2634d2801
< /* recover scope_id for user */
2637c2804,2810
< (void)sa6_recoverscope(sin6);
---
> if (sin6->sin6_scope_id == 0) {
> /* recover scope_id for user */
> (void)sa6_recoverscope(sin6);
> } else {
> /* clear embedded scope_id for user */
> in6_clearscope(&sin6->sin6_addr);
> }
3722,3723c3895,3900
< atomic_add_int(&inp->total_recvs, 1);
< atomic_add_int(&stcb->total_recvs, 1);
---
> if (!(control->spec_flags & M_NOTIFICATION)) {
> atomic_add_int(&inp->total_recvs, 1);
> if (!control->do_not_ref_stcb) {
> atomic_add_int(&stcb->total_recvs, 1);
> }
> }
4022,4023c4199,4200
< struct ifaddr *
< sctp_find_ifa_by_addr(struct sockaddr *sa)
---
> struct sctp_ifa *
> sctp_find_ifa_in_ep(struct sctp_inpcb *inp, struct sockaddr *addr, int holds_lock)
4025,4026c4202
< struct ifnet *ifn;
< struct ifaddr *ifa;
---
> struct sctp_laddr *laddr;
4028,4034c4204,4205
< /* go through all our known interfaces */
< TAILQ_FOREACH(ifn, &ifnet, if_list) {
< /* go through each interface addresses */
< TAILQ_FOREACH(ifa, &ifn->if_addrlist, ifa_list) {
< /* correct family? */
< if (ifa->ifa_addr->sa_family != sa->sa_family)
< continue;
---
> if (holds_lock == 0)
> SCTP_INP_RLOCK(inp);
4036,4039c4207,4235
< #ifdef INET6
< if (ifa->ifa_addr->sa_family == AF_INET6) {
< /* IPv6 address */
< struct sockaddr_in6 *sin1, *sin2, sin6_tmp;
---
> LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
> if (laddr->ifa == NULL)
> continue;
> if (addr->sa_family != laddr->ifa->address.sa.sa_family)
> continue;
> if (addr->sa_family == AF_INET) {
> if (((struct sockaddr_in *)addr)->sin_addr.s_addr ==
> laddr->ifa->address.sin.sin_addr.s_addr) {
> /* found him. */
> if (holds_lock == 0)
> SCTP_INP_RUNLOCK(inp);
> return (laddr->ifa);
> break;
> }
> } else if (addr->sa_family == AF_INET6) {
> if (SCTP6_ARE_ADDR_EQUAL(&((struct sockaddr_in6 *)addr)->sin6_addr,
> &laddr->ifa->address.sin6.sin6_addr)) {
> /* found him. */
> if (holds_lock == 0)
> SCTP_INP_RUNLOCK(inp);
> return (laddr->ifa);
> break;
> }
> }
> }
> if (holds_lock == 0)
> SCTP_INP_RUNLOCK(inp);
> return (NULL);
> }
4041,4059c4237,4241
< sin1 = (struct sockaddr_in6 *)ifa->ifa_addr;
< if (IN6_IS_SCOPE_LINKLOCAL(&sin1->sin6_addr)) {
< /* create a copy and clear scope */
< memcpy(&sin6_tmp, sin1,
< sizeof(struct sockaddr_in6));
< sin1 = &sin6_tmp;
< in6_clearscope(&sin1->sin6_addr);
< }
< sin2 = (struct sockaddr_in6 *)sa;
< if (memcmp(&sin1->sin6_addr, &sin2->sin6_addr,
< sizeof(struct in6_addr)) == 0) {
< /* found it */
< return (ifa);
< }
< } else
< #endif
< if (ifa->ifa_addr->sa_family == AF_INET) {
< /* IPv4 address */
< struct sockaddr_in *sin1, *sin2;
---
> struct sctp_ifa *
> sctp_find_ifa_in_ifn(struct sctp_ifn *sctp_ifnp, struct sockaddr *addr,
> int holds_lock)
> {
> struct sctp_ifa *sctp_ifap;
4061,4067c4243,4256
< sin1 = (struct sockaddr_in *)ifa->ifa_addr;
< sin2 = (struct sockaddr_in *)sa;
< if (sin1->sin_addr.s_addr ==
< sin2->sin_addr.s_addr) {
< /* found it */
< return (ifa);
< }
---
> if (holds_lock == 0)
> SCTP_IPI_ADDR_LOCK();
>
> LIST_FOREACH(sctp_ifap, &sctp_ifnp->ifalist, next_ifa) {
> if (addr->sa_family != sctp_ifap->address.sa.sa_family)
> continue;
> if (addr->sa_family == AF_INET) {
> if (((struct sockaddr_in *)addr)->sin_addr.s_addr ==
> sctp_ifap->address.sin.sin_addr.s_addr) {
> /* found him. */
> if (holds_lock == 0)
> SCTP_IPI_ADDR_UNLOCK();
> return (sctp_ifap);
> break;
4069,4072c4258,4270
< /* else, not AF_INET or AF_INET6, so skip */
< } /* end foreach ifa */
< } /* end foreach ifn */
< /* not found! */
---
> } else if (addr->sa_family == AF_INET6) {
> if (SCTP6_ARE_ADDR_EQUAL(&((struct sockaddr_in6 *)addr)->sin6_addr,
> &sctp_ifap->address.sin6.sin6_addr)) {
> /* found him. */
> if (holds_lock == 0)
> SCTP_IPI_ADDR_UNLOCK();
> return (sctp_ifap);
> break;
> }
> }
> }
> if (holds_lock == 0)
> SCTP_IPI_ADDR_UNLOCK();
4075a4274,4300
> struct sctp_ifa *
> sctp_find_ifa_by_addr(struct sockaddr *addr, uint32_t vrf_id, int holds_lock)
> {
> struct sctp_ifa *sctp_ifap;
> struct sctp_ifn *sctp_ifnp = NULL;
> struct sctp_vrf *vrf;
>
> vrf = sctp_find_vrf(vrf_id);
> if (vrf == NULL)
> return (NULL);
>
> if (holds_lock == 0)
> SCTP_IPI_ADDR_LOCK();
>
> LIST_FOREACH(sctp_ifnp, &vrf->ifnlist, next_ifn) {
> sctp_ifap = sctp_find_ifa_in_ifn(sctp_ifnp, addr, 1);
> if (sctp_ifap) {
> if (holds_lock == 0)
> SCTP_IPI_ADDR_UNLOCK();
> return (sctp_ifap);
> }
> }
> if (holds_lock == 0)
> SCTP_IPI_ADDR_UNLOCK();
> return (NULL);
> }
>
4211c4436,4437
< int alen = 0, slen = 0;
---
> int alen = 0;
> int slen = 0;
4231c4457
< (so->so_state & SS_NBIO)) {
---
> SCTP_SO_IS_NBIO(so)) {
4576c4802
< #ifdef AF_INET
---
> #ifdef INET
4588c4814
< #if defined(AF_INET) && defined(AF_INET6)
---
> #if defined(INET) && defined(INET6)
4607c4833
< #if defined(AF_INET6)
---
> #if defined(INET6)
5255a5482,5490
> int
> sctp_dynamic_set_primary(struct sockaddr *sa, uint32_t vrf_id)
> {
> /*
> * Given a local address. For all associations that holds the
> * address, request a peer-set-primary.
> */
> struct sctp_ifa *ifa;
> struct sctp_laddr *wi;
5256a5492,5528
> ifa = sctp_find_ifa_by_addr(sa, vrf_id, 0);
> if (ifa == NULL) {
> return (EADDRNOTAVAIL);
> }
> /*
> * Now that we have the ifa we must awaken the iterator with this
> * message.
> */
> wi = SCTP_ZONE_GET(sctppcbinfo.ipi_zone_laddr, struct sctp_laddr);
> if (wi == NULL) {
> return (ENOMEM);
> }
> /* Now incr the count and int wi structure */
> SCTP_INCR_LADDR_COUNT();
> bzero(wi, sizeof(*wi));
> wi->ifa = ifa;
> wi->action = SCTP_SET_PRIM_ADDR;
> atomic_add_int(&ifa->refcount, 1);
>
> /* Now add it to the work queue */
> SCTP_IPI_ITERATOR_WQ_LOCK();
> /*
> * Should this really be a tailq? As it is we will process the
> * newest first :-0
> */
> LIST_INSERT_HEAD(&sctppcbinfo.addr_wq, wi, sctp_nxt_addr);
> sctp_timer_start(SCTP_TIMER_TYPE_ADDR_WQ,
> (struct sctp_inpcb *)NULL,
> (struct sctp_tcb *)NULL,
> (struct sctp_nets *)NULL);
> SCTP_IPI_ITERATOR_WQ_UNLOCK();
> return (0);
> }
>
>
>
>
< __FBSDID("$FreeBSD: head/sys/netinet/sctputil.c 166675 2007-02-12 23:24:31Z rrs $");
---
> __FBSDID("$FreeBSD: head/sys/netinet/sctputil.c 167598 2007-03-15 11:27:14Z rrs $");
39a40
> #include <netinet/sctp_sysctl.h>
50a52
> #include <netinet/sctp_bsd_addr.h>
52,53d53
< extern int sctp_warm_the_crc32_table;
<
56,57d55
< #ifdef SCTP_DEBUG
< extern uint32_t sctp_debug_on;
59,61d56
< #endif
<
<
492c487
< sctp_fill_stat_log(struct mbuf *m)
---
> sctp_fill_stat_log(void *optval, size_t *optsize)
499c494
< if (m == NULL)
---
> if (*optsize < sizeof(struct sctp_cwnd_log_req)) {
501,502c496,497
<
< size_limit = (SCTP_BUF_LEN(m) - sizeof(struct sctp_cwnd_log_req));
---
> }
> size_limit = (*optsize - sizeof(struct sctp_cwnd_log_req));
507c502
< req = mtod(m, struct sctp_cwnd_log_req *);
---
> req = (struct sctp_cwnd_log_req *)optval;
572c567
< SCTP_BUF_LEN(m) = (cnt_out * sizeof(struct sctp_cwnd_log)) + sizeof(struct sctp_cwnd_log_req);
---
> *optsize = (cnt_out * sizeof(struct sctp_cwnd_log)) + sizeof(struct sctp_cwnd_log_req);
912c907
< int for_a_init, uint32_t override_tag)
---
> int for_a_init, uint32_t override_tag, uint32_t vrf_id)
933c928
< #ifdef AF_INET
---
> #ifdef INET
939c934
< #ifdef AF_INET6
---
> #ifdef INET6
959a955
> asoc->vrf_id = vrf_id;
1007a1004
> asoc->sack_freq = m->sctp_ep.sctp_sack_freq;
1042c1039,1042
< LIST_INIT(&asoc->sctp_local_addr_list);
---
> asoc->send_sack = 1;
>
> LIST_INIT(&asoc->sctp_restricted_addrs);
>
1144c1144,1149
< extern unsigned int sctp_early_fr_msec;
---
> #if defined(SCTP_USE_THREAD_BASED_ITERATOR)
> static void
> sctp_iterator_work(struct sctp_iterator *it)
> {
> int iteration_count = 0;
> int inp_skip = 0;
1145a1151,1304
> SCTP_ITERATOR_LOCK();
> if (it->inp)
> SCTP_INP_DECR_REF(it->inp);
>
> if (it->inp == NULL) {
> /* iterator is complete */
> done_with_iterator:
> SCTP_ITERATOR_UNLOCK();
> if (it->function_atend != NULL) {
> (*it->function_atend) (it->pointer, it->val);
> }
> SCTP_FREE(it);
> return;
> }
> select_a_new_ep:
> SCTP_INP_WLOCK(it->inp);
> while (((it->pcb_flags) &&
> ((it->inp->sctp_flags & it->pcb_flags) != it->pcb_flags)) ||
> ((it->pcb_features) &&
> ((it->inp->sctp_features & it->pcb_features) != it->pcb_features))) {
> /* endpoint flags or features don't match, so keep looking */
> if (it->iterator_flags & SCTP_ITERATOR_DO_SINGLE_INP) {
> SCTP_INP_WUNLOCK(it->inp);
> goto done_with_iterator;
> }
> SCTP_INP_WUNLOCK(it->inp);
> it->inp = LIST_NEXT(it->inp, sctp_list);
> if (it->inp == NULL) {
> goto done_with_iterator;
> }
> SCTP_INP_WLOCK(it->inp);
> }
>
> /* mark the current iterator on the endpoint */
> it->inp->inp_starting_point_for_iterator = it;
> SCTP_INP_WUNLOCK(it->inp);
> SCTP_INP_RLOCK(it->inp);
>
> /* now go through each assoc which is in the desired state */
> if (it->done_current_ep == 0) {
> if (it->function_inp != NULL)
> inp_skip = (*it->function_inp) (it->inp, it->pointer, it->val);
> it->done_current_ep = 1;
> }
> if (it->stcb == NULL) {
> /* run the per instance function */
> it->stcb = LIST_FIRST(&it->inp->sctp_asoc_list);
> }
> if ((inp_skip) || it->stcb == NULL) {
> if (it->function_inp_end != NULL) {
> inp_skip = (*it->function_inp_end) (it->inp,
> it->pointer,
> it->val);
> }
> SCTP_INP_RUNLOCK(it->inp);
> goto no_stcb;
> }
> if ((it->stcb) &&
> (it->stcb->asoc.stcb_starting_point_for_iterator == it)) {
> it->stcb->asoc.stcb_starting_point_for_iterator = NULL;
> }
> while (it->stcb) {
> SCTP_TCB_LOCK(it->stcb);
> if (it->asoc_state && ((it->stcb->asoc.state & it->asoc_state) != it->asoc_state)) {
> /* not in the right state... keep looking */
> SCTP_TCB_UNLOCK(it->stcb);
> goto next_assoc;
> }
> /* mark the current iterator on the assoc */
> it->stcb->asoc.stcb_starting_point_for_iterator = it;
> /* see if we have limited out the iterator loop */
> iteration_count++;
> if (iteration_count > SCTP_ITERATOR_MAX_AT_ONCE) {
> /* Pause to let others grab the lock */
> atomic_add_int(&it->stcb->asoc.refcnt, 1);
> SCTP_TCB_UNLOCK(it->stcb);
> SCTP_INP_RUNLOCK(it->inp);
> SCTP_ITERATOR_UNLOCK();
> SCTP_ITERATOR_LOCK();
> SCTP_INP_RLOCK(it->inp);
> SCTP_TCB_LOCK(it->stcb);
> atomic_add_int(&it->stcb->asoc.refcnt, -1);
> iteration_count = 0;
> }
> /* run function on this one */
> (*it->function_assoc) (it->inp, it->stcb, it->pointer, it->val);
>
> /*
> * we lie here, it really needs to have its own type but
> * first I must verify that this won't effect things :-0
> */
> if (it->no_chunk_output == 0)
> sctp_chunk_output(it->inp, it->stcb, SCTP_OUTPUT_FROM_T3);
>
> SCTP_TCB_UNLOCK(it->stcb);
> next_assoc:
> it->stcb = LIST_NEXT(it->stcb, sctp_tcblist);
> if (it->stcb == NULL) {
> /* Run last function */
> if (it->function_inp_end != NULL) {
> inp_skip = (*it->function_inp_end) (it->inp,
> it->pointer,
> it->val);
> }
> }
> }
> SCTP_INP_RUNLOCK(it->inp);
> no_stcb:
> /* done with all assocs on this endpoint, move on to next endpoint */
> it->done_current_ep = 0;
> SCTP_INP_WLOCK(it->inp);
> it->inp->inp_starting_point_for_iterator = NULL;
> SCTP_INP_WUNLOCK(it->inp);
> if (it->iterator_flags & SCTP_ITERATOR_DO_SINGLE_INP) {
> it->inp = NULL;
> } else {
> SCTP_INP_INFO_RLOCK();
> it->inp = LIST_NEXT(it->inp, sctp_list);
> SCTP_INP_INFO_RUNLOCK();
> }
> if (it->inp == NULL) {
> goto done_with_iterator;
> }
> goto select_a_new_ep;
> }
>
> void
> sctp_iterator_worker(void)
> {
> struct sctp_iterator *it = NULL;
>
> /* This function is called with the WQ lock in place */
>
> sctppcbinfo.iterator_running = 1;
> again:
> it = TAILQ_FIRST(&sctppcbinfo.iteratorhead);
> while (it) {
> /* now lets work on this one */
> TAILQ_REMOVE(&sctppcbinfo.iteratorhead, it, sctp_nxt_itr);
> SCTP_IPI_ITERATOR_WQ_UNLOCK();
> sctp_iterator_work(it);
> SCTP_IPI_ITERATOR_WQ_LOCK();
> it = TAILQ_FIRST(&sctppcbinfo.iteratorhead);
> }
> if (TAILQ_FIRST(&sctppcbinfo.iteratorhead)) {
> goto again;
> }
> sctppcbinfo.iterator_running = 0;
> return;
> }
>
> #endif
>
>
1150a1310
> struct sctp_asconf_iterator *asc;
1152,1159c1312,1315
< SCTP_IPI_ADDR_LOCK();
< wi = LIST_FIRST(&sctppcbinfo.addr_wq);
< if (wi == NULL) {
< SCTP_IPI_ADDR_UNLOCK();
< return;
< }
< LIST_REMOVE(wi, sctp_nxt_addr);
< if (!SCTP_LIST_EMPTY(&sctppcbinfo.addr_wq)) {
---
> SCTP_MALLOC(asc, struct sctp_asconf_iterator *,
> sizeof(struct sctp_asconf_iterator), "SCTP_ASCONF_ITERATOR");
> if (asc == NULL) {
> /* Try later, no memory */
1163a1320
> return;
1165,1169c1322,1330
< SCTP_IPI_ADDR_UNLOCK();
< if (wi->action == RTM_ADD) {
< sctp_add_ip_address(wi->ifa);
< } else if (wi->action == RTM_DELETE) {
< sctp_delete_ip_address(wi->ifa);
---
> LIST_INIT(&asc->list_of_work);
> asc->cnt = 0;
> SCTP_IPI_ITERATOR_WQ_LOCK();
> wi = LIST_FIRST(&sctppcbinfo.addr_wq);
> while (wi != NULL) {
> LIST_REMOVE(wi, sctp_nxt_addr);
> LIST_INSERT_HEAD(&asc->list_of_work, wi, sctp_nxt_addr);
> asc->cnt++;
> wi = LIST_FIRST(&sctppcbinfo.addr_wq);
1171,1173c1332,1344
< IFAFREE(wi->ifa);
< SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_laddr, wi);
< SCTP_DECR_LADDR_COUNT();
---
> SCTP_IPI_ITERATOR_WQ_UNLOCK();
> if (asc->cnt == 0) {
> SCTP_FREE(asc);
> } else {
> sctp_initiate_iterator(sctp_iterator_ep,
> sctp_iterator_stcb,
> NULL, /* No ep end for boundall */
> SCTP_PCB_FLAGS_BOUNDALL,
> SCTP_PCB_ANY_FEATURES,
> SCTP_ASOC_ANY_STATE, (void *)asc, 0,
> sctp_iterator_end, NULL, 0);
> }
>
1567c1738
< to_ticks = 1;
---
> to_ticks = SCTP_ADDRESS_TICK_DELAY;
1661d1831
< this_random = stcb->asoc.hb_random_values[0];
1663,1667d1832
< stcb->asoc.hb_ect_randombit = 0;
< } else {
< this_random = stcb->asoc.hb_random_values[stcb->asoc.hb_random_idx];
< stcb->asoc.hb_random_idx++;
< stcb->asoc.hb_ect_randombit = 0;
1668a1834,1836
> this_random = stcb->asoc.hb_random_values[stcb->asoc.hb_random_idx];
> stcb->asoc.hb_random_idx++;
> stcb->asoc.hb_ect_randombit = 0;
2634d2801
< /* recover scope_id for user */
2637c2804,2810
< (void)sa6_recoverscope(sin6);
---
> if (sin6->sin6_scope_id == 0) {
> /* recover scope_id for user */
> (void)sa6_recoverscope(sin6);
> } else {
> /* clear embedded scope_id for user */
> in6_clearscope(&sin6->sin6_addr);
> }
3722,3723c3895,3900
< atomic_add_int(&inp->total_recvs, 1);
< atomic_add_int(&stcb->total_recvs, 1);
---
> if (!(control->spec_flags & M_NOTIFICATION)) {
> atomic_add_int(&inp->total_recvs, 1);
> if (!control->do_not_ref_stcb) {
> atomic_add_int(&stcb->total_recvs, 1);
> }
> }
4022,4023c4199,4200
< struct ifaddr *
< sctp_find_ifa_by_addr(struct sockaddr *sa)
---
> struct sctp_ifa *
> sctp_find_ifa_in_ep(struct sctp_inpcb *inp, struct sockaddr *addr, int holds_lock)
4025,4026c4202
< struct ifnet *ifn;
< struct ifaddr *ifa;
---
> struct sctp_laddr *laddr;
4028,4034c4204,4205
< /* go through all our known interfaces */
< TAILQ_FOREACH(ifn, &ifnet, if_list) {
< /* go through each interface addresses */
< TAILQ_FOREACH(ifa, &ifn->if_addrlist, ifa_list) {
< /* correct family? */
< if (ifa->ifa_addr->sa_family != sa->sa_family)
< continue;
---
> if (holds_lock == 0)
> SCTP_INP_RLOCK(inp);
4036,4039c4207,4235
< #ifdef INET6
< if (ifa->ifa_addr->sa_family == AF_INET6) {
< /* IPv6 address */
< struct sockaddr_in6 *sin1, *sin2, sin6_tmp;
---
> LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
> if (laddr->ifa == NULL)
> continue;
> if (addr->sa_family != laddr->ifa->address.sa.sa_family)
> continue;
> if (addr->sa_family == AF_INET) {
> if (((struct sockaddr_in *)addr)->sin_addr.s_addr ==
> laddr->ifa->address.sin.sin_addr.s_addr) {
> /* found him. */
> if (holds_lock == 0)
> SCTP_INP_RUNLOCK(inp);
> return (laddr->ifa);
> break;
> }
> } else if (addr->sa_family == AF_INET6) {
> if (SCTP6_ARE_ADDR_EQUAL(&((struct sockaddr_in6 *)addr)->sin6_addr,
> &laddr->ifa->address.sin6.sin6_addr)) {
> /* found him. */
> if (holds_lock == 0)
> SCTP_INP_RUNLOCK(inp);
> return (laddr->ifa);
> break;
> }
> }
> }
> if (holds_lock == 0)
> SCTP_INP_RUNLOCK(inp);
> return (NULL);
> }
4041,4059c4237,4241
< sin1 = (struct sockaddr_in6 *)ifa->ifa_addr;
< if (IN6_IS_SCOPE_LINKLOCAL(&sin1->sin6_addr)) {
< /* create a copy and clear scope */
< memcpy(&sin6_tmp, sin1,
< sizeof(struct sockaddr_in6));
< sin1 = &sin6_tmp;
< in6_clearscope(&sin1->sin6_addr);
< }
< sin2 = (struct sockaddr_in6 *)sa;
< if (memcmp(&sin1->sin6_addr, &sin2->sin6_addr,
< sizeof(struct in6_addr)) == 0) {
< /* found it */
< return (ifa);
< }
< } else
< #endif
< if (ifa->ifa_addr->sa_family == AF_INET) {
< /* IPv4 address */
< struct sockaddr_in *sin1, *sin2;
---
> struct sctp_ifa *
> sctp_find_ifa_in_ifn(struct sctp_ifn *sctp_ifnp, struct sockaddr *addr,
> int holds_lock)
> {
> struct sctp_ifa *sctp_ifap;
4061,4067c4243,4256
< sin1 = (struct sockaddr_in *)ifa->ifa_addr;
< sin2 = (struct sockaddr_in *)sa;
< if (sin1->sin_addr.s_addr ==
< sin2->sin_addr.s_addr) {
< /* found it */
< return (ifa);
< }
---
> if (holds_lock == 0)
> SCTP_IPI_ADDR_LOCK();
>
> LIST_FOREACH(sctp_ifap, &sctp_ifnp->ifalist, next_ifa) {
> if (addr->sa_family != sctp_ifap->address.sa.sa_family)
> continue;
> if (addr->sa_family == AF_INET) {
> if (((struct sockaddr_in *)addr)->sin_addr.s_addr ==
> sctp_ifap->address.sin.sin_addr.s_addr) {
> /* found him. */
> if (holds_lock == 0)
> SCTP_IPI_ADDR_UNLOCK();
> return (sctp_ifap);
> break;
4069,4072c4258,4270
< /* else, not AF_INET or AF_INET6, so skip */
< } /* end foreach ifa */
< } /* end foreach ifn */
< /* not found! */
---
> } else if (addr->sa_family == AF_INET6) {
> if (SCTP6_ARE_ADDR_EQUAL(&((struct sockaddr_in6 *)addr)->sin6_addr,
> &sctp_ifap->address.sin6.sin6_addr)) {
> /* found him. */
> if (holds_lock == 0)
> SCTP_IPI_ADDR_UNLOCK();
> return (sctp_ifap);
> break;
> }
> }
> }
> if (holds_lock == 0)
> SCTP_IPI_ADDR_UNLOCK();
4075a4274,4300
> struct sctp_ifa *
> sctp_find_ifa_by_addr(struct sockaddr *addr, uint32_t vrf_id, int holds_lock)
> {
> struct sctp_ifa *sctp_ifap;
> struct sctp_ifn *sctp_ifnp = NULL;
> struct sctp_vrf *vrf;
>
> vrf = sctp_find_vrf(vrf_id);
> if (vrf == NULL)
> return (NULL);
>
> if (holds_lock == 0)
> SCTP_IPI_ADDR_LOCK();
>
> LIST_FOREACH(sctp_ifnp, &vrf->ifnlist, next_ifn) {
> sctp_ifap = sctp_find_ifa_in_ifn(sctp_ifnp, addr, 1);
> if (sctp_ifap) {
> if (holds_lock == 0)
> SCTP_IPI_ADDR_UNLOCK();
> return (sctp_ifap);
> }
> }
> if (holds_lock == 0)
> SCTP_IPI_ADDR_UNLOCK();
> return (NULL);
> }
>
4211c4436,4437
< int alen = 0, slen = 0;
---
> int alen = 0;
> int slen = 0;
4231c4457
< (so->so_state & SS_NBIO)) {
---
> SCTP_SO_IS_NBIO(so)) {
4576c4802
< #ifdef AF_INET
---
> #ifdef INET
4588c4814
< #if defined(AF_INET) && defined(AF_INET6)
---
> #if defined(INET) && defined(INET6)
4607c4833
< #if defined(AF_INET6)
---
> #if defined(INET6)
5255a5482,5490
> int
> sctp_dynamic_set_primary(struct sockaddr *sa, uint32_t vrf_id)
> {
> /*
> * Given a local address. For all associations that holds the
> * address, request a peer-set-primary.
> */
> struct sctp_ifa *ifa;
> struct sctp_laddr *wi;
5256a5492,5528
> ifa = sctp_find_ifa_by_addr(sa, vrf_id, 0);
> if (ifa == NULL) {
> return (EADDRNOTAVAIL);
> }
> /*
> * Now that we have the ifa we must awaken the iterator with this
> * message.
> */
> wi = SCTP_ZONE_GET(sctppcbinfo.ipi_zone_laddr, struct sctp_laddr);
> if (wi == NULL) {
> return (ENOMEM);
> }
> /* Now incr the count and int wi structure */
> SCTP_INCR_LADDR_COUNT();
> bzero(wi, sizeof(*wi));
> wi->ifa = ifa;
> wi->action = SCTP_SET_PRIM_ADDR;
> atomic_add_int(&ifa->refcount, 1);
>
> /* Now add it to the work queue */
> SCTP_IPI_ITERATOR_WQ_LOCK();
> /*
> * Should this really be a tailq? As it is we will process the
> * newest first :-0
> */
> LIST_INSERT_HEAD(&sctppcbinfo.addr_wq, wi, sctp_nxt_addr);
> sctp_timer_start(SCTP_TIMER_TYPE_ADDR_WQ,
> (struct sctp_inpcb *)NULL,
> (struct sctp_tcb *)NULL,
> (struct sctp_nets *)NULL);
> SCTP_IPI_ITERATOR_WQ_UNLOCK();
> return (0);
> }
>
>
>
>