Print this page
10409 ipf sometimes freezes RFC 1323 transfers
Reviewed by: Jason King <jbk@joyent.com>


1712                 /*
1713                  * set s0's as appropriate.  Use syn-ack packet as it
1714                  * contains both pieces of required information.
1715                  */
1716                 /*
1717                  * Window scale option is only present in SYN/SYN-ACK packet.
1718                  * Compare with ~TH_FIN to mask out T/TCP setups.
1719                  */
1720                 flags = tcp->th_flags & ~(TH_FIN|TH_ECNALL);
1721                 if (flags == (TH_SYN|TH_ACK)) {
1722                         is->is_s0[source] = ntohl(tcp->th_ack);
1723                         is->is_s0[!source] = ntohl(tcp->th_seq) + 1;
1724                         if (TCP_OFF(tcp) > (sizeof (tcphdr_t) >> 2)) {
1725                                 (void) fr_tcpoptions(fin, tcp, fdata);
1726                         }
1727                         if ((fin->fin_out != 0) && (is->is_pass & FR_NEWISN))
1728                                 fr_checknewisn(fin, is);
1729                 } else if (flags == TH_SYN) {
1730                         is->is_s0[source] = ntohl(tcp->th_seq) + 1;
1731                         if ((TCP_OFF(tcp) > (sizeof(tcphdr_t) >> 2)))
1732                                 (void) fr_tcpoptions(fin, tcp, tdata);
1733 
1734                         if ((fin->fin_out != 0) && (is->is_pass & FR_NEWISN))
1735                                 fr_checknewisn(fin, is);
1736 
1737                 }
1738                 ret = 1;
1739         } else
1740                 fin->fin_flx |= FI_OOW;
1741         MUTEX_EXIT(&is->is_lock);
1742         return ret;
1743 }
1744 
1745 
1746 /* ------------------------------------------------------------------------ */
1747 /* Function:    fr_checknewisn                                              */
1748 /* Returns:     Nil                                                         */
1749 /* Parameters:  fin(I)   - pointer to packet information                    */
1750 /*              is(I)  - pointer to master state structure                  */
1751 /*                                                                          */
1752 /* Check to see if this TCP connection is expecting and needs a new         */


1823          * the window is closed (win == 0).
1824          */
1825         if (win == 0)
1826                 win = 1;
1827 
1828         dsize = fin->fin_dlen - (TCP_OFF(tcp) << 2) +
1829                 ((tcpflags & TH_SYN) ? 1 : 0) + ((tcpflags & TH_FIN) ? 1 : 0);
1830 
1831         /*
1832          * if window scaling is present, the scaling is only allowed
1833          * for windows not in the first SYN packet. In that packet the
1834          * window is 65535 to specify the largest window possible
1835          * for receivers not implementing the window scale option.
1836          * Currently, we do not assume TTCP here. That means that
1837          * if we see a second packet from a host (after the initial
1838          * SYN), we can assume that the receiver of the SYN did
1839          * already send back the SYN/ACK (and thus that we know if
1840          * the receiver also does window scaling)
1841          */
1842         if (!(tcpflags & TH_SYN) && (fdata->td_winflags & TCP_WSCALE_FIRST)) {

1843                 fdata->td_maxwin = win;
1844         }
1845 
1846         end = seq + dsize;
1847 
1848         if ((fdata->td_end == 0) &&
1849             (!(flags & IS_TCPFSM) ||
1850              ((tcpflags & TH_OPENING) == TH_OPENING))) {
1851                 /*
1852                  * Must be a (outgoing) SYN-ACK in reply to a SYN.
1853                  */
1854                 fdata->td_end = end - 1;
1855                 fdata->td_maxwin = 1;
1856                 fdata->td_maxend = end + win;
1857         }
1858 
1859         if (!(tcpflags & TH_ACK)) {  /* Pretend an ack was sent */
1860                 ack = tdata->td_end;
1861         } else if (((tcpflags & (TH_ACK|TH_RST)) == (TH_ACK|TH_RST)) &&
1862                    (ack == 0)) {


1885                 int, dsize,
1886                 int, ackskew,
1887                 int, maxwin,
1888                 int, win
1889         );
1890         if (
1891 #if defined(_KERNEL)
1892                 /* 
1893                  * end <-> s + n
1894                  * maxend <-> ack + win
1895                  * this is upperbound check
1896                  */
1897             (SEQ_GE(fdata->td_maxend, end)) &&
1898                 /*
1899                  * this is lowerbound check
1900                  */
1901             (SEQ_GE(seq, fdata->td_end - maxwin)) &&
1902 #endif
1903 /* XXX what about big packets */
1904 #define MAXACKWINDOW 66000
1905             (-ackskew <= (MAXACKWINDOW << fdata->td_winscale)) &&
1906             ( ackskew <= (MAXACKWINDOW << fdata->td_winscale))) {
1907                 inseq = 1;
1908         /*
1909          * Microsoft Windows will send the next packet to the right of the
1910          * window if SACK is in use.
1911          */
1912         } else if ((seq == fdata->td_maxend) && (ackskew == 0) &&
1913             (fdata->td_winflags & TCP_SACK_PERMIT) &&
1914             (tdata->td_winflags & TCP_SACK_PERMIT)) {
1915                 inseq = 1;
1916         /*
1917          * RST ACK with SEQ equal to 0 is sent by some OSes (i.e. Solaris) as a
1918          * response to initial SYN packet, when  there is no application
1919          * listeing to on a port, where the SYN packet has came to.
1920          */
1921         } else if ((seq == 0) && (tcpflags == (TH_RST|TH_ACK)) &&
1922                         (ackskew >= -1) && (ackskew <= 1)) {
1923                 inseq = 1;
1924         } else if (!(flags & IS_TCPFSM)) {
1925 




1712                 /*
1713                  * set s0's as appropriate.  Use syn-ack packet as it
1714                  * contains both pieces of required information.
1715                  */
1716                 /*
1717                  * Window scale option is only present in SYN/SYN-ACK packet.
1718                  * Compare with ~TH_FIN to mask out T/TCP setups.
1719                  */
1720                 flags = tcp->th_flags & ~(TH_FIN|TH_ECNALL);
1721                 if (flags == (TH_SYN|TH_ACK)) {
1722                         is->is_s0[source] = ntohl(tcp->th_ack);
1723                         is->is_s0[!source] = ntohl(tcp->th_seq) + 1;
1724                         if (TCP_OFF(tcp) > (sizeof (tcphdr_t) >> 2)) {
1725                                 (void) fr_tcpoptions(fin, tcp, fdata);
1726                         }
1727                         if ((fin->fin_out != 0) && (is->is_pass & FR_NEWISN))
1728                                 fr_checknewisn(fin, is);
1729                 } else if (flags == TH_SYN) {
1730                         is->is_s0[source] = ntohl(tcp->th_seq) + 1;
1731                         if ((TCP_OFF(tcp) > (sizeof(tcphdr_t) >> 2)))
1732                                 (void) fr_tcpoptions(fin, tcp, fdata);
1733 
1734                         if ((fin->fin_out != 0) && (is->is_pass & FR_NEWISN))
1735                                 fr_checknewisn(fin, is);
1736 
1737                 }
1738                 ret = 1;
1739         } else
1740                 fin->fin_flx |= FI_OOW;
1741         MUTEX_EXIT(&is->is_lock);
1742         return ret;
1743 }
1744 
1745 
1746 /* ------------------------------------------------------------------------ */
1747 /* Function:    fr_checknewisn                                              */
1748 /* Returns:     Nil                                                         */
1749 /* Parameters:  fin(I)   - pointer to packet information                    */
1750 /*              is(I)  - pointer to master state structure                  */
1751 /*                                                                          */
1752 /* Check to see if this TCP connection is expecting and needs a new         */


