| 1924 | } |
| 1925 | |
| 1926 | static int |
| 1927 | pf_normalize_tcpopt(struct pf_krule *r, struct mbuf *m, struct tcphdr *th, |
| 1928 | int off, sa_family_t af) |
| 1929 | { |
| 1930 | u_int16_t *mss; |
| 1931 | int thoff; |
| 1932 | int opt, cnt, optlen = 0; |
| 1933 | int rewrite = 0; |
| 1934 | u_char opts[TCP_MAXOLEN]; |
| 1935 | u_char *optp = opts; |
| 1936 | size_t startoff; |
| 1937 | |
| 1938 | thoff = th->th_off << 2; |
| 1939 | cnt = thoff - sizeof(struct tcphdr); |
| 1940 | |
| 1941 | if (cnt > 0 && !pf_pull_hdr(m, off + sizeof(*th), opts, cnt, |
| 1942 | NULL, NULL, af)) |
| 1943 | return (rewrite); |
| 1944 | |
| 1945 | for (; cnt > 0; cnt -= optlen, optp += optlen) { |
| 1946 | startoff = optp - opts; |
| 1947 | opt = optp[0]; |
| 1948 | if (opt == TCPOPT_EOL) |
| 1949 | break; |
| 1950 | if (opt == TCPOPT_NOP) |
| 1951 | optlen = 1; |
| 1952 | else { |
| 1953 | if (cnt < 2) |
| 1954 | break; |
| 1955 | optlen = optp[1]; |
| 1956 | if (optlen < 2 || optlen > cnt) |
| 1957 | break; |
| 1958 | } |
| 1959 | switch (opt) { |
| 1960 | case TCPOPT_MAXSEG: |
| 1961 | mss = (u_int16_t *)(optp + 2); |
| 1962 | if ((ntohs(*mss)) > r->max_mss) { |
| 1963 | pf_patch_16_unaligned(m, |
| 1964 | &th->th_sum, |
| 1965 | mss, htons(r->max_mss), |
| 1966 | PF_ALGNMNT(startoff), |
| 1967 | 0); |
| 1968 | rewrite = 1; |
| 1969 | } |
| 1970 | break; |
| 1971 | default: |
| 1972 | break; |
| 1973 | } |
| 1974 | } |
| 1975 | |
| 1976 | if (rewrite) |
| 1977 | m_copyback(m, off + sizeof(*th), thoff - sizeof(*th), opts); |
| 1978 | |
| 1979 | return (rewrite); |
| 1980 | } |
| 1981 | |
| 1982 | #ifdef INET |
| 1983 | static void |
no test coverage detected