This patch adds the missing bits to create expectations that are created in NAT setups.
Unified · Split
| @@ -174,10 +174,19 @@ enum ctattr_expect { · 173 unmodified lines | ||
| 174 | 174 | CTA_EXPECT_ZONE, |
| 175 | 175 | CTA_EXPECT_FLAGS, |
| 176 | 176 | CTA_EXPECT_CLASS, |
| 177 | + CTA_EXPECT_NAT, | |
| 177 | 178 | __CTA_EXPECT_MAX |
| 178 | 179 | }; |
| 179 | 180 | #define CTA_EXPECT_MAX (__CTA_EXPECT_MAX - 1) |
| 180 | 181 | |
| 182 | +enum ctattr_expect_nat { | |
| 183 | + CTA_EXPECT_NAT_UNSPEC, | |
| 184 | + CTA_EXPECT_NAT_DIR, | |
| 185 | + CTA_EXPECT_NAT_TUPLE, | |
| 186 | + __CTA_EXPECT_NAT_MAX | |
| 187 | +}; | |
| 188 | +#define CTA_EXPECT_NAT_MAX (__CTA_EXPECT_NAT_MAX - 1) | |
| 189 | + | |
| 181 | 190 | enum ctattr_help { |
| 182 | 191 | CTA_HELP_UNSPEC, |
| 183 | 192 | CTA_HELP_NAME, |
| @@ -1675,7 +1675,10 @@ ctnetlink_exp_dump_expect(struct sk_buff *skb, · 1674 unmodified lines | ||
| 1675 | 1675 | struct nf_conn *master = exp->master; |
| 1676 | 1676 | long timeout = ((long)exp->timeout.expires - (long)jiffies) / HZ; |
| 1677 | 1677 | struct nf_conn_help *help; |
| 1678 | − | |
| 1678 | +#ifdef CONFIG_NF_NAT_NEEDED | |
| 1679 | + struct nlattr *nest_parms; | |
| 1680 | + struct nf_conntrack_tuple nat_tuple = {}; | |
| 1681 | +#endif | |
| 1679 | 1682 | if (timeout < 0) |
| 1680 | 1683 | timeout = 0; |
| 1681 | 1684 | |
| @@ -1688,6 +1691,25 @@ ctnetlink_exp_dump_expect(struct sk_buff *skb, · 6 unmodified lines | ||
| 1688 | 1691 | CTA_EXPECT_MASTER) < 0) |
| 1689 | 1692 | goto nla_put_failure; |
| 1690 | 1693 | |
| 1694 | +#ifdef CONFIG_NF_NAT_NEEDED | |
| 1695 | + if (exp->saved_ip || exp->saved_proto.all) { | |
| 1696 | + nest_parms = nla_nest_start(skb, CTA_EXPECT_NAT | NLA_F_NESTED); | |
| 1697 | + if (!nest_parms) | |
| 1698 | + goto nla_put_failure; | |
| 1699 | + | |
| 1700 | + NLA_PUT_BE32(skb, CTA_EXPECT_NAT_DIR, htonl(exp->dir)); | |
| 1701 | + | |
| 1702 | + nat_tuple.src.l3num = nf_ct_l3num(master); | |
| 1703 | + nat_tuple.src.u3.ip = exp->saved_ip; | |
| 1704 | + nat_tuple.dst.protonum = nf_ct_protonum(master); | |
| 1705 | + nat_tuple.src.u = exp->saved_proto; | |
| 1706 | + | |
| 1707 | + if (ctnetlink_exp_dump_tuple(skb, &nat_tuple, | |
| 1708 | + CTA_EXPECT_NAT_TUPLE) < 0) | |
| 1709 | + goto nla_put_failure; | |
| 1710 | + nla_nest_end(skb, nest_parms); | |
| 1711 | + } | |
| 1712 | +#endif | |
| 1691 | 1713 | NLA_PUT_BE32(skb, CTA_EXPECT_TIMEOUT, htonl(timeout)); |
| 1692 | 1714 | NLA_PUT_BE32(skb, CTA_EXPECT_ID, htonl((unsigned long)exp)); |
| 1693 | 1715 | NLA_PUT_BE32(skb, CTA_EXPECT_FLAGS, htonl(exp->flags)); |
| @@ -1858,6 +1880,7 @@ static const struct nla_policy exp_nla_policy[CTA_EXPECT_MAX+1] = { · 164 unmodified lines | ||
| 1858 | 1880 | [CTA_EXPECT_ZONE] = { .type = NLA_U16 }, |
| 1859 | 1881 | [CTA_EXPECT_FLAGS] = { .type = NLA_U32 }, |
| 1860 | 1882 | [CTA_EXPECT_CLASS] = { .type = NLA_U32 }, |
| 1883 | + [CTA_EXPECT_NAT] = { .type = NLA_NESTED }, | |
| 1861 | 1884 | }; |
| 1862 | 1885 | |
| 1863 | 1886 | static int |
| @@ -2033,6 +2056,41 @@ ctnetlink_change_expect(struct nf_conntrack_expect *x, · 169 unmodified lines | ||
| 2033 | 2056 | return -EOPNOTSUPP; |
| 2034 | 2057 | } |
| 2035 | 2058 | |
| 2059 | +static const struct nla_policy exp_nat_nla_policy[CTA_EXPECT_NAT_MAX+1] = { | |
| 2060 | + [CTA_EXPECT_NAT_DIR] = { .type = NLA_U32 }, | |
| 2061 | + [CTA_EXPECT_NAT_TUPLE] = { .type = NLA_NESTED }, | |
| 2062 | +}; | |
| 2063 | + | |
| 2064 | +static int | |
| 2065 | +ctnetlink_parse_expect_nat(const struct nlattr *attr, | |
| 2066 | + struct nf_conntrack_expect *exp, | |
| 2067 | + u_int8_t u3) | |
| 2068 | +{ | |
| 2069 | +#ifdef CONFIG_NF_NAT_NEEDED | |
| 2070 | + struct nlattr *tb[CTA_EXPECT_NAT_MAX+1]; | |
| 2071 | + struct nf_conntrack_tuple nat_tuple = {}; | |
| 2072 | + int err; | |
| 2073 | + | |
| 2074 | + nla_parse_nested(tb, CTA_EXPECT_NAT_MAX, attr, exp_nat_nla_policy); | |
| 2075 | + | |
| 2076 | + if (!tb[CTA_EXPECT_NAT_DIR] || !tb[CTA_EXPECT_NAT_TUPLE]) | |
| 2077 | + return -EINVAL; | |
| 2078 | + | |
| 2079 | + err = ctnetlink_parse_tuple((const struct nlattr * const *)tb, | |
| 2080 | + &nat_tuple, CTA_EXPECT_NAT_TUPLE, u3); | |
| 2081 | + if (err < 0) | |
| 2082 | + return err; | |
| 2083 | + | |
| 2084 | + exp->saved_ip = nat_tuple.src.u3.ip; | |
| 2085 | + exp->saved_proto = nat_tuple.src.u; | |
| 2086 | + exp->dir = ntohl(nla_get_be32(tb[CTA_EXPECT_NAT_DIR])); | |
| 2087 | + | |
| 2088 | + return 0; | |
| 2089 | +#else | |
| 2090 | + return -EOPNOTSUPP; | |
| 2091 | +#endif | |
| 2092 | +} | |
| 2093 | + | |
| 2036 | 2094 | static int |
| 2037 | 2095 | ctnetlink_create_expect(struct net *net, u16 zone, |
| 2038 | 2096 | const struct nlattr * const cda[], |
| @@ -2133,9 +2191,15 @@ ctnetlink_create_expect(struct net *net, u16 zone, · 94 unmodified lines | ||
| 2133 | 2191 | memcpy(&exp->mask.src.u3, &mask.src.u3, sizeof(exp->mask.src.u3)); |
| 2134 | 2192 | exp->mask.src.u.all = mask.src.u.all; |
| 2135 | 2193 | |
| 2194 | + if (cda[CTA_EXPECT_NAT]) { | |
| 2195 | + err = ctnetlink_parse_expect_nat(cda[CTA_EXPECT_NAT], | |
| 2196 | + exp, u3); | |
| 2197 | + if (err < 0) | |
| 2198 | + goto err_out; | |
| 2199 | + } | |
| 2136 | 2200 | err = nf_ct_expect_related_report(exp, pid, report); |
| 2201 | +err_out: | |
| 2137 | 2202 | nf_ct_expect_put(exp); |
| 2138 | − | |
| 2139 | 2203 | out: |
| 2140 | 2204 | nf_ct_put(nf_ct_tuplehash_to_ctrack(h)); |
| 2141 | 2205 | return err; |