Author: tuexen
Date: Tue Feb 14 12:00:34 2012
New Revision: 231672
URL: http://svn.freebsd.org/changeset/base/231672

Log:
  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.

Modified:
  head/sys/netinet/sctp_output.c

Modified: head/sys/netinet/sctp_output.c
==============================================================================
--- head/sys/netinet/sctp_output.c      Tue Feb 14 11:51:32 2012        
(r231671)
+++ head/sys/netinet/sctp_output.c      Tue Feb 14 12:00:34 2012        
(r231672)
@@ -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_in
                }
                /* 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 
        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 
        } 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) {
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to