Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / usrsctp / usrsctplib / netinet / sctp_pcb.c
index d4adf5d..393069d 100755 (executable)
@@ -32,7 +32,7 @@
 
 #ifdef __FreeBSD__
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/netinet/sctp_pcb.c 252779 2013-07-05 10:08:49Z tuexen $");
+__FBSDID("$FreeBSD: head/sys/netinet/sctp_pcb.c 263922 2014-03-29 21:26:45Z tuexen $");
 #endif
 
 #include <netinet/sctp_os.h>
@@ -82,8 +82,10 @@ struct sctp_base_info system_base_info;
 #endif
 
 #if defined(__Userspace__)
+#if defined(INET) || defined(INET6)
 struct ifaddrs *g_interfaces;
 #endif
+#endif
 /* FIX: we don't handle multiple link local scopes */
 /* "scopeless" replacement IN6_ARE_ADDR_EQUAL */
 #ifdef INET6
@@ -863,7 +865,13 @@ sctp_del_addr_from_vrf(uint32_t vrf_id, struct sockaddr *addr,
                }
                SCTPDBG(SCTP_DEBUG_PCB4, "Deleting ifa %p\n", (void *)sctp_ifap);
                sctp_ifap->localifa_flags &= SCTP_ADDR_VALID;
-               sctp_ifap->localifa_flags |= SCTP_BEING_DELETED;
+                /*
+                * We don't set the flag. This means that the structure will
+                * hang around in EP's that have bound specific to it until
+                * they close. This gives us TCP like behavior if someone
+                * removes an address (or for that matter adds it right back).
+                */
+               /* sctp_ifap->localifa_flags |= SCTP_BEING_DELETED; */
                vrf->total_ifa_count--;
                LIST_REMOVE(sctp_ifap, next_bucket);
                sctp_remove_ifa_from_ifn(sctp_ifap);
