summaryrefslogtreecommitdiffstats
path: root/sys/netinet
diff options
context:
space:
mode:
authortuexen <tuexen@FreeBSD.org>2012-02-14 12:00:34 +0000
committertuexen <tuexen@FreeBSD.org>2012-02-14 12:00:34 +0000
commitbcfaf51260694a128c1375064baa2ce595f66f24 (patch)
tree09051a1939d8473a25c365f8e8795f37b880d3ed /sys/netinet
parentfec991ff0a2f7e8a6b00e17e11cb33dda126e46b (diff)
downloadFreeBSD-src-bcfaf51260694a128c1375064baa2ce595f66f24.zip
FreeBSD-src-bcfaf51260694a128c1375064baa2ce595f66f24.tar.gz
Fix a bug where the wrong protocol overhead was used. This can lead
to a deadlock of an association when an IPv6 socket was used to communcate with IPv4 and an ICMPv4 fragmentation needed message was received. While there, simplify the code a bit. MFC after: 3 days.
Diffstat (limited to 'sys/netinet')
-rw-r--r--sys/netinet/sctp_output.c87
1 files changed, 62 insertions, 25 deletions
diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c
index a366036..b5bceb2 100644
--- a/sys/netinet/sctp_output.c
+++ b/sys/netinet/sctp_output.c
@@ -7612,16 +7612,22 @@ sctp_fill_outqueue(struct sctp_tcb *stcb,
SCTP_TCB_LOCK_ASSERT(stcb);
asoc = &stcb->asoc;
+ switch (net->ro._l_addr.sa.sa_family) {
+#ifdef INET
+ case AF_INET:
+ goal_mtu = net->mtu - SCTP_MIN_V4_OVERHEAD;
+ break;
+#endif
#ifdef INET6
- if (net->ro._l_addr.sin6.sin6_family == AF_INET6) {
+ case AF_INET6:
goal_mtu = net->mtu - SCTP_MIN_OVERHEAD;
- } else {
- /* ?? not sure what else to do */
- goal_mtu = net->mtu - SCTP_MIN_V4_OVERHEAD;
- }
-#else
- goal_mtu = net->mtu - SCTP_MIN_OVERHEAD;
+ break;
#endif
+ default:
+ /* TSNH */
+ goal_mtu = net->mtu;
+ break;
+ }
/* Need an allowance for the data chunk header too */
goal_mtu -= sizeof(struct sctp_data_chunk);
@@ -8180,10 +8186,21 @@ again_one_more_time:
if (!no_out_cnt)
*num_out += ctl_cnt;
/* recalc a clean slate and setup */
- if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
- mtu = (net->mtu - SCTP_MIN_OVERHEAD);
- } else {
- mtu = (net->mtu - SCTP_MIN_V4_OVERHEAD);
+ switch (net->ro._l_addr.sa.sa_family) {
+#ifdef INET
+ case AF_INET:
+ mtu = net->mtu - SCTP_MIN_V4_OVERHEAD;
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ mtu = net->mtu - SCTP_MIN_OVERHEAD;
+ break;
+#endif
+ default:
+ /* TSNH */
+ mtu = net->mtu;
+ break;
}
to_out = 0;
no_fragmentflg = 1;
@@ -8446,10 +8463,21 @@ again_one_more_time:
if (!no_out_cnt)
*num_out += ctl_cnt;
/* recalc a clean slate and setup */
- if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
- mtu = (net->mtu - SCTP_MIN_OVERHEAD);
- } else {
- mtu = (net->mtu - SCTP_MIN_V4_OVERHEAD);
+ switch (net->ro._l_addr.sa.sa_family) {
+#ifdef INET
+ case AF_INET:
+ mtu = net->mtu - SCTP_MIN_V4_OVERHEAD;
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ mtu = net->mtu - SCTP_MIN_OVERHEAD;
+ break;
+#endif
+ default:
+ /* TSNH */
+ mtu = net->mtu;
+ break;
}
to_out = 0;
no_fragmentflg = 1;
@@ -9492,10 +9520,21 @@ sctp_chunk_retransmission(struct sctp_inpcb *inp,
}
/* pick up the net */
net = chk->whoTo;
- if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
- mtu = (net->mtu - SCTP_MIN_OVERHEAD);
- } else {
+ switch (net->ro._l_addr.sa.sa_family) {
+#ifdef INET
+ case AF_INET:
mtu = net->mtu - SCTP_MIN_V4_OVERHEAD;
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ mtu = net->mtu - SCTP_MIN_OVERHEAD;
+ break;
+#endif
+ default:
+ /* TSNH */
+ mtu = net->mtu;
+ break;
}
if ((asoc->peers_rwnd < mtu) && (asoc->total_flight > 0)) {
@@ -9816,12 +9855,10 @@ one_chunk_around:
return (0);
}
-
-static int
+static void
sctp_timer_validation(struct sctp_inpcb *inp,
struct sctp_tcb *stcb,
- struct sctp_association *asoc,
- int ret)
+ struct sctp_association *asoc)
{
struct sctp_nets *net;
@@ -9829,7 +9866,7 @@ sctp_timer_validation(struct sctp_inpcb *inp,
TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
if (SCTP_OS_TIMER_PENDING(&net->rxt_timer.timer)) {
/* Here is a timer */
- return (ret);
+ return;
}
}
SCTP_TCB_LOCK_ASSERT(stcb);
@@ -9840,7 +9877,7 @@ sctp_timer_validation(struct sctp_inpcb *inp,
} else {
sctp_timer_start(SCTP_TIMER_TYPE_SEND, inp, stcb, asoc->primary_destination);
}
- return (ret);
+ return;
}
void
@@ -9950,7 +9987,7 @@ sctp_chunk_output(struct sctp_inpcb *inp,
#ifdef SCTP_AUDITING_ENABLED
sctp_auditing(8, inp, stcb, NULL);
#endif
- (void)sctp_timer_validation(inp, stcb, asoc, ret);
+ sctp_timer_validation(inp, stcb, asoc);
return;
}
if (ret < 0) {
OpenPOWER on IntegriCloud