* Insert TCP options according to the supplied parameters to the place * optp in a consistent way. Can handle unaligned destinations. * * The order of the option processing is crucial for optimal packing and * alignment for the scarce option space. * * The optimal order for a SYN/SYN-ACK segment is: * MSS (4) + NOP (1) + Window scale (3) + SACK permitted (2) + * Timestamp (10) + Signa
| 1744 | * we only have 10 bytes for SACK options (40 - (12 + 18)). |
| 1745 | */ |
| 1746 | int |
| 1747 | tcp_addoptions(struct tcpopt *to, u_char *optp) |
| 1748 | { |
| 1749 | u_int32_t mask, optlen = 0; |
| 1750 | |
| 1751 | for (mask = 1; mask < TOF_MAXOPT; mask <<= 1) { |
| 1752 | if ((to->to_flags & mask) != mask) |
| 1753 | continue; |
| 1754 | if (optlen == TCP_MAXOLEN) |
| 1755 | break; |
| 1756 | switch (to->to_flags & mask) { |
| 1757 | case TOF_MSS: |
| 1758 | while (optlen % 4) { |
| 1759 | optlen += TCPOLEN_NOP; |
| 1760 | *optp++ = TCPOPT_NOP; |
| 1761 | } |
| 1762 | if (TCP_MAXOLEN - optlen < TCPOLEN_MAXSEG) |
| 1763 | continue; |
| 1764 | optlen += TCPOLEN_MAXSEG; |
| 1765 | *optp++ = TCPOPT_MAXSEG; |
| 1766 | *optp++ = TCPOLEN_MAXSEG; |
| 1767 | to->to_mss = htons(to->to_mss); |
| 1768 | bcopy((u_char *)&to->to_mss, optp, sizeof(to->to_mss)); |
| 1769 | optp += sizeof(to->to_mss); |
| 1770 | break; |
| 1771 | case TOF_SCALE: |
| 1772 | while (!optlen || optlen % 2 != 1) { |
| 1773 | optlen += TCPOLEN_NOP; |
| 1774 | *optp++ = TCPOPT_NOP; |
| 1775 | } |
| 1776 | if (TCP_MAXOLEN - optlen < TCPOLEN_WINDOW) |
| 1777 | continue; |
| 1778 | optlen += TCPOLEN_WINDOW; |
| 1779 | *optp++ = TCPOPT_WINDOW; |
| 1780 | *optp++ = TCPOLEN_WINDOW; |
| 1781 | *optp++ = to->to_wscale; |
| 1782 | break; |
| 1783 | case TOF_SACKPERM: |
| 1784 | while (optlen % 2) { |
| 1785 | optlen += TCPOLEN_NOP; |
| 1786 | *optp++ = TCPOPT_NOP; |
| 1787 | } |
| 1788 | if (TCP_MAXOLEN - optlen < TCPOLEN_SACK_PERMITTED) |
| 1789 | continue; |
| 1790 | optlen += TCPOLEN_SACK_PERMITTED; |
| 1791 | *optp++ = TCPOPT_SACK_PERMITTED; |
| 1792 | *optp++ = TCPOLEN_SACK_PERMITTED; |
| 1793 | break; |
| 1794 | case TOF_TS: |
| 1795 | while (!optlen || optlen % 4 != 2) { |
| 1796 | optlen += TCPOLEN_NOP; |
| 1797 | *optp++ = TCPOPT_NOP; |
| 1798 | } |
| 1799 | if (TCP_MAXOLEN - optlen < TCPOLEN_TIMESTAMP) |
| 1800 | continue; |
| 1801 | optlen += TCPOLEN_TIMESTAMP; |
| 1802 | *optp++ = TCPOPT_TIMESTAMP; |
| 1803 | *optp++ = TCPOLEN_TIMESTAMP; |
no test coverage detected