Merge branch 'em_ipt-add-support-for-addrtype'
Nikolay Aleksandrov says: ==================== em_ipt: add support for addrtype We would like to be able to use the addrtype from tc for ACL rules and em_ipt seems the best place to add support for the already existing xt match. The biggest issue is that addrtype revision 1 (with ipv6 support) is NFPROTO_UNSPEC and currently em_ipt can't differentiate between v4/v6 if such xt match is used because it passes the match's family instead of the packet one. The first 3 patches make em_ipt match only on IP traffic (currently both policy and addrtype recognize such traffic only) and make it pass the actual packet's protocol instead of the xt match family when it's unspecified. They also add support for NFPROTO_UNSPEC xt matches. The last patch allows to add addrtype rules via em_ipt. We need to keep the user-specified nfproto for dumping in order to be compatible with libxtables, we cannot dump NFPROTO_UNSPEC as the nfproto or we'll get an error from libxtables, thus the nfproto is limited to ipv4/ipv6 in patch 03 and is recorded. v3: don't use the user nfproto for matching, only for dumping, more information is available in the commit message in patch 03 v2: change patch 02 to set the nfproto only when unspecified and drop patch 04 from v1 (Eyal Birger) ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
fc41388564
@ -21,6 +21,7 @@
|
||||
struct em_ipt_match {
|
||||
const struct xt_match *match;
|
||||
u32 hook;
|
||||
u8 nfproto;
|
||||
u8 match_data[0] __aligned(8);
|
||||
};
|
||||
|
||||
@ -71,11 +72,25 @@ static int policy_validate_match_data(struct nlattr **tb, u8 mrev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int addrtype_validate_match_data(struct nlattr **tb, u8 mrev)
|
||||
{
|
||||
if (mrev != 1) {
|
||||
pr_err("only addrtype match revision 1 supported");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct em_ipt_xt_match em_ipt_xt_matches[] = {
|
||||
{
|
||||
.match_name = "policy",
|
||||
.validate_match_data = policy_validate_match_data
|
||||
},
|
||||
{
|
||||
.match_name = "addrtype",
|
||||
.validate_match_data = addrtype_validate_match_data
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
@ -115,6 +130,7 @@ static int em_ipt_change(struct net *net, void *data, int data_len,
|
||||
struct em_ipt_match *im = NULL;
|
||||
struct xt_match *match;
|
||||
int mdata_len, ret;
|
||||
u8 nfproto;
|
||||
|
||||
ret = nla_parse_deprecated(tb, TCA_EM_IPT_MAX, data, data_len,
|
||||
em_ipt_policy, NULL);
|
||||
@ -125,6 +141,15 @@ static int em_ipt_change(struct net *net, void *data, int data_len,
|
||||
!tb[TCA_EM_IPT_MATCH_DATA] || !tb[TCA_EM_IPT_NFPROTO])
|
||||
return -EINVAL;
|
||||
|
||||
nfproto = nla_get_u8(tb[TCA_EM_IPT_NFPROTO]);
|
||||
switch (nfproto) {
|
||||
case NFPROTO_IPV4:
|
||||
case NFPROTO_IPV6:
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
match = get_xt_match(tb);
|
||||
if (IS_ERR(match)) {
|
||||
pr_err("unable to load match\n");
|
||||
@ -140,6 +165,7 @@ static int em_ipt_change(struct net *net, void *data, int data_len,
|
||||
|
||||
im->match = match;
|
||||
im->hook = nla_get_u32(tb[TCA_EM_IPT_HOOK]);
|
||||
im->nfproto = nfproto;
|
||||
nla_memcpy(im->match_data, tb[TCA_EM_IPT_MATCH_DATA], mdata_len);
|
||||
|
||||
ret = check_match(net, im, mdata_len);
|
||||
@ -182,15 +208,33 @@ static int em_ipt_match(struct sk_buff *skb, struct tcf_ematch *em,
|
||||
const struct em_ipt_match *im = (const void *)em->data;
|
||||
struct xt_action_param acpar = {};
|
||||
struct net_device *indev = NULL;
|
||||
u8 nfproto = im->match->family;
|
||||
struct nf_hook_state state;
|
||||
int ret;
|
||||
|
||||
switch (tc_skb_protocol(skb)) {
|
||||
case htons(ETH_P_IP):
|
||||
if (!pskb_network_may_pull(skb, sizeof(struct iphdr)))
|
||||
return 0;
|
||||
if (nfproto == NFPROTO_UNSPEC)
|
||||
nfproto = NFPROTO_IPV4;
|
||||
break;
|
||||
case htons(ETH_P_IPV6):
|
||||
if (!pskb_network_may_pull(skb, sizeof(struct ipv6hdr)))
|
||||
return 0;
|
||||
if (nfproto == NFPROTO_UNSPEC)
|
||||
nfproto = NFPROTO_IPV6;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
if (skb->skb_iif)
|
||||
indev = dev_get_by_index_rcu(em->net, skb->skb_iif);
|
||||
|
||||
nf_hook_state_init(&state, im->hook, im->match->family,
|
||||
nf_hook_state_init(&state, im->hook, nfproto,
|
||||
indev ?: skb->dev, skb->dev, NULL, em->net, NULL);
|
||||
|
||||
acpar.match = im->match;
|
||||
@ -213,7 +257,7 @@ static int em_ipt_dump(struct sk_buff *skb, struct tcf_ematch *em)
|
||||
return -EMSGSIZE;
|
||||
if (nla_put_u8(skb, TCA_EM_IPT_MATCH_REVISION, im->match->revision) < 0)
|
||||
return -EMSGSIZE;
|
||||
if (nla_put_u8(skb, TCA_EM_IPT_NFPROTO, im->match->family) < 0)
|
||||
if (nla_put_u8(skb, TCA_EM_IPT_NFPROTO, im->nfproto) < 0)
|
||||
return -EMSGSIZE;
|
||||
if (nla_put(skb, TCA_EM_IPT_MATCH_DATA,
|
||||
im->match->usersize ?: im->match->matchsize,
|
||||
|
Loading…
Reference in New Issue
Block a user