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 | CTA_EXPECT_ZONE, | 174 | CTA_EXPECT_ZONE, |
| 175 | CTA_EXPECT_FLAGS, | 175 | CTA_EXPECT_FLAGS, |
| 176 | CTA_EXPECT_CLASS, | 176 | CTA_EXPECT_CLASS, |
| 177 | CTA_EXPECT_NAT, | ||
| 177 | __CTA_EXPECT_MAX | 178 | __CTA_EXPECT_MAX |
| 178 | }; | 179 | }; |
| 179 | #define CTA_EXPECT_MAX (__CTA_EXPECT_MAX - 1) | 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 | enum ctattr_help { | 190 | enum ctattr_help { |
| 182 | CTA_HELP_UNSPEC, | 191 | CTA_HELP_UNSPEC, |
| 183 | CTA_HELP_NAME, | 192 | CTA_HELP_NAME, |
| @@ -1675,7 +1675,10 @@ ctnetlink_exp_dump_expect(struct sk_buff *skb, · 1674 unmodified lines | |||
| 1675 | struct nf_conn *master = exp->master; | 1675 | struct nf_conn *master = exp->master; |
| 1676 | long timeout = ((long)exp->timeout.expires - (long)jiffies) / HZ; | 1676 | long timeout = ((long)exp->timeout.expires - (long)jiffies) / HZ; |
| 1677 | struct nf_conn_help *help; | 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 | if (timeout < 0) | 1682 | if (timeout < 0) |
| 1680 | timeout = 0; | 1683 | timeout = 0; |
| 1681 | 1684 | ||
| @@ -1688,6 +1691,25 @@ ctnetlink_exp_dump_expect(struct sk_buff *skb, · 6 unmodified lines | |||
| 1688 | CTA_EXPECT_MASTER) < 0) | 1691 | CTA_EXPECT_MASTER) < 0) |
| 1689 | goto nla_put_failure; | 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 | NLA_PUT_BE32(skb, CTA_EXPECT_TIMEOUT, htonl(timeout)); | 1713 | NLA_PUT_BE32(skb, CTA_EXPECT_TIMEOUT, htonl(timeout)); |
| 1692 | NLA_PUT_BE32(skb, CTA_EXPECT_ID, htonl((unsigned long)exp)); | 1714 | NLA_PUT_BE32(skb, CTA_EXPECT_ID, htonl((unsigned long)exp)); |
| 1693 | NLA_PUT_BE32(skb, CTA_EXPECT_FLAGS, htonl(exp->flags)); | 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 | [CTA_EXPECT_ZONE] = { .type = NLA_U16 }, | 1880 | [CTA_EXPECT_ZONE] = { .type = NLA_U16 }, |
| 1859 | [CTA_EXPECT_FLAGS] = { .type = NLA_U32 }, | 1881 | [CTA_EXPECT_FLAGS] = { .type = NLA_U32 }, |
| 1860 | [CTA_EXPECT_CLASS] = { .type = NLA_U32 }, | 1882 | [CTA_EXPECT_CLASS] = { .type = NLA_U32 }, |
| 1883 | [CTA_EXPECT_NAT] = { .type = NLA_NESTED }, | ||
| 1861 | }; | 1884 | }; |
| 1862 | 1885 | ||
| 1863 | static int | 1886 | static int |
| @@ -2033,6 +2056,41 @@ ctnetlink_change_expect(struct nf_conntrack_expect *x, · 169 unmodified lines | |||
| 2033 | return -EOPNOTSUPP; | 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 | static int | 2094 | static int |
| 2037 | ctnetlink_create_expect(struct net *net, u16 zone, | 2095 | ctnetlink_create_expect(struct net *net, u16 zone, |
| 2038 | const struct nlattr * const cda[], | 2096 | const struct nlattr * const cda[], |
| @@ -2133,9 +2191,15 @@ ctnetlink_create_expect(struct net *net, u16 zone, · 94 unmodified lines | |||
| 2133 | memcpy(&exp->mask.src.u3, &mask.src.u3, sizeof(exp->mask.src.u3)); | 2191 | memcpy(&exp->mask.src.u3, &mask.src.u3, sizeof(exp->mask.src.u3)); |
| 2134 | exp->mask.src.u.all = mask.src.u.all; | 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 | err = nf_ct_expect_related_report(exp, pid, report); | 2200 | err = nf_ct_expect_related_report(exp, pid, report); |
| 2201 | err_out: | ||
| 2137 | nf_ct_expect_put(exp); | 2202 | nf_ct_expect_put(exp); |
| 2138 | |||
| 2139 | out: | 2203 | out: |
| 2140 | nf_ct_put(nf_ct_tuplehash_to_ctrack(h)); | 2204 | nf_ct_put(nf_ct_tuplehash_to_ctrack(h)); |
| 2141 | return err; | 2205 | return err; |