Skip to content

Commit 2c2083a

Browse files
roopa-prabhuDhineshCool
authored andcommitted
net: fib_rules: support for match on ip_proto, sport and dport
uapi for ip_proto, sport and dport range match in fib rules. Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com> Acked-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent cc8f191 commit 2c2083a

3 files changed

Lines changed: 103 additions & 2 deletions

File tree

include/net/fib_rules.h

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ struct fib_rule {
2323
u32 table;
2424
u8 action;
2525
u8 l3mdev;
26-
/* 2 bytes hole, try to use */
26+
u8 ip_proto;
2727
u32 target;
2828
__be64 tun_id;
2929
struct fib_rule __rcu *ctarget;
@@ -36,6 +36,8 @@ struct fib_rule {
3636
char iifname[IFNAMSIZ];
3737
char oifname[IFNAMSIZ];
3838
struct fib_kuid_range uid_range;
39+
struct fib_rule_port_range sport_range;
40+
struct fib_rule_port_range dport_range;
3941
struct rcu_head rcu;
4042
};
4143

@@ -134,6 +136,38 @@ static inline u32 frh_get_table(struct fib_rule_hdr *frh, struct nlattr **nla)
134136
return frh->table;
135137
}
136138

139+
static inline bool fib_rule_port_range_set(const struct fib_rule_port_range *range)
140+
{
141+
return range->start != 0 && range->end != 0;
142+
}
143+
144+
static inline bool fib_rule_port_inrange(const struct fib_rule_port_range *a,
145+
__be16 port)
146+
{
147+
return ntohs(port) >= a->start &&
148+
ntohs(port) <= a->end;
149+
}
150+
151+
static inline bool fib_rule_port_range_valid(const struct fib_rule_port_range *a)
152+
{
153+
return a->start != 0 && a->end != 0 && a->end < 0xffff &&
154+
a->start <= a->end;
155+
}
156+
157+
static inline bool fib_rule_port_range_compare(struct fib_rule_port_range *a,
158+
struct fib_rule_port_range *b)
159+
{
160+
return a->start == b->start &&
161+
a->end == b->end;
162+
}
163+
164+
static inline bool fib_rule_requires_fldissect(struct fib_rule *rule)
165+
{
166+
return rule->ip_proto ||
167+
fib_rule_port_range_set(&rule->sport_range) ||
168+
fib_rule_port_range_set(&rule->dport_range);
169+
}
170+
137171
struct fib_rules_ops *fib_rules_register(const struct fib_rules_ops *,
138172
struct net *);
139173
void fib_rules_unregister(struct fib_rules_ops *);

include/uapi/linux/fib_rules.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ struct fib_rule_uid_range {
3434
__u32 end;
3535
};
3636

37+
struct fib_rule_port_range {
38+
__u16 start;
39+
__u16 end;
40+
};
41+
3742
enum {
3843
FRA_UNSPEC,
3944
FRA_DST, /* destination address */
@@ -57,6 +62,9 @@ enum {
5762
FRA_PAD,
5863
FRA_L3MDEV, /* iif or oif is l3mdev goto its table */
5964
FRA_UID_RANGE, /* UID range */
65+
FRA_IP_PROTO, /* ip proto */
66+
FRA_SPORT_RANGE, /* sport */
67+
FRA_DPORT_RANGE, /* dport */
6068
__FRA_MAX
6169
};
6270

net/core/fib_rules.c

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,26 @@ static int nla_put_uid_range(struct sk_buff *skb, struct fib_kuid_range *range)
206206
return nla_put(skb, FRA_UID_RANGE, sizeof(out), &out);
207207
}
208208