@@ -918,8 +926,13 @@ sctp_del_addr_from_vrf(uint32_t vrf_id, struct sockaddr *addr,
 static int
 sctp_does_stcb_own_this_addr(struct sctp_tcb *stcb, struct sockaddr *to)
 {
-       int loopback_scope, ipv4_local_scope, local_scope, site_scope;
-       int ipv4_addr_legal, ipv6_addr_legal;
+       int loopback_scope;
+#if defined(INET)
+       int ipv4_local_scope, ipv4_addr_legal;
+#endif
+#if defined(INET6)
+       int local_scope, site_scope, ipv6_addr_legal;
+#endif
 #if defined(__Userspace__)
        int conn_addr_legal;
 #endif
@@ -928,11 +941,15 @@ sctp_does_stcb_own_this_addr(struct sctp_tcb *stcb, struct sockaddr *to)
        struct sctp_ifa *sctp_ifa;
 
        loopback_scope = stcb->asoc.scope.loopback_scope;
+#if defined(INET)
        ipv4_local_scope = stcb->asoc.scope.ipv4_local_scope;
+       ipv4_addr_legal = stcb->asoc.scope.ipv4_addr_legal;
+#endif
+#if defined(INET6)
        local_scope = stcb->asoc.scope.local_scope;
        site_scope = stcb->asoc.scope.site_scope;
-       ipv4_addr_legal = stcb->asoc.scope.ipv4_addr_legal;
        ipv6_addr_legal = stcb->asoc.scope.ipv6_addr_legal;
+#endif
 #if defined(__Userspace__)
        conn_addr_legal = stcb->asoc.scope.conn_addr_legal;
 #endif
@@ -960,7 +977,9 @@ sctp_does_stcb_own_this_addr(struct sctp_tcb *stcb, struct sockaddr *to)
                                         */
                                        continue;
                                }
-                               
+                               if (sctp_ifa->address.sa.sa_family != to->sa_family) {
+                                       continue;
+                               }
                                switch (sctp_ifa->address.sa.sa_family) {
 #ifdef INET
                                case AF_INET:
@@ -2310,8 +2329,11 @@ sctp_findassociation_special_addr(struct mbuf *m, int offset,
     struct sockaddr *dst)
 {
        struct sctp_paramhdr *phdr, parm_buf;
+#if defined(INET) || defined(INET6)
        struct sctp_tcb *stcb;
-       uint32_t ptype, plen;
+       uint16_t ptype;
+#endif
+       uint16_t plen;
 #ifdef INET
        struct sockaddr_in sin4;
 #endif
@@ -2336,13 +2358,14 @@ sctp_findassociation_special_addr(struct mbuf *m, int offset,
        sin6.sin6_port = sh->src_port;
 #endif
 
-       stcb = NULL;
        offset += sizeof(struct sctp_init_chunk);
 
        phdr = sctp_get_next_param(m, offset, &parm_buf, sizeof(parm_buf));
        while (phdr != NULL) {
                /* now we must see if we want the parameter */
+#if defined(INET) || defined(INET6)
                ptype = ntohs(phdr->param_type);
+#endif
                plen = ntohs(phdr->param_length);
                if (plen == 0) {
                        break;
@@ -2860,7 +2883,7 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id)
 
 #if defined(__APPLE__)
 #if defined(APPLE_LEOPARD) || defined(APPLE_SNOWLEOPARD)
-       inp->ip_inp.inp.inpcb_mtx = lck_mtx_alloc_init(SCTP_BASE_INFO(mtx_grp), SCTP_BASE_INFO(mtx_attr));
+       inp->ip_inp.inp.inpcb_mtx = lck_mtx_alloc_init(SCTP_BASE_INFO(sctbinfo).mtx_grp, SCTP_BASE_INFO(sctbinfo).mtx_attr);
        if (inp->ip_inp.inp.inpcb_mtx == NULL) {
                SCTP_PRINTF("in_pcballoc: can't alloc mutex! so=%p\n", (void *)so);
 #ifdef SCTP_MVRF
@@ -2869,12 +2892,14 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id)
                SCTP_HASH_FREE(inp->sctp_tcbhash, inp->sctp_hashmark);
                so->so_pcb = NULL;
                SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_ep), inp);
-               SCTP_UNLOCK_EXC(SCTP_BASE_INFO(ipi_ep_mtx));
+               SCTP_UNLOCK_EXC(SCTP_BASE_INFO(sctbinfo).ipi_lock);
                SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, ENOMEM);
                return (ENOMEM);
        }
+#elif defined(APPLE_LION) || defined(APPLE_MOUNTAINLION)
+       lck_mtx_init(&inp->ip_inp.inp.inpcb_mtx, SCTP_BASE_INFO(sctbinfo).mtx_grp, SCTP_BASE_INFO(sctbinfo).mtx_attr);
 #else
-       lck_mtx_init(&inp->ip_inp.inp.inpcb_mtx, SCTP_BASE_INFO(mtx_grp), SCTP_BASE_INFO(mtx_attr));
+       lck_mtx_init(&inp->ip_inp.inp.inpcb_mtx, SCTP_BASE_INFO(sctbinfo).ipi_lock_grp, SCTP_BASE_INFO(sctbinfo).ipi_lock_attr);
 #endif
 #endif
        SCTP_INP_INFO_WLOCK();
@@ -2890,7 +2915,12 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id)
        /* add it to the info area */
        LIST_INSERT_HEAD(&SCTP_BASE_INFO(listhead), inp, sctp_list);
 #if defined(__APPLE__)
-       LIST_INSERT_HEAD(&SCTP_BASE_INFO(inplisthead), &inp->ip_inp.inp, inp_list);
+       inp->ip_inp.inp.inp_pcbinfo = &SCTP_BASE_INFO(sctbinfo);
+#if defined(APPLE_LEOPARD) || defined(APPLE_SNOWLEOPARD) || defined(APPLE_LION) || defined(APPLE_MOUNTAINLION)
+       LIST_INSERT_HEAD(SCTP_BASE_INFO(sctbinfo).listhead, &inp->ip_inp.inp, inp_list);
+#else
+       LIST_INSERT_HEAD(SCTP_BASE_INFO(sctbinfo).ipi_listhead, &inp->ip_inp.inp, inp_list);
+#endif
 #endif
        SCTP_INP_INFO_WUNLOCK();
 
@@ -3134,7 +3164,9 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr,
        /* bind a ep to a socket address */
        struct sctppcbhead *head;
        struct sctp_inpcb *inp, *inp_tmp;
+#if defined(INET) || (defined(INET6) && defined(__APPLE__)) || defined(__FreeBSD__) || defined(__APPLE__)
        struct inpcb *ip_inp;
+#endif
        int port_reuse_active = 0;
        int bindall;
 #ifdef SCTP_MVRF
@@ -3148,7 +3180,9 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr,
        error = 0;
        bindall = 1;
        inp = (struct sctp_inpcb *)so->so_pcb;
