summaryrefslogtreecommitdiffstats
path: root/sys/netinet/sctputil.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/sctputil.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/sctputil.c')
-rw-r--r--sys/netinet/sctputil.c107
1 files changed, 77 insertions, 30 deletions
diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c
index 6882cee..6867347 100644
--- a/sys/netinet/sctputil.c
+++ b/sys/netinet/sctputil.c
@@ -1080,14 +1080,11 @@ sctp_init_asoc(struct sctp_inpcb *m, struct sctp_association *asoc,
if (m->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
struct in6pcb *inp6;
-
/* Its a V6 socket */
inp6 = (struct in6pcb *)m;
asoc->ipv6_addr_legal = 1;
/* Now look at the binding flag to see if V4 will be legal */
- if (
- (inp6->inp_flags & IN6P_IPV6_V6ONLY)
- == 0) {
+ if (SCTP_IPV6_V6ONLY(inp6) == 0) {
asoc->ipv4_addr_legal = 1;
} else {
/* V4 addresses are NOT legal on the association */
@@ -1099,7 +1096,6 @@ sctp_init_asoc(struct sctp_inpcb *m, struct sctp_association *asoc,
asoc->ipv6_addr_legal = 0;
}
-
asoc->my_rwnd = max(m->sctp_socket->so_rcv.sb_hiwat, SCTP_MINIMAL_RWND);
asoc->peers_rwnd = m->sctp_socket->so_rcv.sb_hiwat;
@@ -1326,15 +1322,28 @@ sctp_timeout_handler(void *t)
return;
}
tmr->stopped_from = 0xa006;
- /* record in stopped what t-o occured */
- tmr->stopped_from = tmr->type;
if (stcb) {
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_LOCK(stcb);
atomic_add_int(&stcb->asoc.refcnt, -1);
}
+ /* record in stopped what t-o occured */
+ tmr->stopped_from = tmr->type;
+
/* mark as being serviced now */
+ if (SCTP_OS_TIMER_PENDING(&tmr->timer)) {
+ /*
+ * Callout has been rescheduled.
+ */
+ goto get_out;
+ }
+ if (!SCTP_OS_TIMER_ACTIVE(&tmr->timer)) {
+ /*
+ * Not active, so no action.
+ */
+ goto get_out;
+ }
SCTP_OS_TIMER_DEACTIVATE(&tmr->timer);
/* call the handler for the appropriate timer type */
@@ -1575,6 +1584,7 @@ sctp_timeout_handler(void *t)
*/
sctp_fix_ecn_echo(&stcb->asoc);
}
+get_out:
if (stcb) {
SCTP_TCB_UNLOCK(stcb);
}
@@ -2299,7 +2309,7 @@ sctp_calculate_sum(struct mbuf *m, int32_t * pktlen, uint32_t offset)
void
sctp_mtu_size_reset(struct sctp_inpcb *inp,
- struct sctp_association *asoc, u_long mtu)
+ struct sctp_association *asoc, uint32_t mtu)
{
/*
* Reset the P-MTU size on this association, this involves changing
@@ -2450,7 +2460,6 @@ sctp_calculate_rto(struct sctp_tcb *stcb,
return ((uint32_t) new_rto);
}
-
/*
* return a pointer to a contiguous piece of data from the given mbuf chain
* starting at 'off' for 'len' bytes. If the desired piece spans more than
@@ -2498,6 +2507,7 @@ sctp_m_getptr(struct mbuf *m, int off, int len, uint8_t * in_ptr)
}
+
struct sctp_paramhdr *
sctp_get_next_param(struct mbuf *m,
int offset,
@@ -2602,9 +2612,10 @@ sctp_notify_assoc_change(uint32_t event, struct sctp_tcb *stcb,
if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) &&
(event == SCTP_COMM_LOST)) {
- if (TAILQ_EMPTY(&stcb->sctp_ep->read_queue)) {
+ if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_WAIT)
+ stcb->sctp_socket->so_error = ECONNREFUSED;
+ else
stcb->sctp_socket->so_error = ECONNRESET;
- }
/* Wake ANY sleepers */
sorwakeup(stcb->sctp_socket);
sowwakeup(stcb->sctp_socket);
@@ -3644,19 +3655,6 @@ sctp_print_address_pkt(struct ip *iph, struct sctphdr *sh)
}
}
-#if defined(HAVE_SCTP_SO_LASTRECORD)
-
-/* cloned from uipc_socket.c */
-
-#define SCTP_SBLINKRECORD(sb, m0) do { \
- if ((sb)->sb_lastrecord != NULL) \
- SCTP_BUF_NEXT_PKT((sb)->sb_lastrecord) = (m0); \
- else \
- (sb)->sb_mb = (m0); \
- (sb)->sb_lastrecord = (m0); \
-} while (/*CONSTCOND*/0)
-#endif
-
void
sctp_pull_off_control_to_new_inp(struct sctp_inpcb *old_inp,
struct sctp_inpcb *new_inp,
@@ -3980,7 +3978,7 @@ sctp_free_bufspace(struct sctp_tcb *stcb, struct sctp_association *asoc,
0,
tp1->mbcnt);
if (asoc->total_output_queue_size >= tp1->book_size) {
- asoc->total_output_queue_size -= tp1->book_size;
+ atomic_add_int(&asoc->total_output_queue_size, -tp1->book_size);
} else {
asoc->total_output_queue_size = 0;
}
@@ -4325,9 +4323,11 @@ restart_nosblocks:
(inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE)) {
goto out;
}
- if (so->so_error || so->so_rcv.sb_state & SBS_CANTRCVMORE) {
+ if (so->so_rcv.sb_state & SBS_CANTRCVMORE) {
if (so->so_error) {
error = so->so_error;
+ if ((in_flags & MSG_PEEK) == 0)
+ so->so_error = 0;
} else {
error = ENOTCONN;
}
@@ -4387,7 +4387,54 @@ restart_nosblocks:
held_length = 0;
goto restart_nosblocks;
} else if (so->so_rcv.sb_cc == 0) {
- error = EWOULDBLOCK;
+ if (so->so_error) {
+ error = so->so_error;
+ if ((in_flags & MSG_PEEK) == 0)
+ so->so_error = 0;
+ } else {
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0) {
+ /*
+ * For active open side clear flags
+ * for re-use passive open is
+ * blocked by connect.
+ */
+ if (inp->sctp_flags & SCTP_PCB_FLAGS_WAS_ABORTED) {
+ /*
+ * You were aborted, passive
+ * side always hits here
+ */
+ error = ECONNRESET;
+ /*
+ * You get this once if you
+ * are active open side
+ */
+ if (!(inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
+ /*
+ * Remove flag if on
+ * the active open
+ * side
+ */
+ inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAS_ABORTED;
+ }
+ }
+ so->so_state &= ~(SS_ISCONNECTING |
+ SS_ISDISCONNECTING |
+ SS_ISCONFIRMING |
+ SS_ISCONNECTED);
+ if (error == 0) {
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_WAS_CONNECTED) == 0) {
+ error = ENOTCONN;
+ } else {
+ inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAS_CONNECTED;
+ }
+ }
+ goto out;
+ }
+ }
+ error = EWOULDBLOCK;
+ }
goto out;
}
error = sblock(&so->so_rcv, (block_allowed ? M_WAITOK : 0));
@@ -4906,7 +4953,7 @@ get_more_data:
sctp_user_rcvd(stcb, &freed_so_far, hold_rlock, rwnd_req);
}
wait_some_more:
- if (so->so_error || so->so_rcv.sb_state & SBS_CANTRCVMORE) {
+ if (so->so_rcv.sb_state & SBS_CANTRCVMORE) {
goto release;
}
if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)
@@ -5034,7 +5081,7 @@ get_more_data2:
goto release;
}
wait_some_more2:
- if (so->so_error || so->so_rcv.sb_state & SBS_CANTRCVMORE)
+ if (so->so_rcv.sb_state & SBS_CANTRCVMORE)
goto release;
if (hold_rlock == 1) {
SCTP_INP_READ_UNLOCK(inp);
@@ -5128,7 +5175,7 @@ get_more_data2:
hold_sblock = 0;
}
splx(s);
- *mp = sctp_m_copym(m, 0, cp_len,
+ *mp = SCTP_M_COPYM(m, 0, cp_len,
M_TRYWAIT
);
s = splnet();
OpenPOWER on IntegriCloud