diff --git a/include/netlink-private/types.h b/include/netlink-private/types.h index 36fd3a5..b6c5cea 100644 --- a/include/netlink-private/types.h +++ b/include/netlink-private/types.h @@ -346,7 +346,7 @@ struct rtnl_rule uint8_t r_family; uint8_t r_action; uint8_t r_dsfield; /* ipv4 only */ - uint8_t r_unused; + uint8_t r_l3mdev; uint32_t r_table; uint32_t r_flags; uint32_t r_prio; diff --git a/include/netlink/route/rule.h b/include/netlink/route/rule.h index 760b782..ec24269 100644 --- a/include/netlink/route/rule.h +++ b/include/netlink/route/rule.h @@ -67,6 +67,8 @@ extern void rtnl_rule_set_realms(struct rtnl_rule *, uint32_t); extern uint32_t rtnl_rule_get_realms(struct rtnl_rule *); 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 *); +extern uint8_t rtnl_rule_get_l3mdev(struct rtnl_rule *); #ifdef __cplusplus } diff --git a/lib/route/rule.c b/lib/route/rule.c index 2e40bb1..76d9fe8 100644 --- a/lib/route/rule.c +++ b/lib/route/rule.c @@ -39,6 +39,7 @@ #define RULE_ATTR_DST 0x0800 #define RULE_ATTR_DSFIELD 0x1000 #define RULE_ATTR_FLOW 0x2000 +#define RULE_ATTR_L3MDEV 0x4000 static struct nl_cache_ops rtnl_rule_ops; static struct nl_object_ops rule_obj_ops; @@ -80,6 +81,7 @@ static struct nla_policy rule_policy[FRA_MAX+1] = { [FRA_FWMASK] = { .type = NLA_U32 }, [FRA_GOTO] = { .type = NLA_U32 }, [FRA_FLOW] = { .type = NLA_U32 }, + [FRA_L3MDEV] = { .type = NLA_U8 }, }; static int rule_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, @@ -108,8 +110,9 @@ static int rule_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, rule->r_action = frh->action; rule->r_flags = frh->flags; - rule->ce_mask = (RULE_ATTR_FAMILY | RULE_ATTR_TABLE | RULE_ATTR_ACTION | - RULE_ATTR_FLAGS); + rule->ce_mask = (RULE_ATTR_FAMILY | RULE_ATTR_ACTION | RULE_ATTR_FLAGS); + if (rule->r_table) + rule->ce_mask |= RULE_ATTR_TABLE; /* ipv4 only */ if (frh->tos) { @@ -119,7 +122,8 @@ static int rule_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, if (tb[FRA_TABLE]) { rule->r_table = nla_get_u32(tb[FRA_TABLE]); - rule->ce_mask |= RULE_ATTR_TABLE; + if (rule->r_table) + rule->ce_mask |= RULE_ATTR_TABLE; } if (tb[FRA_IIFNAME]) { @@ -173,6 +177,11 @@ static int rule_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, rule->ce_mask |= RULE_ATTR_FLOW; } + if (tb[FRA_L3MDEV]) { + rule->r_l3mdev = nla_get_u8(tb[FRA_L3MDEV]); + rule->ce_mask |= RULE_ATTR_L3MDEV; + } + err = pp->pp_cb((struct nl_object *) rule, pp); errout: rtnl_rule_put(rule); @@ -220,6 +229,9 @@ static void rule_dump_line(struct nl_object *o, struct nl_dump_params *p) nl_dump(p, "lookup %s ", rtnl_route_table2str(r->r_table, buf, sizeof(buf))); + if (r->ce_mask & RULE_ATTR_L3MDEV) + nl_dump(p, "lookup [l3mdev-table] "); + if (r->ce_mask & RULE_ATTR_FLOW) nl_dump(p, "flow %s ", rtnl_realms2str(r->r_flow, buf, sizeof(buf))); @@ -415,6 +427,9 @@ static int build_rule_msg(struct rtnl_rule *tmpl, int cmd, int flags, if (tmpl->ce_mask & RULE_ATTR_FLOW) NLA_PUT_U32(msg, FRA_FLOW, tmpl->r_flow); + if (tmpl->ce_mask & RULE_ATTR_L3MDEV) + NLA_PUT_U8(msg, FRA_L3MDEV, tmpl->r_l3mdev); + *result = msg; return 0; @@ -691,6 +706,17 @@ uint8_t rtnl_rule_get_action(struct rtnl_rule *rule) return rule->r_action; } +void rtnl_rule_set_l3mdev(struct rtnl_rule *rule) +{ + rule->r_l3mdev = 1; + rule->ce_mask |= RULE_ATTR_L3MDEV; +} + +uint8_t rtnl_rule_get_l3mdev(struct rtnl_rule *rule) +{ + return rule->r_l3mdev; +} + void rtnl_rule_set_realms(struct rtnl_rule *rule, uint32_t realms) { rule->r_flow = realms;