+#if defined(INET) || (defined(INET6) && defined(__APPLE__)) || defined(__FreeBSD__) || defined(__APPLE__)
        ip_inp = (struct inpcb *)so->so_pcb;
+#endif
 #ifdef SCTP_DEBUG
        if (addr) {
                SCTPDBG(SCTP_DEBUG_PCB1, "Bind called port: %d\n",
@@ -3879,17 +3913,7 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
                                /* Left with Data unread */
                                struct mbuf *op_err;
 
-                               op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr),
-                                                              0, M_NOWAIT, 1, MT_DATA);
-                               if (op_err) {
-                                       /* Fill in the user initiated abort */
-                                       struct sctp_paramhdr *ph;
-
-                                       SCTP_BUF_LEN(op_err) = sizeof(struct sctp_paramhdr);
-                                       ph = mtod(op_err, struct sctp_paramhdr *);
-                                       ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT);
-                                       ph->param_length = htons(SCTP_BUF_LEN(op_err));
-                               }
+                               op_err = sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, "");
                                asoc->sctp_ep->last_abort_code = SCTP_FROM_SCTP_PCB+SCTP_LOC_3;
                                sctp_send_abort_tcb(asoc, op_err, SCTP_SO_LOCKED);
                                SCTP_STAT_INCR_COUNTER32(sctps_aborted);
@@ -3959,17 +3983,7 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
                                    (asoc->asoc.state & SCTP_STATE_PARTIAL_MSG_LEFT)) {
                                        struct mbuf *op_err;
                                abort_anyway:
-                                       op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr),
-                                                                      0, M_NOWAIT, 1, MT_DATA);
-                                       if (op_err) {
-                                               /* Fill in the user initiated abort */
-                                               struct sctp_paramhdr *ph;
-
-                                               SCTP_BUF_LEN(op_err) = sizeof(struct sctp_paramhdr);
-                                               ph = mtod(op_err, struct sctp_paramhdr *);
-                                               ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT);
-                                               ph->param_length = htons(SCTP_BUF_LEN(op_err));
-                                       }
+                                       op_err = sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, "");
                                        asoc->sctp_ep->last_abort_code = SCTP_FROM_SCTP_PCB+SCTP_LOC_5;
                                        sctp_send_abort_tcb(asoc, op_err, SCTP_SO_LOCKED);
                                        SCTP_STAT_INCR_COUNTER32(sctps_aborted);
@@ -4036,17 +4050,7 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
                    ((asoc->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) == 0)) {
                        struct mbuf *op_err;
 
-                       op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr),
-                                                      0, M_NOWAIT, 1, MT_DATA);
-                       if (op_err) {
-                               /* Fill in the user initiated abort */
-                               struct sctp_paramhdr *ph;
-
-                               SCTP_BUF_LEN(op_err) = sizeof(struct sctp_paramhdr);
-                               ph = mtod(op_err, struct sctp_paramhdr *);
-                               ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT);
-                               ph->param_length = htons(SCTP_BUF_LEN(op_err));
-                       }
+                       op_err = sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, "");
                        asoc->sctp_ep->last_abort_code = SCTP_FROM_SCTP_PCB+SCTP_LOC_7;
                        sctp_send_abort_tcb(asoc, op_err, SCTP_SO_LOCKED);
                        SCTP_STAT_INCR_COUNTER32(sctps_aborted);
