Page MenuHomeFreeBSD

D31757.diff
No OneTemporary

D31757.diff

diff --git a/sys/netinet/sctp_pcb.h b/sys/netinet/sctp_pcb.h
--- a/sys/netinet/sctp_pcb.h
+++ b/sys/netinet/sctp_pcb.h
@@ -526,6 +526,9 @@
int
sctp_inpcb_bind(struct socket *, struct sockaddr *,
struct sctp_ifa *, struct thread *);
+int
+sctp_inpcb_bind_locked(struct sctp_inpcb *, struct sockaddr *,
+ struct sctp_ifa *, struct thread *);
struct sctp_tcb *
sctp_findassociation_addr(struct mbuf *, int,
diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c
--- a/sys/netinet/sctp_pcb.c
+++ b/sys/netinet/sctp_pcb.c
@@ -2801,14 +2801,19 @@
SCTP_DECR_LADDR_COUNT();
}
-/* sctp_ifap is used to bypass normal local address validation checks */
+/*
+ * Bind the socket, with the PCB and global info locks held. Note, if a
+ * socket address is specified, the PCB lock may be dropped and re-acquired.
+ *
+ * sctp_ifap is used to bypass normal local address validation checks.
+ */
int
-sctp_inpcb_bind(struct socket *so, struct sockaddr *addr,
+sctp_inpcb_bind_locked(struct sctp_inpcb *inp, struct sockaddr *addr,
struct sctp_ifa *sctp_ifap, struct thread *td)
{
/* bind a ep to a socket address */
struct sctppcbhead *head;
- struct sctp_inpcb *inp, *inp_tmp;
+ struct sctp_inpcb *inp_tmp;
struct inpcb *ip_inp;
int port_reuse_active = 0;
int bindall;
@@ -2821,8 +2826,11 @@
error = 0;
lport = 0;
bindall = 1;
- inp = (struct sctp_inpcb *)so->so_pcb;
- ip_inp = (struct inpcb *)so->so_pcb;
+ ip_inp = &inp->ip_inp.inp;
+
+ SCTP_INP_INFO_WLOCK_ASSERT();
+ SCTP_INP_WLOCK_ASSERT(inp);
+
#ifdef SCTP_DEBUG
if (addr) {
SCTPDBG(SCTP_DEBUG_PCB1, "Bind called port: %d\n",
@@ -2831,8 +2839,6 @@
SCTPDBG_ADDR(SCTP_DEBUG_PCB1, addr);
}
#endif
- SCTP_INP_INFO_WLOCK();
- SCTP_INP_WLOCK(inp);
if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) == 0) {
error = EINVAL;
/* already did a bind, subsequent binds NOT allowed ! */
@@ -2925,20 +2931,16 @@
vrf_id = inp->def_vrf_id;
if (lport) {
- /* increase our count due to the unlock we do */
- SCTP_INP_INCR_REF(inp);
-
/*
* Did the caller specify a port? if so we must see if an ep
* already has this one bound.
*/
/* got to be root to get at low ports */
- if (ntohs(lport) < IPPORT_RESERVED) {
- if ((error = priv_check(td, PRIV_NETINET_RESERVEDPORT)) != 0) {
- SCTP_INP_DECR_REF(inp);
- goto out;
- }
+ if (ntohs(lport) < IPPORT_RESERVED &&
+ (error = priv_check(td, PRIV_NETINET_RESERVEDPORT)) != 0) {
+ goto out;
}
+ SCTP_INP_INCR_REF(inp);
SCTP_INP_WUNLOCK(inp);
if (bindall) {
vrf_id = inp->def_vrf_id;
@@ -2962,10 +2964,11 @@
port_reuse_active = 1;
goto continue_anyway;
}
+ SCTP_INP_WLOCK(inp);
SCTP_INP_DECR_REF(inp);
error = EADDRINUSE;
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, error);
- goto out_inp_unlocked;
+ goto out;
}
} else {
inp_tmp = sctp_pcb_findep(addr, 0, 1, vrf_id);
@@ -2988,10 +2991,11 @@
port_reuse_active = 1;
goto continue_anyway;
}
+ SCTP_INP_WLOCK(inp);
SCTP_INP_DECR_REF(inp);
error = EADDRINUSE;
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, error);
- goto out_inp_unlocked;
+ goto out;
}
}
continue_anyway:
@@ -3201,8 +3205,21 @@
("%s: inp %p is already bound", __func__, inp));
inp->sctp_flags &= ~SCTP_PCB_FLAGS_UNBOUND;
out:
+ return (error);
+}
+
+int
+sctp_inpcb_bind(struct socket *so, struct sockaddr *addr,
+ struct sctp_ifa *sctp_ifap, struct thread *td)
+{
+ struct sctp_inpcb *inp;
+ int error;
+
+ inp = so->so_pcb;
+ SCTP_INP_INFO_WLOCK();
+ SCTP_INP_WLOCK(inp);
+ error = sctp_inpcb_bind_locked(inp, addr, sctp_ifap, td);
SCTP_INP_WUNLOCK(inp);
-out_inp_unlocked:
SCTP_INP_INFO_WUNLOCK();
return (error);
}

File Metadata

Mime Type
text/plain
Expires
Sun, Nov 17, 11:44 PM (22 h, 17 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
14686657
Default Alt Text
D31757.diff (3 KB)

Event Timeline