Subject: tcp urgent pointer problem in tcp_output.c tcp_input.c
To: None <netbsd-bugs@netbsd.org>
From: Aleph Software Consulting <paleph@netcom.com>
List: netbsd-bugs
Date: 06/02/2000 16:07:31
tcp_output can put out a 0 length data tcp packet with TH_URG and
pointer set.

tcp_input accepts urgent pointer when TH_URG set in tcp packet with no data.

Found this by tracking down a rlogin hang.

We were sending the urgent pointer on a zero length packet. In this case
the tcp sequence # was being to calculate the urgent pointer. A window
update was happening so the pointer was incorrectly set to a large value.
tcp_input() didn't recognize that the packet was zero length when updaing
the so_sobmark value in the socket. This meant the value was incorrectly
incremented beyond the correct point. When subsequent correct (and smaller)
urgent values arrived, they were ignored.  ultimately tcp_input would reach
the point where the urgent pointer should have been. With rlogin, the
reader was now waiting for SS_RCVATMARK to be set. Since so_oobmark was 
incorrect, this flag was not being set properly and rlogin would hang waiting
for it.

According to rfc 793, "To send an urgent indication the user must
also send at least one data octet."

*** tcp_output.c.58     Fri Jun  2 14:22:05 2000
--- tcp_output.c.59     Fri Jun  2 14:21:18 2000
***************
*** 639,645 ****
        if (win < (int)(tp->rcv_adv - tp->rcv_nxt))
                win = (int)(tp->rcv_adv - tp->rcv_nxt);
        ti->ti_win = htons( (u_short) (win>>tp->rcv_scale) );
!       if (SEQ_GT(tp->snd_up, tp->snd_nxt)) {
                ti->ti_urp = htons((u_short)(tp->snd_up - tp->snd_nxt));
                ti->ti_flags |= TH_URG;
        } else
--- 639,651 ----
        if (win < (int)(tp->rcv_adv - tp->rcv_nxt))
                win = (int)(tp->rcv_adv - tp->rcv_nxt);
        ti->ti_win = htons( (u_short) (win>>tp->rcv_scale) );
! 
!       /*
!        * According to rfc 793, "To send an urgent indication the user must
!        * also send at least one data octet."
!        * PV. 774356
!        */
!       if (SEQ_GT(tp->snd_up, tp->snd_nxt) && len) {
                ti->ti_urp = htons((u_short)(tp->snd_up - tp->snd_nxt));
                ti->ti_flags |= TH_URG;
        } else


*** tcp_input.c.100     Fri Jun  2 14:23:36 2000
--- tcp_input.c.101     Fri Jun  2 14:22:51 2000
***************
*** 1824,1831 ****
  
        /*
         * Process segments with URG.
         */
!       if ((tiflags & TH_URG) && ti->ti_urp &&
            TCPS_HAVERCVDFIN(tp->t_state) == 0) {
                TT(tp, TTR_URG, ti, tp->t_state);
                /*
--- 1824,1834 ----
  
        /*
         * Process segments with URG.
+        * according to rfc 793, "To send an urgent indication the user must
+        * also send at least one data octet."
+        * PV. 774356
         */
!       if ((tiflags & TH_URG) && ti->ti_urp && tlen &&
            TCPS_HAVERCVDFIN(tp->t_state) == 0) {
                TT(tp, TTR_URG, ti, tp->t_state);
                /*