#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>
#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
}
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);
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
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
*/
continue;
}
-
+ if (sctp_ifa->address.sa.sa_family != to->sa_family) {
+ continue;
+ }
switch (sctp_ifa->address.sa.sa_family) {
#ifdef INET
case AF_INET:
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
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;
#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
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();
/* 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();
/* 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
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",
/* 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);
(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);
((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);
#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;
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);
/* 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) {
}
}
#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)
{
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
/* 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();
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);
*/
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");
}
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;
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,
} 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) {
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) {
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()...
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();