mirror of
https://gitee.com/openharmony/third_party_libnl
synced 2024-11-27 20:20:30 +00:00
rule: Add support for protocol and port ranges
Add support for recent fib rule features - specifying a protocol that installed a rule and an IP protocol plus port range for rules. Signed-off-by: David Ahern <dsa@cumulusnetworks.com>
This commit is contained in:
parent
fc4880fa5b
commit
961c4f6750
@ -31,6 +31,7 @@
|
||||
#include <linux/tc_act/tc_skbedit.h>
|
||||
#include <linux/tc_act/tc_gact.h>
|
||||
#include <linux/sock_diag.h>
|
||||
#include <linux/fib_rules.h>
|
||||
|
||||
#define NL_SOCK_PASSCRED (1<<1)
|
||||
#define NL_OWN_PORT (1<<2)
|
||||
@ -358,6 +359,8 @@ struct rtnl_rule
|
||||
uint8_t r_action;
|
||||
uint8_t r_dsfield; /* ipv4 only */
|
||||
uint8_t r_l3mdev;
|
||||
uint8_t r_protocol; /* protocol that installed rule */
|
||||
uint8_t r_ip_proto; /* IP/IPv6 protocol */
|
||||
uint32_t r_table;
|
||||
uint32_t r_flags;
|
||||
uint32_t r_prio;
|
||||
@ -369,6 +372,9 @@ struct rtnl_rule
|
||||
struct nl_addr *r_dst;
|
||||
char r_iifname[IFNAMSIZ];
|
||||
char r_oifname[IFNAMSIZ];
|
||||
|
||||
struct fib_rule_port_range r_sport;
|
||||
struct fib_rule_port_range r_dport;
|
||||
};
|
||||
|
||||
struct rtnl_neightbl_parms
|
||||
|
@ -69,6 +69,22 @@ extern void rtnl_rule_set_goto(struct rtnl_rule *, uint32_t);
|
||||
extern uint32_t rtnl_rule_get_goto(struct rtnl_rule *);
|
||||
extern void rtnl_rule_set_l3mdev(struct rtnl_rule *, int);
|
||||
extern int rtnl_rule_get_l3mdev(struct rtnl_rule *);
|
||||
extern int rtnl_rule_set_protocol(struct rtnl_rule *, uint8_t);
|
||||
extern int rtnl_rule_get_protocol(struct rtnl_rule *, uint8_t *);
|
||||
extern int rtnl_rule_set_ipproto(struct rtnl_rule *, uint8_t);
|
||||
extern int rtnl_rule_get_ipproto(struct rtnl_rule *, uint8_t *);
|
||||
extern int rtnl_rule_set_sport(struct rtnl_rule *, uint16_t start);
|
||||
extern int rtnl_rule_set_sport_range(struct rtnl_rule *,
|
||||
uint16_t start,
|
||||
uint16_t end);
|
||||
extern int rtnl_rule_get_sport(struct rtnl_rule *, uint16_t *start,
|
||||
uint16_t *end);
|
||||
extern int rtnl_rule_set_dport(struct rtnl_rule *, uint16_t start);
|
||||
extern int rtnl_rule_set_dport_range(struct rtnl_rule *,
|
||||
uint16_t start,
|
||||
uint16_t end);
|
||||
extern int rtnl_rule_get_dport(struct rtnl_rule *, uint16_t *start,
|
||||
uint16_t *end);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
213
lib/route/rule.c
213
lib/route/rule.c
@ -25,21 +25,25 @@
|
||||
#include <linux/fib_rules.h>
|
||||
|
||||
/** @cond SKIP */
|
||||
#define RULE_ATTR_FAMILY 0x0001
|
||||
#define RULE_ATTR_TABLE 0x0002
|
||||
#define RULE_ATTR_ACTION 0x0004
|
||||
#define RULE_ATTR_FLAGS 0x0008
|
||||
#define RULE_ATTR_IIFNAME 0x0010
|
||||
#define RULE_ATTR_OIFNAME 0x0020
|
||||
#define RULE_ATTR_PRIO 0x0040
|
||||
#define RULE_ATTR_MARK 0x0080
|
||||
#define RULE_ATTR_MASK 0x0100
|
||||
#define RULE_ATTR_GOTO 0x0200
|
||||
#define RULE_ATTR_SRC 0x0400
|
||||
#define RULE_ATTR_DST 0x0800
|
||||
#define RULE_ATTR_DSFIELD 0x1000
|
||||
#define RULE_ATTR_FLOW 0x2000
|
||||
#define RULE_ATTR_L3MDEV 0x4000
|
||||
#define RULE_ATTR_FAMILY 0x000001
|
||||
#define RULE_ATTR_TABLE 0x000002
|
||||
#define RULE_ATTR_ACTION 0x000004
|
||||
#define RULE_ATTR_FLAGS 0x000008
|
||||
#define RULE_ATTR_IIFNAME 0x000010
|
||||
#define RULE_ATTR_OIFNAME 0x000020
|
||||
#define RULE_ATTR_PRIO 0x000040
|
||||
#define RULE_ATTR_MARK 0x000080
|
||||
#define RULE_ATTR_MASK 0x000100
|
||||
#define RULE_ATTR_GOTO 0x000200
|
||||
#define RULE_ATTR_SRC 0x000400
|
||||
#define RULE_ATTR_DST 0x000800
|
||||
#define RULE_ATTR_DSFIELD 0x001000
|
||||
#define RULE_ATTR_FLOW 0x002000
|
||||
#define RULE_ATTR_L3MDEV 0x004000
|
||||
#define RULE_ATTR_PROTOCOL 0x008000
|
||||
#define RULE_ATTR_IP_PROTO 0x010000
|
||||
#define RULE_ATTR_SPORT 0x020000
|
||||
#define RULE_ATTR_DPORT 0x040000
|
||||
|
||||
static struct nl_cache_ops rtnl_rule_ops;
|
||||
static struct nl_object_ops rule_obj_ops;
|
||||
@ -82,6 +86,12 @@ static struct nla_policy rule_policy[FRA_MAX+1] = {
|
||||
[FRA_GOTO] = { .type = NLA_U32 },
|
||||
[FRA_FLOW] = { .type = NLA_U32 },
|
||||
[FRA_L3MDEV] = { .type = NLA_U8 },
|
||||
[FRA_PROTOCOL] = { .type = NLA_U8 },
|
||||
[FRA_IP_PROTO] = { .type = NLA_U8 },
|
||||
[FRA_SPORT_RANGE] = { .minlen = sizeof(struct fib_rule_port_range),
|
||||
.maxlen = sizeof(struct fib_rule_port_range) },
|
||||
[FRA_DPORT_RANGE] = { .minlen = sizeof(struct fib_rule_port_range),
|
||||
.maxlen = sizeof(struct fib_rule_port_range) },
|
||||
};
|
||||
|
||||
static int rule_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
|
||||
@ -182,6 +192,32 @@ static int rule_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
|
||||
rule->ce_mask |= RULE_ATTR_L3MDEV;
|
||||
}
|
||||
|
||||
if (tb[FRA_PROTOCOL]) {
|
||||
rule->r_protocol = nla_get_u8(tb[FRA_PROTOCOL]);
|
||||
rule->ce_mask |= RULE_ATTR_PROTOCOL;
|
||||
}
|
||||
|
||||
if (tb[FRA_IP_PROTO]) {
|
||||
rule->r_ip_proto = nla_get_u8(tb[FRA_IP_PROTO]);
|
||||
rule->ce_mask |= RULE_ATTR_IP_PROTO;
|
||||
}
|
||||
|
||||
if (tb[FRA_SPORT_RANGE]) {
|
||||
struct fib_rule_port_range *pr;
|
||||
|
||||
pr = nla_data(tb[FRA_SPORT_RANGE]);
|
||||
rule->r_sport = *pr;
|
||||
rule->ce_mask |= RULE_ATTR_SPORT;
|
||||
}
|
||||
|
||||
if (tb[FRA_DPORT_RANGE]) {
|
||||
struct fib_rule_port_range *pr;
|
||||
|
||||
pr = nla_data(tb[FRA_DPORT_RANGE]);
|
||||
rule->r_dport = *pr;
|
||||
rule->ce_mask |= RULE_ATTR_DPORT;
|
||||
}
|
||||
|
||||
err = pp->pp_cb((struct nl_object *) rule, pp);
|
||||
errout:
|
||||
rtnl_rule_put(rule);
|
||||
@ -232,6 +268,30 @@ static void rule_dump_line(struct nl_object *o, struct nl_dump_params *p)
|
||||
if (r->ce_mask & RULE_ATTR_L3MDEV)
|
||||
nl_dump(p, "lookup [l3mdev-table] ");
|
||||
|
||||
if (r->ce_mask & RULE_ATTR_IP_PROTO)
|
||||
nl_dump(p, "ipproto %s ",
|
||||
nl_ip_proto2str(r->r_ip_proto, buf, sizeof(buf)));
|
||||
|
||||
if (r->ce_mask & RULE_ATTR_SPORT) {
|
||||
if (r->r_sport.start == r->r_sport.end)
|
||||
nl_dump(p, "sport %u ", r->r_sport.start);
|
||||
else
|
||||
nl_dump(p, "sport %u-%u ",
|
||||
r->r_sport.start, r->r_sport.end);
|
||||
}
|
||||
|
||||
if (r->ce_mask & RULE_ATTR_DPORT) {
|
||||
if (r->r_dport.start == r->r_dport.end)
|
||||
nl_dump(p, "dport %u ", r->r_dport.start);
|
||||
else
|
||||
nl_dump(p, "dport %u-%u ",
|
||||
r->r_dport.start, r->r_dport.end);
|
||||
}
|
||||
|
||||
if (r->ce_mask & RULE_ATTR_PROTOCOL)
|
||||
nl_dump(p, "protocol %s ",
|
||||
rtnl_route_proto2str(r->r_protocol, buf, sizeof(buf)));
|
||||
|
||||
if (r->ce_mask & RULE_ATTR_FLOW)
|
||||
nl_dump(p, "flow %s ",
|
||||
rtnl_realms2str(r->r_flow, buf, sizeof(buf)));
|
||||
@ -256,8 +316,6 @@ static void rule_dump_stats(struct nl_object *obj, struct nl_dump_params *p)
|
||||
rule_dump_details(obj, p);
|
||||
}
|
||||
|
||||
#define RULE_ATTR_FLAGS 0x0008
|
||||
|
||||
static uint64_t rule_compare(struct nl_object *_a, struct nl_object *_b,
|
||||
uint64_t attrs, int flags)
|
||||
{
|
||||
@ -430,6 +488,19 @@ static int build_rule_msg(struct rtnl_rule *tmpl, int cmd, int flags,
|
||||
if (tmpl->ce_mask & RULE_ATTR_L3MDEV)
|
||||
NLA_PUT_U8(msg, FRA_L3MDEV, tmpl->r_l3mdev);
|
||||
|
||||
if (tmpl->ce_mask & RULE_ATTR_IP_PROTO)
|
||||
NLA_PUT_U8(msg, FRA_IP_PROTO, tmpl->r_ip_proto);
|
||||
|
||||
if (tmpl->ce_mask & RULE_ATTR_SPORT)
|
||||
NLA_PUT(msg, FRA_SPORT_RANGE, sizeof(tmpl->r_sport),
|
||||
&tmpl->r_sport);
|
||||
|
||||
if (tmpl->ce_mask & RULE_ATTR_DPORT)
|
||||
NLA_PUT(msg, FRA_DPORT_RANGE, sizeof(tmpl->r_dport),
|
||||
&tmpl->r_dport);
|
||||
|
||||
if (tmpl->ce_mask & RULE_ATTR_PROTOCOL)
|
||||
NLA_PUT_U8(msg, FRA_PROTOCOL, tmpl->r_protocol);
|
||||
|
||||
*result = msg;
|
||||
return 0;
|
||||
@ -744,6 +815,114 @@ int rtnl_rule_get_l3mdev(struct rtnl_rule *rule)
|
||||
return rule->r_l3mdev;
|
||||
}
|
||||
|
||||
int rtnl_rule_set_protocol(struct rtnl_rule *rule, uint8_t protocol)
|
||||
{
|
||||
if (protocol) {
|
||||
rule->r_protocol = protocol;
|
||||
rule->ce_mask |= RULE_ATTR_PROTOCOL;
|
||||
} else {
|
||||
rule->r_protocol = 0;
|
||||
rule->ce_mask &= ~((uint32_t) RULE_ATTR_PROTOCOL);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rtnl_rule_get_protocol(struct rtnl_rule *rule, uint8_t *protocol)
|
||||
{
|
||||
if (!(rule->ce_mask & RULE_ATTR_PROTOCOL))
|
||||
return -NLE_INVAL;
|
||||
|
||||
*protocol = rule->r_protocol;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rtnl_rule_set_ipproto(struct rtnl_rule *rule, uint8_t ip_proto)
|
||||
{
|
||||
if (ip_proto) {
|
||||
rule->r_ip_proto = ip_proto;
|
||||
rule->ce_mask |= RULE_ATTR_IP_PROTO;
|
||||
} else {
|
||||
rule->r_ip_proto = 0;
|
||||
rule->ce_mask &= ~((uint32_t) RULE_ATTR_IP_PROTO);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rtnl_rule_get_ipproto(struct rtnl_rule *rule, uint8_t *ip_proto)
|
||||
{
|
||||
if (!(rule->ce_mask & RULE_ATTR_IP_PROTO))
|
||||
return -NLE_INVAL;
|
||||
|
||||
*ip_proto = rule->r_ip_proto;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __rtnl_rule_set_port(struct fib_rule_port_range *prange,
|
||||
uint16_t start, uint16_t end,
|
||||
uint64_t attr, uint64_t *mask)
|
||||
{
|
||||
if ((start && end < start) || (end && !start))
|
||||
return -NLE_INVAL;
|
||||
|
||||
if (start) {
|
||||
prange->start = start;
|
||||
prange->end = end;
|
||||
*mask |= attr;
|
||||
} else {
|
||||
prange->start = 0;
|
||||
prange->end = 0;
|
||||
*mask &= ~attr;
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rtnl_rule_set_sport(struct rtnl_rule *rule, uint16_t sport)
|
||||
{
|
||||
return __rtnl_rule_set_port(&rule->r_sport, sport, sport,
|
||||
RULE_ATTR_SPORT, &rule->ce_mask);
|
||||
}
|
||||
|
||||
int rtnl_rule_set_sport_range(struct rtnl_rule *rule, uint16_t start,
|
||||
uint16_t end)
|
||||
{
|
||||
return __rtnl_rule_set_port(&rule->r_sport, start, end,
|
||||
RULE_ATTR_SPORT, &rule->ce_mask);
|
||||
}
|
||||
|
||||
int rtnl_rule_get_sport(struct rtnl_rule *rule, uint16_t *start, uint16_t *end)
|
||||
{
|
||||
if (!(rule->ce_mask & RULE_ATTR_SPORT))
|
||||
return -NLE_INVAL;
|
||||
|
||||
*start = rule->r_sport.start;
|
||||
*end = rule->r_sport.end;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rtnl_rule_set_dport(struct rtnl_rule *rule, uint16_t dport)
|
||||
{
|
||||
return __rtnl_rule_set_port(&rule->r_dport, dport, dport,
|
||||
RULE_ATTR_DPORT, &rule->ce_mask);
|
||||
}
|
||||
|
||||
int rtnl_rule_set_dport_range(struct rtnl_rule *rule, uint16_t start,
|
||||
uint16_t end)
|
||||
{
|
||||
return __rtnl_rule_set_port(&rule->r_dport, start, end,
|
||||
RULE_ATTR_DPORT, &rule->ce_mask);
|
||||
}
|
||||
|
||||
int rtnl_rule_get_dport(struct rtnl_rule *rule, uint16_t *start, uint16_t *end)
|
||||
{
|
||||
if (!(rule->ce_mask & RULE_ATTR_DPORT))
|
||||
return -NLE_INVAL;
|
||||
|
||||
*start = rule->r_dport.start;
|
||||
*end = rule->r_dport.end;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rtnl_rule_set_realms(struct rtnl_rule *rule, uint32_t realms)
|
||||
{
|
||||
rule->r_flow = realms;
|
||||
|
@ -1088,4 +1088,14 @@ global:
|
||||
rtnl_link_geneve_get_udp_zero_csum6_rx;
|
||||
rtnl_link_geneve_set_flags;
|
||||
rtnl_link_geneve_get_flags;
|
||||
rtnl_rule_set_protocol;
|
||||
rtnl_rule_get_protocol;
|
||||
rtnl_rule_set_ipproto;
|
||||
rtnl_rule_get_ipproto;
|
||||
rtnl_rule_set_sport;
|
||||
rtnl_rule_set_sport_range;
|
||||
rtnl_rule_get_sport;
|
||||
rtnl_rule_set_dport;
|
||||
rtnl_rule_set_dport_range;
|
||||
rtnl_rule_get_dport;
|
||||
} libnl_3_4;
|
||||
|
Loading…
Reference in New Issue
Block a user