Fix two bugs which resulted in a screwed up end point list:

* Use a save way to walk throught a list while manipulting it.
* Have to appropiate locks in place.
Joint work with rrs@

MFC after: 3 days
This commit is contained in:
Michael Tuexen 2015-03-24 21:12:45 +00:00
parent 512cd1357a
commit 0426123f75
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=280459
2 changed files with 9 additions and 8 deletions

View File

@ -1867,7 +1867,7 @@ sctp_swap_inpcb_for_listen(struct sctp_inpcb *inp)
{
/* For 1-2-1 with port reuse */
struct sctppcbhead *head;
struct sctp_inpcb *tinp;
struct sctp_inpcb *tinp, *ninp;
if (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE)) {
/* only works with port reuse on */
@ -1877,10 +1877,11 @@ sctp_swap_inpcb_for_listen(struct sctp_inpcb *inp)
return (0);
}
SCTP_INP_RUNLOCK(inp);
SCTP_INP_INFO_WLOCK();
head = &SCTP_BASE_INFO(sctp_ephash)[SCTP_PCBHASH_ALLADDR(inp->sctp_lport,
SCTP_BASE_INFO(hashmark))];
/* Kick out all non-listeners to the TCP hash */
LIST_FOREACH(tinp, head, sctp_hash) {
LIST_FOREACH_SAFE(tinp, head, sctp_hash, ninp) {
if (tinp->sctp_lport != inp->sctp_lport) {
continue;
}
@ -1908,6 +1909,7 @@ sctp_swap_inpcb_for_listen(struct sctp_inpcb *inp)
LIST_INSERT_HEAD(head, inp, sctp_hash);
SCTP_INP_WUNLOCK(inp);
SCTP_INP_RLOCK(inp);
SCTP_INP_INFO_WUNLOCK();
return (0);
}

View File

@ -6965,8 +6965,8 @@ sctp_listen(struct socket *so, int backlog, struct thread *p)
#endif
SOCK_LOCK(so);
error = solisten_proto_check(so);
SOCK_UNLOCK(so);
if (error) {
SOCK_UNLOCK(so);
SCTP_INP_RUNLOCK(inp);
return (error);
}
@ -6979,28 +6979,27 @@ sctp_listen(struct socket *so, int backlog, struct thread *p)
* move the guy that was listener to the TCP Pool.
*/
if (sctp_swap_inpcb_for_listen(inp)) {
goto in_use;
SCTP_INP_RUNLOCK(inp);
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
return (EADDRINUSE);
}
}
if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
(inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
/* We are already connected AND the TCP model */
in_use:
SCTP_INP_RUNLOCK(inp);
SOCK_UNLOCK(so);
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
return (EADDRINUSE);
}
SCTP_INP_RUNLOCK(inp);
if (inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) {
/* We must do a bind. */
SOCK_UNLOCK(so);
if ((error = sctp_inpcb_bind(so, NULL, NULL, p))) {
/* bind error, probably perm */
return (error);
}
SOCK_LOCK(so);
}
SOCK_LOCK(so);
/* It appears for 7.0 and on, we must always call this. */
solisten_proto(so, backlog);
if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {