summaryrefslogtreecommitdiffstats
path: root/sys/netinet/sctputil.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netinet/sctputil.c')
-rw-r--r--sys/netinet/sctputil.c61
1 files changed, 50 insertions, 11 deletions
diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c
index 31b9c06..05ab850 100644
--- a/sys/netinet/sctputil.c
+++ b/sys/netinet/sctputil.c
@@ -806,7 +806,7 @@ sctp_fill_random_store(struct sctp_pcb *m)
}
uint32_t
-sctp_select_initial_TSN(struct sctp_pcb *m)
+sctp_select_initial_TSN(struct sctp_pcb *inp)
{
/*
* A true implementation should use random selection process to get
@@ -815,27 +815,36 @@ sctp_select_initial_TSN(struct sctp_pcb *m)
*/
uint32_t x, *xp;
uint8_t *p;
+ int store_at, new_store;
- if (m->initial_sequence_debug != 0) {
+ if (inp->initial_sequence_debug != 0) {
uint32_t ret;
- ret = m->initial_sequence_debug;
- m->initial_sequence_debug++;
+ ret = inp->initial_sequence_debug;
+ inp->initial_sequence_debug++;
return (ret);
}
- if ((m->store_at + sizeof(u_long)) > SCTP_SIGNATURE_SIZE) {
+retry:
+ store_at = inp->store_at;
+ new_store = store_at + sizeof(uint32_t);
+ if (new_store >= (SCTP_SIGNATURE_SIZE - 3)) {
+ new_store = 0;
+ }
+ if (!atomic_cmpset_int(&inp->store_at, store_at, new_store)) {
+ goto retry;
+ }
+ if (new_store == 0) {
/* Refill the random store */
- sctp_fill_random_store(m);
+ sctp_fill_random_store(inp);
}
- p = &m->random_store[(int)m->store_at];
+ p = &inp->random_store[store_at];
xp = (uint32_t *) p;
x = *xp;
- m->store_at += sizeof(uint32_t);
return (x);
}
uint32_t
-sctp_select_a_tag(struct sctp_inpcb *m)
+sctp_select_a_tag(struct sctp_inpcb *inp)
{
u_long x, not_done;
struct timeval now;
@@ -843,12 +852,12 @@ sctp_select_a_tag(struct sctp_inpcb *m)
(void)SCTP_GETTIME_TIMEVAL(&now);
not_done = 1;
while (not_done) {
- x = sctp_select_initial_TSN(&m->sctp_ep);
+ x = sctp_select_initial_TSN(&inp->sctp_ep);
if (x == 0) {
/* we never use 0 */
continue;
}
- if (sctp_is_vtag_good(m, x, &now)) {
+ if (sctp_is_vtag_good(inp, x, &now)) {
not_done = 0;
}
}
@@ -1758,6 +1767,15 @@ sctp_timeout_handler(void *t)
#endif
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_ASCONF_TMR, SCTP_SO_NOT_LOCKED);
break;
+ case SCTP_TIMER_TYPE_PRIM_DELETED:
+ if ((stcb == NULL) || (inp == NULL)) {
+ break;
+ }
+ if (sctp_delete_prim_timer(inp, stcb, net)) {
+ goto out_decr;
+ }
+ SCTP_STAT_INCR(sctps_timodelprim);
+ break;
case SCTP_TIMER_TYPE_AUTOCLOSE:
if ((stcb == NULL) || (inp == NULL)) {
@@ -2152,6 +2170,13 @@ sctp_timer_start(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
}
tmr = &stcb->asoc.asconf_timer;
break;
+ case SCTP_TIMER_TYPE_PRIM_DELETED:
+ if ((stcb == NULL) || (net != NULL)) {
+ return;
+ }
+ to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto);
+ tmr = &stcb->asoc.delete_prim_timer;
+ break;
case SCTP_TIMER_TYPE_AUTOCLOSE:
if (stcb == NULL) {
return;
@@ -2330,6 +2355,12 @@ sctp_timer_stop(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
}
tmr = &stcb->asoc.asconf_timer;
break;
+ case SCTP_TIMER_TYPE_PRIM_DELETED:
+ if (stcb == NULL) {
+ return;
+ }
+ tmr = &stcb->asoc.delete_prim_timer;
+ break;
case SCTP_TIMER_TYPE_AUTOCLOSE:
if (stcb == NULL) {
return;
@@ -5629,6 +5660,11 @@ wait_some_more:
SOCKBUF_LOCK(&so->so_rcv);
hold_sblock = 1;
}
+ if ((copied_so_far) && (control->length == 0) &&
+ (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE))
+ ) {
+ goto release;
+ }
if (so->so_rcv.sb_cc <= control->held_length) {
error = sbwait(&so->so_rcv);
if (error) {
@@ -6339,9 +6375,11 @@ sctp_local_addr_count(struct sctp_tcb *stcb)
ipv4_addr_legal = 1;
}
+ SCTP_IPI_ADDR_LOCK();
vrf = sctp_find_vrf(stcb->asoc.vrf_id);
if (vrf == NULL) {
/* no vrf, no addresses */
+ SCTP_IPI_ADDR_UNLOCK();
return (0);
}
if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
@@ -6417,6 +6455,7 @@ sctp_local_addr_count(struct sctp_tcb *stcb)
count++;
}
}
+ SCTP_IPI_ADDR_UNLOCK();
return (count);
}
OpenPOWER on IntegriCloud