@@ -4377,7 +4381,7 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr,
 #endif
                if (set_scope) {
 #ifdef SCTP_DONT_DO_PRIVADDR_SCOPE
-                       stcb->ipv4_local_scope = 1;
+                       stcb->asoc.scope.ipv4_local_scope = 1;
 #else
                        if (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) {
                                stcb->asoc.scope.ipv4_local_scope = 1;
@@ -5053,6 +5057,7 @@ sctp_aloc_assoc(struct sctp_inpcb *inp, struct sockaddr *firstaddr,
                        asoc->nr_mapping_array = NULL;
                }
                SCTP_DECR_ASOC_COUNT();
+               SCTP_TCB_UNLOCK(stcb);
                SCTP_TCB_LOCK_DESTROY(stcb);
                SCTP_TCB_SEND_LOCK_DESTROY(stcb);
                LIST_REMOVE(stcb, sctp_tcbasocidhash);
@@ -5867,6 +5872,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
        /* Insert new items here :> */
 
        /* Get rid of LOCK */
+       SCTP_TCB_UNLOCK(stcb);
        SCTP_TCB_LOCK_DESTROY(stcb);
        SCTP_TCB_SEND_LOCK_DESTROY(stcb);
        if (from_inpcbfree == SCTP_NORMAL_PROC) {
@@ -6517,7 +6523,7 @@ sctp_startup_mcore_threads(void)
        }
 }
 #endif
-#if defined(__FreeBSD__) && __FreeBSD_cc_version >= 1100000
+#if defined(__FreeBSD__) && __FreeBSD_cc_version >= 1200000
 static struct mbuf *
 sctp_netisr_hdlr(struct mbuf *m, uintptr_t source)
 {
@@ -6592,6 +6598,25 @@ sctp_pcb_init()
        LIST_INIT(&SCTP_BASE_INFO(listhead));
 #if defined(__APPLE__)
        LIST_INIT(&SCTP_BASE_INFO(inplisthead));
+#if defined(APPLE_LEOPARD) || defined(APPLE_SNOWLEOPARD) || defined(APPLE_LION) || defined(APPLE_MOUNTAINLION)
+       SCTP_BASE_INFO(sctbinfo).listhead = &SCTP_BASE_INFO(inplisthead);
+       SCTP_BASE_INFO(sctbinfo).mtx_grp_attr = lck_grp_attr_alloc_init();
+       lck_grp_attr_setdefault(SCTP_BASE_INFO(sctbinfo).mtx_grp_attr);
+       SCTP_BASE_INFO(sctbinfo).mtx_grp = lck_grp_alloc_init("sctppcb", SCTP_BASE_INFO(sctbinfo).mtx_grp_attr);
+       SCTP_BASE_INFO(sctbinfo).mtx_attr = lck_attr_alloc_init();
+       lck_attr_setdefault(SCTP_BASE_INFO(sctbinfo).mtx_attr);
+#else
+       SCTP_BASE_INFO(sctbinfo).ipi_listhead = &SCTP_BASE_INFO(inplisthead);
+       SCTP_BASE_INFO(sctbinfo).ipi_lock_grp_attr = lck_grp_attr_alloc_init();
+       lck_grp_attr_setdefault(SCTP_BASE_INFO(sctbinfo).ipi_lock_grp_attr);
+       SCTP_BASE_INFO(sctbinfo).ipi_lock_grp = lck_grp_alloc_init("sctppcb", SCTP_BASE_INFO(sctbinfo).ipi_lock_grp_attr);
+       SCTP_BASE_INFO(sctbinfo).ipi_lock_attr = lck_attr_alloc_init();
+       lck_attr_setdefault(SCTP_BASE_INFO(sctbinfo).ipi_lock_attr);
+#endif
+#if !defined(APPLE_LEOPARD) && !defined(APPLE_SNOWLEOPARD) && !defined(APPLE_LION) && !defined(APPLE_MOUNTAINLION)
+       SCTP_BASE_INFO(sctbinfo).ipi_gc = sctp_gc;
+       in_pcbinfo_attach(&SCTP_BASE_INFO(sctbinfo));
+#endif
 #endif
 
 
@@ -6665,17 +6690,6 @@ sctp_pcb_init()
 
 
        /* Master Lock INIT for info structure */
-#if defined(__APPLE__)
-       /* allocate the lock group attribute for SCTP PCB mutexes */
-       SCTP_BASE_INFO(mtx_grp_attr) = lck_grp_attr_alloc_init();
-       lck_grp_attr_setdefault(SCTP_BASE_INFO(mtx_grp_attr));
-       /* allocate the lock group for SCTP PCB mutexes */
-       SCTP_BASE_INFO(mtx_grp) = lck_grp_alloc_init("sctppcb",
-                                                    SCTP_BASE_INFO(mtx_grp_attr));
-       /* allocate the lock attribute for SCTP PCB mutexes */
-       SCTP_BASE_INFO(mtx_attr) = lck_attr_alloc_init();
-       lck_attr_setdefault(SCTP_BASE_INFO(mtx_attr));
-#endif                         /* __APPLE__ */
        SCTP_INP_INFO_LOCK_INIT();
        SCTP_STATLOG_INIT_LOCK();
 
@@ -6713,7 +6727,6 @@ sctp_pcb_init()
        for (i = 0; i < SCTP_STACK_VTAG_HASH_SIZE; i++) {
                LIST_INIT(&SCTP_BASE_INFO(vtag_timewait)[i]);
        }
-
 #if defined(SCTP_PROCESS_LEVEL_LOCKS)
 #if defined(__Userspace_os_Windows)
        InitializeConditionVariable(&sctp_it_ctl.iterator_wakeup);
@@ -6735,7 +6748,7 @@ sctp_pcb_init()
         */
        sctp_init_vrf_list(SCTP_DEFAULT_VRF);
 #endif
-#if defined(__FreeBSD__) && __FreeBSD_cc_version >= 1100000
+#if defined(__FreeBSD__) && __FreeBSD_cc_version >= 1200000
        if (ip_register_flow_handler(sctp_netisr_hdlr, IPPROTO_SCTP)) {
                SCTP_PRINTF("***SCTP- Error can't register netisr handler***\n");
        }
@@ -6768,37 +6781,9 @@ sctp_pcb_finish(void)
        struct sctp_tagblock *twait_block, *prev_twait_block;
        struct sctp_laddr *wi, *nwi;
        int i;
-
-#if defined(__FreeBSD__)
-       /* Free BSD the it thread never exits
-        * but we do clean up. The only way
-        * freebsd reaches here if we have VRF's
-        * but we still add the ifdef to make it
-        * compile on old versions.
-        */
-       {
-               struct sctp_iterator *it, *nit;
-
-               SCTP_IPI_ITERATOR_WQ_LOCK();
-               TAILQ_FOREACH_SAFE(it, &sctp_it_ctl.iteratorhead, sctp_nxt_itr, nit) {
-                       if (it->vn != curvnet) {
-                               continue;
-                       }
-                       TAILQ_REMOVE(&sctp_it_ctl.iteratorhead, it, sctp_nxt_itr);
-                       if (it->function_atend != NULL) {
-                               (*it->function_atend) (it->pointer, it->val);
-                       }
-                       SCTP_FREE(it,SCTP_M_ITER);
-               }
-               SCTP_IPI_ITERATOR_WQ_UNLOCK();
-               SCTP_ITERATOR_LOCK();
-               if ((sctp_it_ctl.cur_it) &&
-                   (sctp_it_ctl.cur_it->vn == curvnet)) {
-                       sctp_it_ctl.iterator_flags |= SCTP_ITERATOR_STOP_CUR_IT;
-               }
-               SCTP_ITERATOR_UNLOCK();
-       }
-#else
+       struct sctp_iterator *it, *nit;
+       
+#if !defined(__FreeBSD__)
        /* Notify the iterator to exit. */
        SCTP_IPI_ITERATOR_WQ_LOCK();
        sctp_it_ctl.iterator_flags |= SCTP_ITERATOR_MUST_EXIT;
@@ -6806,6 +6791,9 @@ sctp_pcb_finish(void)
        SCTP_IPI_ITERATOR_WQ_UNLOCK();
 #endif
 #if defined(__APPLE__)
+#if !defined(APPLE_LEOPARD) && !defined(APPLE_SNOWLEOPARD) && !defined(APPLE_LION) && !defined(APPLE_MOUNTAINLION)
+       in_pcbinfo_detach(&SCTP_BASE_INFO(sctbinfo));
+#endif
        SCTP_IPI_ITERATOR_WQ_LOCK();
        do {
                msleep(&sctp_it_ctl.iterator_flags,
@@ -6814,8 +6802,6 @@ sctp_pcb_finish(void)
        } while ((sctp_it_ctl.iterator_flags & SCTP_ITERATOR_EXITED) == 0);
        thread_deallocate(sctp_it_ctl.thread_proc);
        SCTP_IPI_ITERATOR_WQ_UNLOCK();
-       SCTP_IPI_ITERATOR_WQ_DESTROY();
-       SCTP_ITERATOR_LOCK_DESTROY();
 #endif
 #if defined(__Windows__)
        if (sctp_it_ctl.iterator_thread_obj != NULL) {
@@ -6830,7 +6816,56 @@ sctp_pcb_finish(void)
                ObDereferenceObject(sctp_it_ctl.iterator_thread_obj);
        }
 #endif
-
+#if defined(__Userspace__)
+       if (sctp_it_ctl.thread_proc) {
+#if defined(__Userspace_os_Windows)
+               WaitForSingleObject(sctp_it_ctl.thread_proc, INFINITE);
+               CloseHandle(sctp_it_ctl.thread_proc);
+               sctp_it_ctl.thread_proc = NULL;
+#else
+               pthread_join(sctp_it_ctl.thread_proc, NULL);
+               sctp_it_ctl.thread_proc = 0;
+#endif
+       }
+#endif
+#if defined(SCTP_PROCESS_LEVEL_LOCKS)
+#if defined(__Userspace_os_Windows)
+       DeleteConditionVariable(&sctp_it_ctl.iterator_wakeup);
+#else
+       pthread_cond_destroy(&sctp_it_ctl.iterator_wakeup);
+#endif
+#endif
+       /* In FreeBSD the iterator thread never exits
+        * but we do clean up.
+        * The only way FreeBSD reaches here is if we have VRF's
+        * but we still add the ifdef to make it compile on old versions.
+        */
+       SCTP_IPI_ITERATOR_WQ_LOCK();
+       TAILQ_FOREACH_SAFE(it, &sctp_it_ctl.iteratorhead, sctp_nxt_itr, nit) {
+#if defined(__FreeBSD__) && __FreeBSD_version >= 801000
+               if (it->vn != curvnet) {
+                       continue;
+               }
+#endif
+               TAILQ_REMOVE(&sctp_it_ctl.iteratorhead, it, sctp_nxt_itr);
+               if (it->function_atend != NULL) {
+                       (*it->function_atend) (it->pointer, it->val);
+               }
+               SCTP_FREE(it,SCTP_M_ITER);
+       }
+       SCTP_IPI_ITERATOR_WQ_UNLOCK();
+#if defined(__FreeBSD__) && __FreeBSD_version >= 801000
+       SCTP_ITERATOR_LOCK();
+       if ((sctp_it_ctl.cur_it) &&
+           (sctp_it_ctl.cur_it->vn == curvnet)) {
+               sctp_it_ctl.iterator_flags |= SCTP_ITERATOR_STOP_CUR_IT;
+       }
+       SCTP_ITERATOR_UNLOCK();
+#endif
+#if !defined(__FreeBSD__)
+       SCTP_IPI_ITERATOR_WQ_DESTROY();
+       SCTP_ITERATOR_LOCK_DESTROY();
+#endif
        SCTP_OS_TIMER_STOP(&SCTP_BASE_INFO(addr_wq_timer.timer));
        SCTP_WQ_ADDR_LOCK();
        LIST_FOREACH_SAFE(wi, &SCTP_BASE_INFO(addr_wq), sctp_nxt_addr, nwi) {
@@ -6868,8 +6903,10 @@ sctp_pcb_finish(void)
        SCTP_HASH_FREE(SCTP_BASE_INFO(vrf_ifn_hash), SCTP_BASE_INFO(vrf_ifn_hashmark));
 #if defined(__Userspace__) && !defined(__Userspace_os_Windows)
        /* free memory allocated by getifaddrs call */
+#if defined(INET) || defined(INET6)
        freeifaddrs(g_interfaces);
 #endif
+#endif
 
        /* free the TIMEWAIT list elements malloc'd in the function
         * sctp_add_vtag_to_timewait()...
@@ -6900,16 +6937,20 @@ sctp_pcb_finish(void)
        SCTP_IPI_COUNT_DESTROY();
 #endif
        SCTP_STATLOG_DESTROY();
-#if !defined(__Userspace__)
        SCTP_INP_INFO_LOCK_DESTROY();
-#endif
 
        SCTP_WQ_ADDR_DESTROY();
 
 #if defined(__APPLE__)
-       lck_grp_attr_free(SCTP_BASE_INFO(mtx_grp_attr));
-       lck_grp_free(SCTP_BASE_INFO(mtx_grp));
-       lck_attr_free(SCTP_BASE_INFO(mtx_attr));
+#if defined(APPLE_LEOPARD) || defined(APPLE_SNOWLEOPARD) || defined(APPLE_LION) || defined(APPLE_MOUNTAINLION)
+       lck_grp_attr_free(SCTP_BASE_INFO(sctbinfo).mtx_grp_attr);
+       lck_grp_free(SCTP_BASE_INFO(sctbinfo).mtx_grp);
+       lck_attr_free(SCTP_BASE_INFO(sctbinfo).mtx_attr);
+#else
+       lck_grp_attr_free(SCTP_BASE_INFO(sctbinfo).ipi_lock_grp_attr);
+       lck_grp_free(SCTP_BASE_INFO(sctbinfo).ipi_lock_grp);
+       lck_attr_free(SCTP_BASE_INFO(sctbinfo).ipi_lock_attr);
+#endif
 #endif
 #if defined(__Userspace__)
        SCTP_TIMERQ_LOCK_DESTROY();