Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F132024778
D31908.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
12 KB
Referenced Files
None
Subscribers
None
D31908.diff
View Options
Index: sys/netinet/sctp_input.c
===================================================================
--- sys/netinet/sctp_input.c
+++ sys/netinet/sctp_input.c
@@ -679,7 +679,9 @@
if ((SCTP_GET_STATE(stcb) == SCTP_STATE_COOKIE_WAIT) ||
(SCTP_GET_STATE(stcb) == SCTP_STATE_COOKIE_ECHOED)) {
+ SCTP_INP_INFO_RLOCK();
new_vtag = sctp_select_a_tag(stcb->sctp_ep, stcb->sctp_ep->sctp_lport, stcb->rport, 1);
+ SCTP_INP_INFO_RLOCK();
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
SCTP_INP_INFO_WLOCK();
@@ -2183,6 +2185,8 @@
* INIT/INIT-ACK/COOKIE arrived. But of course then it
* should have went to the other code.. not here.. oh well..
* a bit of protection is worth having..
+ *
+ * XXXMJ unlocked
*/
stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
soisconnected(stcb->sctp_socket);
Index: sys/netinet/sctp_output.c
===================================================================
--- sys/netinet/sctp_output.c
+++ sys/netinet/sctp_output.c
@@ -5817,7 +5817,9 @@
atomic_add_int(&asoc->refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
new_tag:
+ SCTP_INP_INFO_RLOCK();
vtag = sctp_select_a_tag(inp, inp->sctp_lport, sh->src_port, 1);
+ SCTP_INP_INFO_RUNLOCK();
if ((asoc->peer_supports_nat) && (vtag == asoc->my_vtag)) {
/*
* Got a duplicate vtag on some guy behind a
@@ -5834,7 +5836,9 @@
} else {
SCTP_INP_INCR_REF(inp);
SCTP_INP_RUNLOCK(inp);
+ SCTP_INP_INFO_RLOCK();
vtag = sctp_select_a_tag(inp, inp->sctp_lport, sh->src_port, 1);
+ SCTP_INP_INFO_RUNLOCK();
initack->init.initiate_tag = htonl(vtag);
/* get a TSN to use too */
initack->init.initial_tsn = htonl(sctp_select_initial_TSN(&inp->sctp_ep));
@@ -12722,7 +12726,7 @@
panic("Error, should hold create lock and I don't?");
}
#endif
- stcb = sctp_aloc_assoc(inp, addr, &error, 0, 0, vrf_id,
+ stcb = sctp_aloc_assoc_connected(inp, addr, &error, 0, 0, vrf_id,
inp->sctp_ep.pre_open_stream_count,
inp->sctp_ep.port,
p,
@@ -12731,14 +12735,6 @@
/* Error is setup for us in the call */
goto out_unlocked;
}
- if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
- stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
- /*
- * Set the connected flag so we can queue
- * data
- */
- soisconnecting(so);
- }
hold_tcblock = 1;
if (create_lock_applied) {
SCTP_ASOC_CREATE_UNLOCK(inp);
Index: sys/netinet/sctp_pcb.h
===================================================================
--- sys/netinet/sctp_pcb.h
+++ sys/netinet/sctp_pcb.h
@@ -577,6 +577,10 @@
sctp_aloc_assoc(struct sctp_inpcb *, struct sockaddr *,
int *, uint32_t, uint32_t, uint32_t, uint16_t, uint16_t,
struct thread *, int);
+struct sctp_tcb *
+sctp_aloc_assoc_connected(struct sctp_inpcb *, struct sockaddr *,
+ int *, uint32_t, uint32_t, uint32_t, uint16_t, uint16_t,
+ struct thread *, int);
int sctp_free_assoc(struct sctp_inpcb *, struct sctp_tcb *, int, int);
Index: sys/netinet/sctp_pcb.c
===================================================================
--- sys/netinet/sctp_pcb.c
+++ sys/netinet/sctp_pcb.c
@@ -1546,10 +1546,6 @@
struct sctp_tcb *stcb;
uint32_t id;
- if (inp == NULL) {
- SCTP_PRINTF("TSNH ep_associd\n");
- return (NULL);
- }
if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) {
SCTP_PRINTF("TSNH ep_associd0\n");
return (NULL);
@@ -4151,12 +4147,11 @@
* careful to add all additional addresses once they are know right away or
* else the assoc will be may experience a blackout scenario.
*/
-struct sctp_tcb *
-sctp_aloc_assoc(struct sctp_inpcb *inp, struct sockaddr *firstaddr,
+static struct sctp_tcb *
+sctp_aloc_assoc_locked(struct sctp_inpcb *inp, struct sockaddr *firstaddr,
int *error, uint32_t override_tag, uint32_t initial_tsn,
uint32_t vrf_id, uint16_t o_streams, uint16_t port,
- struct thread *p,
- int initialize_auth_params)
+ struct thread *p, int initialize_auth_params)
{
/* note the p argument is only valid in unbound sockets */
@@ -4166,6 +4161,9 @@
uint16_t rport;
int err;
+ SCTP_INP_INFO_WLOCK_ASSERT();
+ SCTP_INP_WLOCK_ASSERT(inp);
+
/*
* Assumption made here: Caller has done a
* sctp_findassociation_ep_addr(ep, addr's); to make sure the
@@ -4182,7 +4180,11 @@
*error = EINVAL;
return (NULL);
}
- SCTP_INP_RLOCK(inp);
+ if (inp->sctp_flags & (SCTP_PCB_FLAGS_SOCKET_GONE | SCTP_PCB_FLAGS_SOCKET_ALLGONE)) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL);
+ *error = EINVAL;
+ return (NULL);
+ }
if ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) &&
((sctp_is_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE)) ||
(inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED))) {
@@ -4192,7 +4194,6 @@
* sctp_aloc_assoc.. or the one-2-many socket. If a peeled
* off, or connected one does this.. its an error.
*/
- SCTP_INP_RUNLOCK(inp);
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL);
*error = EINVAL;
return (NULL);
@@ -4201,7 +4202,6 @@
(inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE)) {
if ((inp->sctp_flags & SCTP_PCB_FLAGS_WAS_CONNECTED) ||
(inp->sctp_flags & SCTP_PCB_FLAGS_WAS_ABORTED)) {
- SCTP_INP_RUNLOCK(inp);
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL);
*error = EINVAL;
return (NULL);
@@ -4245,7 +4245,6 @@
(((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) != 0) &&
(SCTP_IPV6_V6ONLY(inp) != 0))) {
/* Invalid address */
- SCTP_INP_RUNLOCK(inp);
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL);
*error = EINVAL;
return (NULL);
@@ -4265,7 +4264,6 @@
IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr) ||
((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0)) {
/* Invalid address */
- SCTP_INP_RUNLOCK(inp);
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL);
*error = EINVAL;
return (NULL);
@@ -4276,18 +4274,16 @@
#endif
default:
/* not supported family type */
- SCTP_INP_RUNLOCK(inp);
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL);
*error = EINVAL;
return (NULL);
}
- SCTP_INP_RUNLOCK(inp);
if (inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) {
/*
* If you have not performed a bind, then we need to do the
* ephemeral bind for you.
*/
- if ((err = sctp_inpcb_bind(inp->sctp_socket, NULL, NULL, p))) {
+ if ((err = sctp_inpcb_bind_locked(inp, NULL, NULL, p))) {
/* bind error, probably perm */
*error = err;
return (NULL);
@@ -4320,21 +4316,6 @@
*error = err;
return (NULL);
}
- /* and the port */
- SCTP_INP_INFO_WLOCK();
- SCTP_INP_WLOCK(inp);
- if (inp->sctp_flags & (SCTP_PCB_FLAGS_SOCKET_GONE | SCTP_PCB_FLAGS_SOCKET_ALLGONE)) {
- /* inpcb freed while alloc going on */
- SCTP_TCB_LOCK_DESTROY(stcb);
- SCTP_TCB_SEND_LOCK_DESTROY(stcb);
- SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_asoc), stcb);
- SCTP_INP_WUNLOCK(inp);
- SCTP_INP_INFO_WUNLOCK();
- SCTP_DECR_ASOC_COUNT();
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL);
- *error = EINVAL;
- return (NULL);
- }
SCTP_TCB_LOCK(stcb);
asoc->assoc_id = sctp_aloc_a_assoc_id(inp, stcb);
@@ -4342,7 +4323,6 @@
head = &SCTP_BASE_INFO(sctp_asochash)[SCTP_PCBHASH_ASOC(stcb->asoc.my_vtag, SCTP_BASE_INFO(hashasocmark))];
/* put it in the bucket in the vtag hash of assoc's for the system */
LIST_INSERT_HEAD(head, stcb, sctp_asocs);
- SCTP_INP_INFO_WUNLOCK();
if (sctp_add_remote_addr(stcb, firstaddr, NULL, port, SCTP_DO_SETSCOPE, SCTP_ALLOC_ASOC)) {
/* failure.. memory error? */
@@ -4362,6 +4342,7 @@
SCTP_TCB_UNLOCK(stcb);
SCTP_TCB_LOCK_DESTROY(stcb);
SCTP_TCB_SEND_LOCK_DESTROY(stcb);
+ LIST_REMOVE(stcb, sctp_asocs);
LIST_REMOVE(stcb, sctp_tcbasocidhash);
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_asoc), stcb);
SCTP_INP_WUNLOCK(inp);
@@ -4387,11 +4368,55 @@
if (initialize_auth_params == SCTP_INITIALIZE_AUTH_PARAMS) {
sctp_initialize_auth_params(inp, stcb);
}
- SCTP_INP_WUNLOCK(inp);
SCTPDBG(SCTP_DEBUG_PCB1, "Association %p now allocated\n", (void *)stcb);
return (stcb);
}
+struct sctp_tcb *
+sctp_aloc_assoc(struct sctp_inpcb *inp, struct sockaddr *firstaddr,
+ int *error, uint32_t override_tag, uint32_t initial_tsn,
+ uint32_t vrf_id, uint16_t o_streams, uint16_t port,
+ struct thread *p, int initialize_auth_params)
+{
+ struct sctp_tcb *stcb;
+
+ SCTP_INP_INFO_WLOCK();
+ SCTP_INP_WLOCK(inp);
+ stcb = sctp_aloc_assoc_locked(inp, firstaddr, error, override_tag,
+ initial_tsn, vrf_id, o_streams, port, p, initialize_auth_params);
+ SCTP_INP_INFO_WUNLOCK();
+ SCTP_INP_WUNLOCK(inp);
+ return (stcb);
+}
+
+struct sctp_tcb *
+sctp_aloc_assoc_connected(struct sctp_inpcb *inp, struct sockaddr *firstaddr,
+ int *error, uint32_t override_tag, uint32_t initial_tsn,
+ uint32_t vrf_id, uint16_t o_streams, uint16_t port,
+ struct thread *p, int initialize_auth_params)
+{
+ struct sctp_tcb *stcb;
+
+ SCTP_INP_INFO_WLOCK();
+ SCTP_INP_WLOCK(inp);
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
+ SCTP_IS_LISTENING(inp)) {
+ SCTP_INP_INFO_WUNLOCK();
+ SCTP_INP_WUNLOCK(inp);
+ *error = EINVAL;
+ return (NULL);
+ }
+ stcb = sctp_aloc_assoc_locked(inp, firstaddr, error, override_tag,
+ initial_tsn, vrf_id, o_streams, port, p, initialize_auth_params);
+ SCTP_INP_INFO_WUNLOCK();
+ if (stcb != NULL && (inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE)) {
+ inp->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
+ soisconnecting(inp->sctp_socket);
+ }
+ SCTP_INP_WUNLOCK(inp);
+ return (stcb);
+}
+
void
sctp_remove_net(struct sctp_tcb *stcb, struct sctp_nets *net)
{
@@ -4505,7 +4530,7 @@
struct sctp_tagblock *twait_block;
int i;
- SCTP_INP_INFO_RLOCK_ASSERT();
+ SCTP_INP_INFO_LOCK_ASSERT();
chain = &SCTP_BASE_INFO(vtag_timewait)[(tag % SCTP_STACK_VTAG_HASH_SIZE)];
LIST_FOREACH(twait_block, chain, sctp_nxt_tagblock) {
for (i = 0; i < SCTP_NUMBER_IN_VTAG_BLOCK; i++) {
@@ -6672,7 +6697,8 @@
struct sctp_tcb *stcb;
bool result;
- SCTP_INP_INFO_RLOCK();
+ SCTP_INP_INFO_LOCK_ASSERT();
+
head = &SCTP_BASE_INFO(sctp_asochash)[SCTP_PCBHASH_ASOC(tag, SCTP_BASE_INFO(hashasocmark))];
LIST_FOREACH(stcb, head, sctp_asocs) {
/*
@@ -6699,7 +6725,6 @@
}
result = !sctp_is_in_timewait(tag, lport, rport, (uint32_t)now->tv_sec);
out:
- SCTP_INP_INFO_RUNLOCK();
return (result);
}
Index: sys/netinet/sctp_usrreq.c
===================================================================
--- sys/netinet/sctp_usrreq.c
+++ sys/netinet/sctp_usrreq.c
@@ -1412,7 +1412,7 @@
vrf_id = inp->def_vrf_id;
/* We are GOOD to go */
- stcb = sctp_aloc_assoc(inp, sa, &error, 0, 0, vrf_id,
+ stcb = sctp_aloc_assoc_connected(inp, sa, &error, 0, 0, vrf_id,
inp->sctp_ep.pre_open_stream_count,
inp->sctp_ep.port,
(struct thread *)p,
@@ -1421,11 +1421,6 @@
/* Gak! no memory */
goto out_now;
}
- if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
- stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
- /* Set the connected flag so we can queue data */
- soisconnecting(so);
- }
SCTP_SET_STATE(stcb, SCTP_STATE_COOKIE_WAIT);
/* move to second address */
switch (sa->sa_family) {
@@ -7061,7 +7056,7 @@
vrf_id = inp->def_vrf_id;
/* We are GOOD to go */
- stcb = sctp_aloc_assoc(inp, addr, &error, 0, 0, vrf_id,
+ stcb = sctp_aloc_assoc_connected(inp, addr, &error, 0, 0, vrf_id,
inp->sctp_ep.pre_open_stream_count,
inp->sctp_ep.port, p,
SCTP_INITIALIZE_AUTH_PARAMS);
@@ -7069,11 +7064,6 @@
/* Gak! no memory */
goto out_now;
}
- if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
- stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
- /* Set the connected flag so we can queue data */
- soisconnecting(so);
- }
SCTP_SET_STATE(stcb, SCTP_STATE_COOKIE_WAIT);
(void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
Index: sys/netinet6/sctp6_usrreq.c
===================================================================
--- sys/netinet6/sctp6_usrreq.c
+++ sys/netinet6/sctp6_usrreq.c
@@ -945,7 +945,7 @@
return (EALREADY);
}
/* We are GOOD to go */
- stcb = sctp_aloc_assoc(inp, addr, &error, 0, 0, vrf_id,
+ stcb = sctp_aloc_assoc_connected(inp, addr, &error, 0, 0, vrf_id,
inp->sctp_ep.pre_open_stream_count,
inp->sctp_ep.port, p,
SCTP_INITIALIZE_AUTH_PARAMS);
@@ -954,11 +954,6 @@
/* Gak! no memory */
return (error);
}
- if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
- stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
- /* Set the connected flag so we can queue data */
- soisconnecting(so);
- }
SCTP_SET_STATE(stcb, SCTP_STATE_COOKIE_WAIT);
(void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
NET_EPOCH_ENTER(et);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Oct 14, 1:20 AM (6 h, 19 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
23700350
Default Alt Text
D31908.diff (12 KB)
Attached To
Mode
D31908: sctp: Tighten up locking around sctp_aloc_assoc()
Attached
Detach File
Event Timeline
Log In to Comment