209+
static int nla_get_port_range(struct nlattr *pattr,
210+
struct fib_rule_port_range *port_range)
211+
{
212+
const struct fib_rule_port_range *pr = nla_data(pattr);
213+
214+
if (!fib_rule_port_range_valid(pr))
215+
return -EINVAL;
216+
217+
port_range->start = pr->start;
218+
port_range->end = pr->end;
219+
220+
return 0;
221+
}
222+
223+
static int nla_put_port_range(struct sk_buff *skb, int attrtype,
224+
struct fib_rule_port_range *range)
225+
{
226+
return nla_put(skb, attrtype, sizeof(*range), range);
227+
}
228+
209229
static int fib_rule_match(struct fib_rule *rule, struct fib_rules_ops *ops,
210230
struct flowi *fl, int flags,
211231
struct fib_lookup_arg *arg)
@@ -551,6 +571,8 @@ int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr *nlh)
551571
{
552572
struct net *net = sock_net(skb->sk);
553573
struct fib_rule_hdr *frh = nlmsg_data(nlh);
574+
struct fib_rule_port_range sprange = {0, 0};
575+
struct fib_rule_port_range dprange = {0, 0};
554576
struct fib_rules_ops *ops = NULL;
555577
struct fib_rule *rule, *tmp;
556578
struct nlattr *tb[FRA_MAX+1];
@@ -584,6 +606,20 @@ int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr *nlh)
584606
range = fib_kuid_range_unset;
585607
}
586608

609+
if (tb[FRA_SPORT_RANGE]) {
610+
err = nla_get_port_range(tb[FRA_SPORT_RANGE],
611+
&sprange);
612+
if (err)
613+
goto errout;
614+
}
615+
616+
if (tb[FRA_DPORT_RANGE]) {
617+
err = nla_get_port_range(tb[FRA_DPORT_RANGE],
618+
&dprange);
619+
if (err)
620+
goto errout;
621+
}
622+
587623
list_for_each_entry(rule, &ops->rules_list, list) {
588624
if (frh->action && (frh->action != rule->action))
589625
continue;
@@ -625,6 +661,18 @@ int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr *nlh)
625661
!uid_eq(rule->uid_range.end, range.end)))
626662
continue;
627663

664+
if (tb[FRA_IP_PROTO] &&
665+
(rule->ip_proto != nla_get_u8(tb[FRA_IP_PROTO])))
666+
continue;
667+
668+
if (fib_rule_port_range_set(&sprange) &&
669+
!fib_rule_port_range_compare(&rule->sport_range, &sprange))
670+
continue;
671+
672+
if (fib_rule_port_range_set(&dprange) &&
673+
!fib_rule_port_range_compare(&rule->dport_range, &dprange))
674+
continue;
675+
628676
if (!ops->compare(rule, frh, tb))
629677
continue;
630678

@@ -694,6 +742,12 @@ static inline size_t fib_rule_nlmsg_size(struct fib_rules_ops *ops,
694742
+ nla_total_size(4) /* FRA_FWMASK */
695743
+ nla_total_size_64bit(8) /* FRA_TUN_ID */
696744
+ nla_total_size(sizeof(struct fib_kuid_range));
745+
+ nla_total_size(8); /* FRA_TUN_ID */
746+
+ nla_total_size(sizeof(struct fib_kuid_range))
747+
+ nla_total_size(1) /* FRA_PROTOCOL */
748+
+ nla_total_size(1) /* FRA_IP_PROTO */
749+
+ nla_total_size(sizeof(struct fib_rule_port_range)) /* FRA_SPORT_RANGE */
750+
+ nla_total_size(sizeof(struct fib_rule_port_range)); /* FRA_DPORT_RANGE */
697751

698752
if (ops->nlmsg_payload)
699753
payload += ops->nlmsg_payload(rule);
@@ -755,7 +809,12 @@ static int fib_nl_fill_rule(struct sk_buff *skb, struct fib_rule *rule,
755809
(rule->l3mdev &&
756810
nla_put_u8(skb, FRA_L3MDEV, rule->l3mdev)) ||
757811
(uid_range_set(&rule->uid_range) &&
758-
nla_put_uid_range(skb, &rule->uid_range)))
812+
nla_put_uid_range(skb, &rule->uid_range)) ||
813+
(fib_rule_port_range_set(&rule->sport_range) &&
814+
nla_put_port_range(skb, FRA_SPORT_RANGE, &rule->sport_range)) ||
815+
(fib_rule_port_range_set(&rule->dport_range) &&
816+
nla_put_port_range(skb, FRA_DPORT_RANGE, &rule->dport_range)) ||
817+
(rule->ip_proto && nla_put_u8(skb, FRA_IP_PROTO, rule->ip_proto)))
759818
goto nla_put_failure;
760819

761820
if (rule->suppress_ifgroup != -1) {

0 commit comments

Comments
 (0)