svn commit: r280459 - head/sys/netinet
Michael Tuexen
tuexen at FreeBSD.org
Tue Mar 24 21:12:46 UTC 2015
Author: tuexen
Date: Tue Mar 24 21:12:45 2015
New Revision: 280459
URL: https://svnweb.freebsd.org/changeset/base/280459
Log:
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
Modified:
head/sys/netinet/sctp_pcb.c
head/sys/netinet/sctp_usrreq.c
Modified: head/sys/netinet/sctp_pcb.c
==============================================================================
--- head/sys/netinet/sctp_pcb.c Tue Mar 24 20:33:24 2015 (r280458)
+++ head/sys/netinet/sctp_pcb.c Tue Mar 24 21:12:45 2015 (r280459)
@@ -1867,7 +1867,7 @@ sctp_swap_inpcb_for_listen(struct sctp_i
{
/* 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_i
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_i
LIST_INSERT_HEAD(head, inp, sctp_hash);
SCTP_INP_WUNLOCK(inp);
SCTP_INP_RLOCK(inp);
+ SCTP_INP_INFO_WUNLOCK();
return (0);
}
Modified: head/sys/netinet/sctp_usrreq.c
==============================================================================
--- head/sys/netinet/sctp_usrreq.c Tue Mar 24 20:33:24 2015 (r280458)
+++ head/sys/netinet/sctp_usrreq.c Tue Mar 24 21:12:45 2015 (r280459)
@@ -6965,8 +6965,8 @@ sctp_listen(struct socket *so, int backl
#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 backl
* 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) {
More information about the svn-src-head
mailing list