summaryrefslogtreecommitdiffstats
path: root/sys/netinet/sctp_pcb.c
diff options
context:
space:
mode:
authorrrs <rrs@FreeBSD.org>2007-01-15 15:12:10 +0000
committerrrs <rrs@FreeBSD.org>2007-01-15 15:12:10 +0000
commit094d70fac7c91a2d4fa26601007f25c9d46b058e (patch)
tree7e51ed488736cee7b8b3fdcc5a1fa638803647b8 /sys/netinet/sctp_pcb.c
parentaf870dbd2eb2b7c401adbdae5995f68a5ff112a3 (diff)
downloadFreeBSD-src-094d70fac7c91a2d4fa26601007f25c9d46b058e.zip
FreeBSD-src-094d70fac7c91a2d4fa26601007f25c9d46b058e.tar.gz
- Macroizes the V6ONLY flag check.
- Added a short time wait (not used yet) constant - Corrected the type of the crc32c table (it was unsigned long and really is a uint32_t - Got rid of the user of MHeaders until they are truely needed by lower layers. - Fixed an initialization problem in the readq structure (ordering was off). - Found yet another collision bug when the random number generator returns two numbers on one side (during a collision) that are the same. Also added some tracking of cookies that will go away when we know that we have the last collision bug gone. - Fixed an init bug for book_size_scale, that was causing Early FR code to run when it should not. - Fixed a flight size tracking bug that was associated with Early FR but due to above bug also effected all FR's - Fixed it so Max Burst also will apply to Fast Retransmit. - Fixed a bug in the temporary logging code that allowed a static log array overflow - hashinit_flags is now used. - Two last mcopym's were converted to the macro sctp_m_copym that has always been used by all other places - macro sctp_m_copym was converted to upper case. - We now validate sinfo_flags on input (we did not before). - Fixed a bug that prevented a user from sending data and immediately shuting down with one send operation. - Moved to use hashdestroy instead of free() in our macros. - Fixed an init problem in our timed_wait vtag where we did not fully initialize our time-wait blocks. - Timer stops were re-positioned. - A pcb cleanup method was added, however this probably will not be used in BSD.. unless we make module loadable protocols - I think this fixes the mysterious timer bug.. it was a ordering of locks problem in the way we did timers. It now conforms to the timeout(9) manual (except for the _drain part, we had to do this a different way due to locks). - Fixed error return code so we get either CONNREUSED or CONNRESET depending on where one is in progression - Purged an unused clone macro. - Fixed a read erro code issue where we were NOT getting the proper error when the connection was reset. - Purged an unused clone macro. - Fixed a read erro code issue where we were NOT getting the proper error when the connection was reset. Approved by: gnn
Diffstat (limited to 'sys/netinet/sctp_pcb.c')
-rw-r--r--sys/netinet/sctp_pcb.c92
1 files changed, 38 insertions, 54 deletions
diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c
index 67b5189..b9934b6 100644
--- a/sys/netinet/sctp_pcb.c
+++ b/sys/netinet/sctp_pcb.c
@@ -32,7 +32,6 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-
#include "opt_ipsec.h"
#include "opt_compat.h"
#include "opt_inet6.h"
@@ -671,8 +670,7 @@ sctp_endpoint_probe(struct sockaddr *nam, struct sctppcbhead *head,
/* got it */
if ((nam->sa_family == AF_INET) &&
(inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
- (((struct inpcb *)inp)->inp_flags & IN6P_IPV6_V6ONLY)
- ) {
+ SCTP_IPV6_V6ONLY(inp)) {
/* IPv4 on a IPv6 socket with ONLY IPv6 set */
SCTP_INP_RUNLOCK(inp);
continue;
@@ -1431,8 +1429,7 @@ sctp_inpcb_alloc(struct socket *so)
SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_ep, inp);
return (EOPNOTSUPP);
}
- inp->sctp_tcbhash = hashinit(sctp_pcbtblsize,
- M_PCB,
+ inp->sctp_tcbhash = SCTP_HASH_INIT(sctp_pcbtblsize,
&inp->sctp_hashmark);
if (inp->sctp_tcbhash == NULL) {
printf("Out of SCTP-INPCB->hashinit - no resources\n");
@@ -1592,7 +1589,7 @@ sctp_move_pcb_and_assoc(struct sctp_inpcb *old_inp, struct sctp_inpcb *new_inp,
SCTP_INP_INFO_WUNLOCK();
if (new_inp->sctp_tcbhash != NULL) {
- SCTP_FREE(new_inp->sctp_tcbhash);
+ SCTP_HASH_FREE(new_inp->sctp_tcbhash, new_inp->sctp_hashmark);
new_inp->sctp_tcbhash = NULL;
}
if ((new_inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) {
@@ -1660,8 +1657,7 @@ sctp_isport_inuse(struct sctp_inpcb *inp, uint16_t lport)
/* This one is in use. */
/* check the v6/v4 binding issue */
if ((t_inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
- (((struct inpcb *)t_inp)->inp_flags & IN6P_IPV6_V6ONLY)
- ) {
+ SCTP_IPV6_V6ONLY(t_inp)) {
if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
/* collision in V6 space */
return (1);
@@ -1675,8 +1671,7 @@ sctp_isport_inuse(struct sctp_inpcb *inp, uint16_t lport)
} else {
/* t_inp is bound only V4 */
if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
- (((struct inpcb *)inp)->inp_flags & IN6P_IPV6_V6ONLY)
- ) {
+ SCTP_IPV6_V6ONLY(t_inp)) {
/* no conflict */
continue;
}
@@ -1724,9 +1719,7 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr, struct thread *p)
struct sockaddr_in *sin;
/* IPV6_V6ONLY socket? */
- if (
- (ip_inp->inp_flags & IN6P_IPV6_V6ONLY)
- ) {
+ if (SCTP_IPV6_V6ONLY(ip_inp)) {
return (EINVAL);
}
if (addr->sa_len != sizeof(*sin))
@@ -2460,8 +2453,8 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
#endif
/* Now lets see about freeing the EP hash table. */
if (inp->sctp_tcbhash != NULL) {
- SCTP_FREE(inp->sctp_tcbhash);
- inp->sctp_tcbhash = 0;
+ SCTP_HASH_FREE(inp->sctp_tcbhash, inp->sctp_hashmark);
+ inp->sctp_tcbhash = NULL;
}
/* Now we must put the ep memory back into the zone pool */
SCTP_INP_LOCK_DESTROY(inp);
@@ -3116,8 +3109,8 @@ sctp_del_remote_addr(struct sctp_tcb *stcb, struct sockaddr *remaddr)
}
-static void
-sctp_add_vtag_to_timewait(struct sctp_inpcb *inp, uint32_t tag)
+void
+sctp_add_vtag_to_timewait(struct sctp_inpcb *inp, uint32_t tag, uint32_t time)
{
struct sctpvtaghead *chain;
struct sctp_tagblock *twait_block;
@@ -3134,7 +3127,7 @@ sctp_add_vtag_to_timewait(struct sctp_inpcb *inp, uint32_t tag)
if ((twait_block->vtag_block[i].v_tag == 0) &&
!set) {
twait_block->vtag_block[i].tv_sec_at_expire =
- now.tv_sec + SCTP_TIME_WAIT;
+ now.tv_sec + time;
twait_block->vtag_block[i].v_tag = tag;
set = 1;
} else if ((twait_block->vtag_block[i].v_tag) &&
@@ -3167,7 +3160,7 @@ sctp_add_vtag_to_timewait(struct sctp_inpcb *inp, uint32_t tag)
if (twait_block == NULL) {
return;
}
- memset(twait_block, 0, sizeof(struct sctp_timewait));
+ memset(twait_block, 0, sizeof(struct sctp_tagblock));
LIST_INSERT_HEAD(chain, twait_block, sctp_nxt_tagblock);
twait_block->vtag_block[0].tv_sec_at_expire = now.tv_sec +
SCTP_TIME_WAIT;
@@ -3419,32 +3412,15 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
}
}
}
- /* Stop any timer someone may have started */
- SCTP_OS_TIMER_STOP(&asoc->strreset_timer.timer);
/*
* Make it invalid too, that way if its about to run it will abort
* and return.
*/
- asoc->strreset_timer.type = SCTP_TIMER_TYPE_NONE;
sctp_iterator_asoc_being_freed(inp, stcb);
/* re-increment the lock */
if (from_inpcbfree == SCTP_NORMAL_PROC) {
atomic_add_int(&stcb->asoc.refcnt, -1);
}
- /* now restop the timers to be sure - this is paranoia at is finest! */
- SCTP_OS_TIMER_STOP(&asoc->hb_timer.timer);
- SCTP_OS_TIMER_STOP(&asoc->dack_timer.timer);
- SCTP_OS_TIMER_STOP(&asoc->strreset_timer.timer);
- SCTP_OS_TIMER_STOP(&asoc->asconf_timer.timer);
- SCTP_OS_TIMER_STOP(&asoc->shut_guard_timer.timer);
- SCTP_OS_TIMER_STOP(&asoc->autoclose_timer.timer);
- SCTP_OS_TIMER_STOP(&asoc->delayed_event_timer.timer);
-
- TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
- SCTP_OS_TIMER_STOP(&net->fr_timer.timer);
- SCTP_OS_TIMER_STOP(&net->rxt_timer.timer);
- SCTP_OS_TIMER_STOP(&net->pmtu_timer.timer);
- }
asoc->state = 0;
if (inp->sctp_tcbhash) {
LIST_REMOVE(stcb, sctp_tcbhash);
@@ -3461,8 +3437,28 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
}
/* pull from vtag hash */
LIST_REMOVE(stcb, sctp_asocs);
- sctp_add_vtag_to_timewait(inp, asoc->my_vtag);
+ sctp_add_vtag_to_timewait(inp, asoc->my_vtag, SCTP_TIME_WAIT);
+
+
+ /*
+ * Now restop the timers to be sure - this is paranoia at is finest!
+ */
+ SCTP_OS_TIMER_STOP(&asoc->strreset_timer.timer);
+ SCTP_OS_TIMER_STOP(&asoc->hb_timer.timer);
+ SCTP_OS_TIMER_STOP(&asoc->dack_timer.timer);
+ SCTP_OS_TIMER_STOP(&asoc->strreset_timer.timer);
+ SCTP_OS_TIMER_STOP(&asoc->asconf_timer.timer);
+ SCTP_OS_TIMER_STOP(&asoc->shut_guard_timer.timer);
+ SCTP_OS_TIMER_STOP(&asoc->autoclose_timer.timer);
+ SCTP_OS_TIMER_STOP(&asoc->delayed_event_timer.timer);
+ TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
+ SCTP_OS_TIMER_STOP(&net->fr_timer.timer);
+ SCTP_OS_TIMER_STOP(&net->rxt_timer.timer);
+ SCTP_OS_TIMER_STOP(&net->pmtu_timer.timer);
+ }
+
+ asoc->strreset_timer.type = SCTP_TIMER_TYPE_NONE;
prev = NULL;
/*
* The chunk lists and such SHOULD be empty but we check them just
@@ -4224,26 +4220,16 @@ sctp_pcb_init()
TUNABLE_INT_FETCH("net.inet.sctp.tcbhashsize", &sctp_hashtblsize);
TUNABLE_INT_FETCH("net.inet.sctp.pcbhashsize", &sctp_pcbtblsize);
TUNABLE_INT_FETCH("net.inet.sctp.chunkscale", &sctp_chunkscale);
-
- sctppcbinfo.sctp_asochash = hashinit((sctp_hashtblsize * 31),
- M_PCB,
+ sctppcbinfo.sctp_asochash = SCTP_HASH_INIT((sctp_hashtblsize * 31),
&sctppcbinfo.hashasocmark);
-
- sctppcbinfo.sctp_ephash = hashinit(sctp_hashtblsize,
- M_PCB,
+ sctppcbinfo.sctp_ephash = SCTP_HASH_INIT(sctp_hashtblsize,
&sctppcbinfo.hashmark);
-
- sctppcbinfo.sctp_tcpephash = hashinit(sctp_hashtblsize,
- M_PCB,
+ sctppcbinfo.sctp_tcpephash = SCTP_HASH_INIT(sctp_hashtblsize,
&sctppcbinfo.hashtcpmark);
-
sctppcbinfo.hashtblsize = sctp_hashtblsize;
- /*
- * init the small hash table we use to track restarted asoc's
- */
- sctppcbinfo.sctp_restarthash = hashinit(SCTP_STACK_VTAG_HASH_SIZE,
- M_PCB,
+ /* init the small hash table we use to track restarted asoc's */
+ sctppcbinfo.sctp_restarthash = SCTP_HASH_INIT(SCTP_STACK_VTAG_HASH_SIZE,
&sctppcbinfo.hashrestartmark);
/* init the zones */
@@ -4308,8 +4294,6 @@ sctp_pcb_init()
SCTP_OS_TIMER_INIT(&sctppcbinfo.addr_wq_timer.timer);
- /* port stuff */
- sctppcbinfo.lastlow = ipport_firstauto;
/* Init the TIMEWAIT list */
for (i = 0; i < SCTP_STACK_VTAG_HASH_SIZE; i++) {
LIST_INIT(&sctppcbinfo.vtag_timewait[i]);
OpenPOWER on IntegriCloud