summaryrefslogtreecommitdiffstats
path: root/sys/netinet/sctp_pcb.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netinet/sctp_pcb.c')
-rw-r--r--sys/netinet/sctp_pcb.c151
1 files changed, 68 insertions, 83 deletions
diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c
index 536ab72..2b498b7 100644
--- a/sys/netinet/sctp_pcb.c
+++ b/sys/netinet/sctp_pcb.c
@@ -452,6 +452,7 @@ sctp_add_addr_to_vrf(uint32_t vrf_id, void *ifn, uint32_t ifn_index,
}
SCTP_INCR_LADDR_COUNT();
bzero(wi, sizeof(*wi));
+ (void)SCTP_GETTIME_TIMEVAL(&wi->start_time);
wi->ifa = sctp_ifap;
wi->action = SCTP_ADD_IP_ADDRESS;
SCTP_IPI_ITERATOR_WQ_LOCK();
@@ -529,6 +530,7 @@ out_now:
}
SCTP_INCR_LADDR_COUNT();
bzero(wi, sizeof(*wi));
+ (void)SCTP_GETTIME_TIMEVAL(&wi->start_time);
wi->ifa = sctp_ifap;
wi->action = SCTP_DEL_IP_ADDRESS;
SCTP_IPI_ITERATOR_WQ_LOCK();
@@ -994,25 +996,32 @@ sctp_findassociation_ep_asocid(struct sctp_inpcb *inp, sctp_assoc_t asoc_id, int
SCTP_INP_RLOCK(stcb->sctp_ep);
if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) {
SCTP_INP_RUNLOCK(stcb->sctp_ep);
- SCTP_INP_INFO_RUNLOCK();
- return (NULL);
+ continue;
+ }
+ if (want_lock) {
+ SCTP_TCB_LOCK(stcb);
}
- SCTP_TCB_LOCK(stcb);
- SCTP_INP_RUNLOCK(stcb->sctp_ep);
if (stcb->asoc.assoc_id == id) {
/* candidate */
+ SCTP_INP_RUNLOCK(stcb->sctp_ep);
if (inp != stcb->sctp_ep) {
/*
* some other guy has the same id active (id
* collision ??).
*/
- SCTP_TCB_UNLOCK(stcb);
+ if (want_lock) {
+ SCTP_TCB_UNLOCK(stcb);
+ }
continue;
}
SCTP_INP_INFO_RUNLOCK();
return (stcb);
+ } else {
+ SCTP_INP_RUNLOCK(stcb->sctp_ep);
+ }
+ if (want_lock) {
+ SCTP_TCB_UNLOCK(stcb);
}
- SCTP_TCB_UNLOCK(stcb);
}
SCTP_INP_INFO_RUNLOCK();
return (NULL);
@@ -1773,6 +1782,8 @@ sctp_inpcb_alloc(struct socket *so)
SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_ep, inp);
return (EOPNOTSUPP);
}
+ sctp_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE);
+
inp->sctp_tcbhash = SCTP_HASH_INIT(sctp_pcbtblsize,
&inp->sctp_hashmark);
if (inp->sctp_tcbhash == NULL) {
@@ -1957,6 +1968,7 @@ sctp_move_pcb_and_assoc(struct sctp_inpcb *old_inp, struct sctp_inpcb *new_inp,
}
SCTP_INCR_LADDR_COUNT();
bzero(laddr, sizeof(*laddr));
+ (void)SCTP_GETTIME_TIMEVAL(&laddr->start_time);
laddr->ifa = oladdr->ifa;
atomic_add_int(&laddr->ifa->refcount, 1);
LIST_INSERT_HEAD(&new_inp->sctp_addr_list, laddr,
@@ -2184,88 +2196,60 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr, struct thread *p)
}
}
} else {
- /*
- * get any port but lets make sure no one has any address
- * with this port bound
- */
-
- /*
- * setup the inp to the top (I could use the union but this
- * is just as easy
- */
- uint32_t port_guess;
- uint16_t port_attempt;
- int not_done = 1;
- int not_found = 1;
-
- while (not_done) {
- port_guess = sctp_select_initial_TSN(&inp->sctp_ep);
- port_attempt = (port_guess & 0x0000ffff);
- if (port_attempt == 0) {
- goto next_half;
- }
- if (port_attempt < IPPORT_RESERVED) {
- port_attempt += IPPORT_RESERVED;
- }
- not_found = 1;
- vrf_id = inp->def_vrf_id;
- if (sctp_isport_inuse(inp, htons(port_attempt),
- vrf_id) == 1) {
- /* got a port we can use */
- not_found = 0;
- }
- if (not_found == 1) {
- /* We can use this port */
- not_done = 0;
- continue;
+ uint16_t first, last, candiate;
+ uint16_t count;
+ int done;
+
+ if (ip_inp->inp_flags & INP_HIGHPORT) {
+ first = ipport_hifirstauto;
+ last = ipport_hilastauto;
+ } else if (ip_inp->inp_flags & INP_LOWPORT) {
+ if (p && (error =
+ priv_check_cred(p->td_ucred,
+ PRIV_NETINET_RESERVEDPORT,
+ SUSER_ALLOWJAIL
+ )
+ )) {
+ SCTP_INP_DECR_REF(inp);
+ SCTP_INP_WUNLOCK(inp);
+ SCTP_INP_INFO_WUNLOCK();
+ return (error);
}
- /* try upper half */
- next_half:
- port_attempt = ((port_guess >> 16) & 0x0000ffff);
+ first = ipport_lowfirstauto;
+ last = ipport_lowlastauto;
+ } else {
+ first = ipport_firstauto;
+ last = ipport_lastauto;
+ }
+ if (first > last) {
+ uint16_t temp;
- if (port_attempt == 0) {
- goto last_try;
- }
- if (port_attempt < IPPORT_RESERVED) {
- port_attempt += IPPORT_RESERVED;
- }
- not_found = 1;
- vrf_id = inp->def_vrf_id;
- if (sctp_isport_inuse(inp, htons(port_attempt),
- vrf_id) == 1) {
- /* got a port we can use */
- not_found = 0;
- }
- if (not_found == 1) {
- /* We can use this port */
- not_done = 0;
- continue;
- }
- /* try two half's added together */
- last_try:
- port_attempt = (((port_guess >> 16) & 0x0000ffff) +
- (port_guess & 0x0000ffff));
- if (port_attempt == 0) {
- /* get a new random number */
- continue;
- }
- if (port_attempt < IPPORT_RESERVED) {
- port_attempt += IPPORT_RESERVED;
- }
- not_found = 1;
- vrf_id = inp->def_vrf_id;
- if (sctp_isport_inuse(inp, htons(port_attempt), vrf_id) == 1) {
- /* got a port we can use */
- not_found = 0;
+ temp = first;
+ first = last;
+ last = temp;
+ }
+ count = last - first + 1; /* number of candidates */
+ candiate = first + sctp_select_initial_TSN(&inp->sctp_ep) % (count);
+
+ done = 0;
+ while (!done) {
+ if (sctp_isport_inuse(inp, htons(candiate), inp->def_vrf_id) == 0) {
+ done = 1;
}
- if (not_found == 1) {
- /* We can use this port */
- not_done = 0;
- continue;
+ if (!done) {
+ if (--count == 0) {
+ SCTP_INP_DECR_REF(inp);
+ SCTP_INP_WUNLOCK(inp);
+ SCTP_INP_INFO_WUNLOCK();
+ return (EADDRNOTAVAIL);
+ }
+ if (candiate == last)
+ candiate = first;
+ else
+ candiate = candiate + 1;
}
}
- /* we don't get out of the loop until we have a port */
- lport = htons(port_attempt);
+ lport = htons(candiate);
}
SCTP_INP_DECR_REF(inp);
if (inp->sctp_flags & (SCTP_PCB_FLAGS_SOCKET_GONE |
@@ -4448,6 +4432,7 @@ sctp_insert_laddr(struct sctpladdr *list, struct sctp_ifa *ifa, uint32_t act)
}
SCTP_INCR_LADDR_COUNT();
bzero(laddr, sizeof(*laddr));
+ (void)SCTP_GETTIME_TIMEVAL(&laddr->start_time);
laddr->ifa = ifa;
laddr->action = act;
atomic_add_int(&ifa->refcount, 1);
OpenPOWER on IntegriCloud