1823          * the window is closed (win == 0).
1824          */
1825         if (win == 0)
1826                 win = 1;
1827 
1828         dsize = fin->fin_dlen - (TCP_OFF(tcp) << 2) +
1829                 ((tcpflags & TH_SYN) ? 1 : 0) + ((tcpflags & TH_FIN) ? 1 : 0);
1830 
1831         /*
1832          * if window scaling is present, the scaling is only allowed
1833          * for windows not in the first SYN packet. In that packet the
1834          * window is 65535 to specify the largest window possible
1835          * for receivers not implementing the window scale option.
1836          * Currently, we do not assume TTCP here. That means that
1837          * if we see a second packet from a host (after the initial
1838          * SYN), we can assume that the receiver of the SYN did
1839          * already send back the SYN/ACK (and thus that we know if
1840          * the receiver also does window scaling)
1841          */
1842         if (!(tcpflags & TH_SYN) && (fdata->td_winflags & TCP_WSCALE_FIRST)) {
1843                 fdata->td_winflags &= ~TCP_WSCALE_FIRST;
1844                 fdata->td_maxwin = win;
1845         }
1846 
1847         end = seq + dsize;
1848 
1849         if ((fdata->td_end == 0) &&
1850             (!(flags & IS_TCPFSM) ||
1851              ((tcpflags & TH_OPENING) == TH_OPENING))) {
1852                 /*
1853                  * Must be a (outgoing) SYN-ACK in reply to a SYN.
1854                  */
1855                 fdata->td_end = end - 1;
1856                 fdata->td_maxwin = 1;
1857                 fdata->td_maxend = end + win;
1858         }
1859 
1860         if (!(tcpflags & TH_ACK)) {  /* Pretend an ack was sent */
1861                 ack = tdata->td_end;
1862         } else if (((tcpflags & (TH_ACK|TH_RST)) == (TH_ACK|TH_RST)) &&
1863                    (ack == 0)) {


1886                 int, dsize,
1887                 int, ackskew,
1888                 int, maxwin,
1889                 int, win
1890         );
1891         if (
1892 #if defined(_KERNEL)
1893                 /* 
1894                  * end <-> s + n
1895                  * maxend <-> ack + win
1896                  * this is upperbound check
1897                  */
1898             (SEQ_GE(fdata->td_maxend, end)) &&
1899                 /*
1900                  * this is lowerbound check
1901                  */
1902             (SEQ_GE(seq, fdata->td_end - maxwin)) &&
1903 #endif
1904 /* XXX what about big packets */
1905 #define MAXACKWINDOW 66000
1906             (-ackskew <= (MAXACKWINDOW)) &&
1907             ( ackskew <= (MAXACKWINDOW << fdata->td_winscale))) {
1908                 inseq = 1;
1909         /*
1910          * Microsoft Windows will send the next packet to the right of the
1911          * window if SACK is in use.
1912          */
1913         } else if ((seq == fdata->td_maxend) && (ackskew == 0) &&
1914             (fdata->td_winflags & TCP_SACK_PERMIT) &&
1915             (tdata->td_winflags & TCP_SACK_PERMIT)) {
1916                 inseq = 1;
1917         /*
1918          * RST ACK with SEQ equal to 0 is sent by some OSes (i.e. Solaris) as a
1919          * response to initial SYN packet, when  there is no application
1920          * listeing to on a port, where the SYN packet has came to.
1921          */
1922         } else if ((seq == 0) && (tcpflags == (TH_RST|TH_ACK)) &&
1923                         (ackskew >= -1) && (ackskew <= 1)) {
1924                 inseq = 1;
1925         } else if (!(flags & IS_TCPFSM)) {
1926