Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

netfilter: ctnetlink: add NAT support for expectations

This patch adds the missing bits to create expectations that
are created in NAT setups.

+75 -2
+66 -2
net/netfilter/nf_conntrack_netlink.c
··· 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 ··· 1691 1688 CTA_EXPECT_MASTER) < 0) 1692 1689 goto nla_put_failure; 1693 1690 1691 + #ifdef CONFIG_NF_NAT_NEEDED 1692 + if (exp->saved_ip || exp->saved_proto.all) { 1693 + nest_parms = nla_nest_start(skb, CTA_EXPECT_NAT | NLA_F_NESTED); 1694 + if (!nest_parms) 1695 + goto nla_put_failure; 1696 + 1697 + NLA_PUT_BE32(skb, CTA_EXPECT_NAT_DIR, htonl(exp->dir)); 1698 + 1699 + nat_tuple.src.l3num = nf_ct_l3num(master); 1700 + nat_tuple.src.u3.ip = exp->saved_ip; 1701 + nat_tuple.dst.protonum = nf_ct_protonum(master); 1702 + nat_tuple.src.u = exp->saved_proto; 1703 + 1704 + if (ctnetlink_exp_dump_tuple(skb, &nat_tuple, 1705 + CTA_EXPECT_NAT_TUPLE) < 0) 1706 + goto nla_put_failure; 1707 + nla_nest_end(skb, nest_parms); 1708 + } 1709 + #endif 1694 1710 NLA_PUT_BE32(skb, CTA_EXPECT_TIMEOUT, htonl(timeout)); 1695 1711 NLA_PUT_BE32(skb, CTA_EXPECT_ID, htonl((unsigned long)exp)); 1696 1712 NLA_PUT_BE32(skb, CTA_EXPECT_FLAGS, htonl(exp->flags)); ··· 1880 1858 [CTA_EXPECT_ZONE] = { .type = NLA_U16 }, 1881 1859 [CTA_EXPECT_FLAGS] = { .type = NLA_U32 }, 1882 1860 [CTA_EXPECT_CLASS] = { .type = NLA_U32 }, 1861 + [CTA_EXPECT_NAT] = { .type = NLA_NESTED }, 1883 1862 }; 1884 1863 1885 1864 static int ··· 2056 2033 return -EOPNOTSUPP; 2057 2034 } 2058 2035 2036 + static const struct nla_policy exp_nat_nla_policy[CTA_EXPECT_NAT_MAX+1] = { 2037 + [CTA_EXPECT_NAT_DIR] = { .type = NLA_U32 }, 2038 + [CTA_EXPECT_NAT_TUPLE] = { .type = NLA_NESTED }, 2039 + }; 2040 + 2041 + static int 2042 + ctnetlink_parse_expect_nat(const struct nlattr *attr, 2043 + struct nf_conntrack_expect *exp, 2044 + u_int8_t u3) 2045 + { 2046 + #ifdef CONFIG_NF_NAT_NEEDED 2047 + struct nlattr *tb[CTA_EXPECT_NAT_MAX+1]; 2048 + struct nf_conntrack_tuple nat_tuple = {}; 2049 + int err; 2050 + 2051 + nla_parse_nested(tb, CTA_EXPECT_NAT_MAX, attr, exp_nat_nla_policy); 2052 + 2053 + if (!tb[CTA_EXPECT_NAT_DIR] || !tb[CTA_EXPECT_NAT_TUPLE]) 2054 + return -EINVAL; 2055 + 2056 + err = ctnetlink_parse_tuple((const struct nlattr * const *)tb, 2057 + &nat_tuple, CTA_EXPECT_NAT_TUPLE, u3); 2058 + if (err < 0) 2059 + return err; 2060 + 2061 + exp->saved_ip = nat_tuple.src.u3.ip; 2062 + exp->saved_proto = nat_tuple.src.u; 2063 + exp->dir = ntohl(nla_get_be32(tb[CTA_EXPECT_NAT_DIR])); 2064 + 2065 + return 0; 2066 + #else 2067 + return -EOPNOTSUPP; 2068 + #endif 2069 + } 2070 + 2059 2071 static int 2060 2072 ctnetlink_create_expect(struct net *net, u16 zone, 2061 2073 const struct nlattr * const cda[], ··· 2191 2133 memcpy(&exp->mask.src.u3, &mask.src.u3, sizeof(exp->mask.src.u3)); 2192 2134 exp->mask.src.u.all = mask.src.u.all; 2193 2135 2136 + if (cda[CTA_EXPECT_NAT]) { 2137 + err = ctnetlink_parse_expect_nat(cda[CTA_EXPECT_NAT], 2138 + exp, u3); 2139 + if (err < 0) 2140 + goto err_out; 2141 + } 2194 2142 err = nf_ct_expect_related_report(exp, pid, report); 2143 + err_out: 2195 2144 nf_ct_expect_put(exp); 2196 - 2197 2145 out: 2198 2146 nf_ct_put(nf_ct_tuplehash_to_ctrack(h)); 2199 2147 return err;