144d362409d5469aed47d19e7908d19bd194493aThomas Graf/*
244d362409d5469aed47d19e7908d19bd194493aThomas Graf * lib/route/rule.c          Routing Rules
344d362409d5469aed47d19e7908d19bd194493aThomas Graf *
444d362409d5469aed47d19e7908d19bd194493aThomas Graf *	This library is free software; you can redistribute it and/or
544d362409d5469aed47d19e7908d19bd194493aThomas Graf *	modify it under the terms of the GNU Lesser General Public
644d362409d5469aed47d19e7908d19bd194493aThomas Graf *	License as published by the Free Software Foundation version 2.1
744d362409d5469aed47d19e7908d19bd194493aThomas Graf *	of the License.
844d362409d5469aed47d19e7908d19bd194493aThomas Graf *
9054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * Copyright (c) 2003-2010 Thomas Graf <tgraf@suug.ch>
1044d362409d5469aed47d19e7908d19bd194493aThomas Graf */
1144d362409d5469aed47d19e7908d19bd194493aThomas Graf
1244d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
1344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @ingroup rtnl
1444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @defgroup rule Routing Rules
1544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @brief
1644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{
1744d362409d5469aed47d19e7908d19bd194493aThomas Graf */
1844d362409d5469aed47d19e7908d19bd194493aThomas Graf
19054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart#include <netlink-private/netlink.h>
2044d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/netlink.h>
2144d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/utils.h>
2244d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/route/rtnl.h>
2344d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/route/rule.h>
2444d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <inttypes.h>
2544d362409d5469aed47d19e7908d19bd194493aThomas Graf
2644d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @cond SKIP */
2744d362409d5469aed47d19e7908d19bd194493aThomas Graf#define RULE_ATTR_FAMILY	0x0001
28054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart#define RULE_ATTR_TABLE		0x0002
29054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart#define RULE_ATTR_ACTION	0x0004
30054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart#define RULE_ATTR_FLAGS		0x0008
31054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart#define RULE_ATTR_IIFNAME	0x0010
32054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart#define RULE_ATTR_OIFNAME	0x0020
33054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart#define RULE_ATTR_PRIO		0x0040
34054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart#define RULE_ATTR_MARK		0x0080
35054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart#define RULE_ATTR_MASK		0x0100
36054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart#define RULE_ATTR_GOTO		0x0200
37054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart#define RULE_ATTR_SRC		0x0400
38054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart#define RULE_ATTR_DST		0x0800
39054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart#define RULE_ATTR_DSFIELD	0x1000
40054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart#define RULE_ATTR_FLOW		0x2000
4144d362409d5469aed47d19e7908d19bd194493aThomas Graf
4244d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct nl_cache_ops rtnl_rule_ops;
4344d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct nl_object_ops rule_obj_ops;
4444d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @endcond */
4544d362409d5469aed47d19e7908d19bd194493aThomas Graf
4644d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic void rule_free_data(struct nl_object *c)
4744d362409d5469aed47d19e7908d19bd194493aThomas Graf{
4844d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct rtnl_rule *rule = nl_object_priv(c);
4944d362409d5469aed47d19e7908d19bd194493aThomas Graf
5044d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (!rule)
5144d362409d5469aed47d19e7908d19bd194493aThomas Graf		return;
5244d362409d5469aed47d19e7908d19bd194493aThomas Graf
5344d362409d5469aed47d19e7908d19bd194493aThomas Graf	nl_addr_put(rule->r_src);
5444d362409d5469aed47d19e7908d19bd194493aThomas Graf	nl_addr_put(rule->r_dst);
5544d362409d5469aed47d19e7908d19bd194493aThomas Graf}
5644d362409d5469aed47d19e7908d19bd194493aThomas Graf
5744d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int rule_clone(struct nl_object *_dst, struct nl_object *_src)
5844d362409d5469aed47d19e7908d19bd194493aThomas Graf{
5944d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct rtnl_rule *dst = nl_object_priv(_dst);
6044d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct rtnl_rule *src = nl_object_priv(_src);
6144d362409d5469aed47d19e7908d19bd194493aThomas Graf
6244d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (src->r_src)
6344d362409d5469aed47d19e7908d19bd194493aThomas Graf		if (!(dst->r_src = nl_addr_clone(src->r_src)))
648a3efffa5b3fde252675239914118664d36a2c24Thomas Graf			return -NLE_NOMEM;
6544d362409d5469aed47d19e7908d19bd194493aThomas Graf
6644d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (src->r_dst)
6744d362409d5469aed47d19e7908d19bd194493aThomas Graf		if (!(dst->r_dst = nl_addr_clone(src->r_dst)))
688a3efffa5b3fde252675239914118664d36a2c24Thomas Graf			return -NLE_NOMEM;
6944d362409d5469aed47d19e7908d19bd194493aThomas Graf
7044d362409d5469aed47d19e7908d19bd194493aThomas Graf	return 0;
7144d362409d5469aed47d19e7908d19bd194493aThomas Graf}
7244d362409d5469aed47d19e7908d19bd194493aThomas Graf
73054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartstatic struct nla_policy rule_policy[FRA_MAX+1] = {
74054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	[FRA_TABLE]	= { .type = NLA_U32 },
75054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	[FRA_IIFNAME]	= { .type = NLA_STRING, .maxlen = IFNAMSIZ },
76054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	[FRA_OIFNAME]	= { .type = NLA_STRING, .maxlen = IFNAMSIZ },
77054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	[FRA_PRIORITY]	= { .type = NLA_U32 },
78054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	[FRA_FWMARK]	= { .type = NLA_U32 },
79054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	[FRA_FWMASK]	= { .type = NLA_U32 },
80054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	[FRA_GOTO]	= { .type = NLA_U32 },
81054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	[FRA_FLOW]	= { .type = NLA_U32 },
8244d362409d5469aed47d19e7908d19bd194493aThomas Graf};
8344d362409d5469aed47d19e7908d19bd194493aThomas Graf
8444d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int rule_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
853040a1d6254465bed9e44e4d1bf279c2c50cd16aThomas Graf			   struct nlmsghdr *n, struct nl_parser_param *pp)
8644d362409d5469aed47d19e7908d19bd194493aThomas Graf{
8744d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct rtnl_rule *rule;
88054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	struct fib_rule_hdr *frh;
89054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	struct nlattr *tb[FRA_MAX+1];
90eed2afaab7aa72fae393a395a8879b91a922ff5eThomas Graf	int err = 1, family;
9144d362409d5469aed47d19e7908d19bd194493aThomas Graf
9244d362409d5469aed47d19e7908d19bd194493aThomas Graf	rule = rtnl_rule_alloc();
9344d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (!rule) {
948a3efffa5b3fde252675239914118664d36a2c24Thomas Graf		err = -NLE_NOMEM;
9544d362409d5469aed47d19e7908d19bd194493aThomas Graf		goto errout;
9644d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
9744d362409d5469aed47d19e7908d19bd194493aThomas Graf
9844d362409d5469aed47d19e7908d19bd194493aThomas Graf	rule->ce_msgtype = n->nlmsg_type;
99054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	frh = nlmsg_data(n);
10044d362409d5469aed47d19e7908d19bd194493aThomas Graf
101054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	err = nlmsg_parse(n, sizeof(*frh), tb, FRA_MAX, rule_policy);
10244d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (err < 0)
10344d362409d5469aed47d19e7908d19bd194493aThomas Graf		goto errout;
10444d362409d5469aed47d19e7908d19bd194493aThomas Graf
105054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	rule->r_family = family = frh->family;
106054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	rule->r_table = frh->table;
107054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	rule->r_action = frh->action;
108054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	rule->r_flags = frh->flags;
109054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
110054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	rule->ce_mask = (RULE_ATTR_FAMILY | RULE_ATTR_TABLE | RULE_ATTR_ACTION |
111054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart			 RULE_ATTR_FLAGS);
112054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
113054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	/* ipv4 only */
114054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	if (frh->tos) {
115054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		rule->r_dsfield = frh->tos;
116054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		rule->ce_mask |= RULE_ATTR_DSFIELD;
11744d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
11844d362409d5469aed47d19e7908d19bd194493aThomas Graf
119054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	if (tb[FRA_TABLE]) {
120054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		rule->r_table = nla_get_u32(tb[FRA_TABLE]);
121054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		rule->ce_mask |= RULE_ATTR_TABLE;
12244d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
12344d362409d5469aed47d19e7908d19bd194493aThomas Graf
124054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	if (tb[FRA_IIFNAME]) {
125054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		nla_strlcpy(rule->r_iifname, tb[FRA_IIFNAME], IFNAMSIZ);
126054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		rule->ce_mask |= RULE_ATTR_IIFNAME;
12744d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
12844d362409d5469aed47d19e7908d19bd194493aThomas Graf
129054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	if (tb[FRA_OIFNAME]) {
130054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		nla_strlcpy(rule->r_oifname, tb[FRA_OIFNAME], IFNAMSIZ);
131054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		rule->ce_mask |= RULE_ATTR_OIFNAME;
132054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	}
133054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
134054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	if (tb[FRA_PRIORITY]) {
135054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		rule->r_prio = nla_get_u32(tb[FRA_PRIORITY]);
136054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		rule->ce_mask |= RULE_ATTR_PRIO;
137054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	}
138054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
139054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	if (tb[FRA_FWMARK]) {
140054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		rule->r_mark = nla_get_u32(tb[FRA_FWMARK]);
14144d362409d5469aed47d19e7908d19bd194493aThomas Graf		rule->ce_mask |= RULE_ATTR_MARK;
14244d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
14344d362409d5469aed47d19e7908d19bd194493aThomas Graf
144054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	if (tb[FRA_FWMASK]) {
145054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		rule->r_mask = nla_get_u32(tb[FRA_FWMASK]);
146054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		rule->ce_mask |= RULE_ATTR_MASK;
147054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	}
148054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
149054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	if (tb[FRA_GOTO]) {
150054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		rule->r_goto = nla_get_u32(tb[FRA_GOTO]);
151054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		rule->ce_mask |= RULE_ATTR_GOTO;
15244d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
15344d362409d5469aed47d19e7908d19bd194493aThomas Graf
154054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	if (tb[FRA_SRC]) {
155054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		if (!(rule->r_src = nl_addr_alloc_attr(tb[FRA_SRC], family)))
156054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart			goto errout_enomem;
157054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
158054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		nl_addr_set_prefixlen(rule->r_src, frh->src_len);
159054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		rule->ce_mask |= RULE_ATTR_SRC;
16044d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
16144d362409d5469aed47d19e7908d19bd194493aThomas Graf
162054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	if (tb[FRA_DST]) {
163054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		if (!(rule->r_dst = nl_addr_alloc_attr(tb[FRA_DST], family)))
164eed2afaab7aa72fae393a395a8879b91a922ff5eThomas Graf			goto errout_enomem;
165054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		nl_addr_set_prefixlen(rule->r_dst, frh->dst_len);
166054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		rule->ce_mask |= RULE_ATTR_DST;
16744d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
16844d362409d5469aed47d19e7908d19bd194493aThomas Graf
169054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	/* ipv4 only */
170054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	if (tb[FRA_FLOW]) {
171054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		rule->r_flow = nla_get_u32(tb[FRA_FLOW]);
172054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		rule->ce_mask |= RULE_ATTR_FLOW;
173054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	}
174107dc162c56ace6eea5a167b7881520e6cecb831Ben Gamsa
17544d362409d5469aed47d19e7908d19bd194493aThomas Graf	err = pp->pp_cb((struct nl_object *) rule, pp);
17644d362409d5469aed47d19e7908d19bd194493aThomas Graferrout:
17744d362409d5469aed47d19e7908d19bd194493aThomas Graf	rtnl_rule_put(rule);
17844d362409d5469aed47d19e7908d19bd194493aThomas Graf	return err;
179eed2afaab7aa72fae393a395a8879b91a922ff5eThomas Graf
180eed2afaab7aa72fae393a395a8879b91a922ff5eThomas Graferrout_enomem:
181eed2afaab7aa72fae393a395a8879b91a922ff5eThomas Graf	err = -NLE_NOMEM;
182eed2afaab7aa72fae393a395a8879b91a922ff5eThomas Graf	goto errout;
18344d362409d5469aed47d19e7908d19bd194493aThomas Graf}
18444d362409d5469aed47d19e7908d19bd194493aThomas Graf
1851155370f520cb64657e25153255cf7dc1424317fThomas Grafstatic int rule_request_update(struct nl_cache *c, struct nl_sock *h)
18644d362409d5469aed47d19e7908d19bd194493aThomas Graf{
18744d362409d5469aed47d19e7908d19bd194493aThomas Graf	return nl_rtgen_request(h, RTM_GETRULE, AF_UNSPEC, NLM_F_DUMP);
18844d362409d5469aed47d19e7908d19bd194493aThomas Graf}
18944d362409d5469aed47d19e7908d19bd194493aThomas Graf
190d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Grafstatic void rule_dump_line(struct nl_object *o, struct nl_dump_params *p)
19144d362409d5469aed47d19e7908d19bd194493aThomas Graf{
19244d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct rtnl_rule *r = (struct rtnl_rule *) o;
19344d362409d5469aed47d19e7908d19bd194493aThomas Graf	char buf[128];
19444d362409d5469aed47d19e7908d19bd194493aThomas Graf
195d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf	nl_dump_line(p, "%8d ", (r->ce_mask & RULE_ATTR_PRIO) ? r->r_prio : 0);
196d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf	nl_dump(p, "%s ", nl_af2str(r->r_family, buf, sizeof(buf)));
19744d362409d5469aed47d19e7908d19bd194493aThomas Graf
19844d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (r->ce_mask & RULE_ATTR_SRC)
199d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf		nl_dump(p, "from %s ",
20044d362409d5469aed47d19e7908d19bd194493aThomas Graf			nl_addr2str(r->r_src, buf, sizeof(buf)));
20144d362409d5469aed47d19e7908d19bd194493aThomas Graf
20244d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (r->ce_mask & RULE_ATTR_DST)
203d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf		nl_dump(p, "to %s ",
20444d362409d5469aed47d19e7908d19bd194493aThomas Graf			nl_addr2str(r->r_dst, buf, sizeof(buf)));
20544d362409d5469aed47d19e7908d19bd194493aThomas Graf
206054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	if (r->ce_mask & RULE_ATTR_DSFIELD)
207054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		nl_dump(p, "tos %u ", r->r_dsfield);
208054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
209054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	if (r->ce_mask & (RULE_ATTR_MARK | RULE_ATTR_MASK))
210054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		nl_dump(p, "mark %#x/%#x", r->r_mark, r->r_mask);
21144d362409d5469aed47d19e7908d19bd194493aThomas Graf
212054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	if (r->ce_mask & RULE_ATTR_IIFNAME)
213054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		nl_dump(p, "iif %s ", r->r_iifname);
21444d362409d5469aed47d19e7908d19bd194493aThomas Graf
215054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	if (r->ce_mask & RULE_ATTR_OIFNAME)
216054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		nl_dump(p, "oif %s ", r->r_oifname);
21744d362409d5469aed47d19e7908d19bd194493aThomas Graf
21844d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (r->ce_mask & RULE_ATTR_TABLE)
219d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf		nl_dump(p, "lookup %s ",
22044d362409d5469aed47d19e7908d19bd194493aThomas Graf			rtnl_route_table2str(r->r_table, buf, sizeof(buf)));
22144d362409d5469aed47d19e7908d19bd194493aThomas Graf
222054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	if (r->ce_mask & RULE_ATTR_FLOW)
223054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		nl_dump(p, "flow %s ",
224054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart			rtnl_realms2str(r->r_flow, buf, sizeof(buf)));
22544d362409d5469aed47d19e7908d19bd194493aThomas Graf
226054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	if (r->ce_mask & RULE_ATTR_GOTO)
227054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		nl_dump(p, "goto %u ", r->r_goto);
228054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
229054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	if (r->ce_mask & RULE_ATTR_ACTION)
230054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		nl_dump(p, "action %s",
231054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart			nl_rtntype2str(r->r_action, buf, sizeof(buf)));
232054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
233054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	nl_dump(p, "\n");
23444d362409d5469aed47d19e7908d19bd194493aThomas Graf}
23544d362409d5469aed47d19e7908d19bd194493aThomas Graf
236d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Grafstatic void rule_dump_details(struct nl_object *obj, struct nl_dump_params *p)
23744d362409d5469aed47d19e7908d19bd194493aThomas Graf{
238d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf	rule_dump_line(obj, p);
23944d362409d5469aed47d19e7908d19bd194493aThomas Graf}
24044d362409d5469aed47d19e7908d19bd194493aThomas Graf
241d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Grafstatic void rule_dump_stats(struct nl_object *obj, struct nl_dump_params *p)
24244d362409d5469aed47d19e7908d19bd194493aThomas Graf{
243d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf	rule_dump_details(obj, p);
24444d362409d5469aed47d19e7908d19bd194493aThomas Graf}
24544d362409d5469aed47d19e7908d19bd194493aThomas Graf
246054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart#define RULE_ATTR_FLAGS		0x0008
24744d362409d5469aed47d19e7908d19bd194493aThomas Graf
24844d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int rule_compare(struct nl_object *_a, struct nl_object *_b,
24944d362409d5469aed47d19e7908d19bd194493aThomas Graf			uint32_t attrs, int flags)
25044d362409d5469aed47d19e7908d19bd194493aThomas Graf{
25144d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct rtnl_rule *a = (struct rtnl_rule *) _a;
25244d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct rtnl_rule *b = (struct rtnl_rule *) _b;
25344d362409d5469aed47d19e7908d19bd194493aThomas Graf	int diff = 0;
25444d362409d5469aed47d19e7908d19bd194493aThomas Graf
25544d362409d5469aed47d19e7908d19bd194493aThomas Graf#define RULE_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, RULE_ATTR_##ATTR, a, b, EXPR)
25644d362409d5469aed47d19e7908d19bd194493aThomas Graf
25744d362409d5469aed47d19e7908d19bd194493aThomas Graf	diff |= RULE_DIFF(FAMILY,	a->r_family != b->r_family);
25844d362409d5469aed47d19e7908d19bd194493aThomas Graf	diff |= RULE_DIFF(TABLE,	a->r_table != b->r_table);
259054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	diff |= RULE_DIFF(ACTION,	a->r_action != b->r_action);
260054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	diff |= RULE_DIFF(IIFNAME,	strcmp(a->r_iifname, b->r_iifname));
261054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	diff |= RULE_DIFF(OIFNAME,	strcmp(a->r_oifname, b->r_oifname));
26244d362409d5469aed47d19e7908d19bd194493aThomas Graf	diff |= RULE_DIFF(PRIO,		a->r_prio != b->r_prio);
26344d362409d5469aed47d19e7908d19bd194493aThomas Graf	diff |= RULE_DIFF(MARK,		a->r_mark != b->r_mark);
264054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	diff |= RULE_DIFF(MASK,		a->r_mask != b->r_mask);
265054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	diff |= RULE_DIFF(GOTO,		a->r_goto != b->r_goto);
26644d362409d5469aed47d19e7908d19bd194493aThomas Graf	diff |= RULE_DIFF(SRC,		nl_addr_cmp(a->r_src, b->r_src));
26744d362409d5469aed47d19e7908d19bd194493aThomas Graf	diff |= RULE_DIFF(DST,		nl_addr_cmp(a->r_dst, b->r_dst));
268054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	diff |= RULE_DIFF(DSFIELD,	a->r_dsfield != b->r_dsfield);
269054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	diff |= RULE_DIFF(FLOW,		a->r_flow != b->r_flow);
27044d362409d5469aed47d19e7908d19bd194493aThomas Graf
27144d362409d5469aed47d19e7908d19bd194493aThomas Graf#undef RULE_DIFF
27244d362409d5469aed47d19e7908d19bd194493aThomas Graf
27344d362409d5469aed47d19e7908d19bd194493aThomas Graf	return diff;
27444d362409d5469aed47d19e7908d19bd194493aThomas Graf}
27544d362409d5469aed47d19e7908d19bd194493aThomas Graf
276054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartstatic const struct trans_tbl rule_attrs[] = {
27744d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(RULE_ATTR_FAMILY, family)
278054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	__ADD(RULE_ATTR_TABLE, table)
279054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	__ADD(RULE_ATTR_ACTION, action)
280054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	__ADD(RULE_ATTR_IIFNAME, iifname)
281054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	__ADD(RULE_ATTR_OIFNAME, oifname)
28244d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(RULE_ATTR_PRIO, prio)
28344d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(RULE_ATTR_MARK, mark)
284054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	__ADD(RULE_ATTR_MASK, mask)
285054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	__ADD(RULE_ATTR_GOTO, goto)
28644d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(RULE_ATTR_SRC, src)
28744d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(RULE_ATTR_DST, dst)
28844d362409d5469aed47d19e7908d19bd194493aThomas Graf	__ADD(RULE_ATTR_DSFIELD, dsfield)
289054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	__ADD(RULE_ATTR_FLOW, flow)
29044d362409d5469aed47d19e7908d19bd194493aThomas Graf};
29144d362409d5469aed47d19e7908d19bd194493aThomas Graf
29244d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic char *rule_attrs2str(int attrs, char *buf, size_t len)
29344d362409d5469aed47d19e7908d19bd194493aThomas Graf{
29444d362409d5469aed47d19e7908d19bd194493aThomas Graf	return __flags2str(attrs, buf, len, rule_attrs,
29544d362409d5469aed47d19e7908d19bd194493aThomas Graf			   ARRAY_SIZE(rule_attrs));
29644d362409d5469aed47d19e7908d19bd194493aThomas Graf}
29744d362409d5469aed47d19e7908d19bd194493aThomas Graf
29844d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
29944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Allocation/Freeing
30044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{
30144d362409d5469aed47d19e7908d19bd194493aThomas Graf */
30244d362409d5469aed47d19e7908d19bd194493aThomas Graf
30344d362409d5469aed47d19e7908d19bd194493aThomas Grafstruct rtnl_rule *rtnl_rule_alloc(void)
30444d362409d5469aed47d19e7908d19bd194493aThomas Graf{
30544d362409d5469aed47d19e7908d19bd194493aThomas Graf	return (struct rtnl_rule *) nl_object_alloc(&rule_obj_ops);
30644d362409d5469aed47d19e7908d19bd194493aThomas Graf}
30744d362409d5469aed47d19e7908d19bd194493aThomas Graf
30844d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid rtnl_rule_put(struct rtnl_rule *rule)
30944d362409d5469aed47d19e7908d19bd194493aThomas Graf{
31044d362409d5469aed47d19e7908d19bd194493aThomas Graf	nl_object_put((struct nl_object *) rule);
31144d362409d5469aed47d19e7908d19bd194493aThomas Graf}
31244d362409d5469aed47d19e7908d19bd194493aThomas Graf
31344d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */
31444d362409d5469aed47d19e7908d19bd194493aThomas Graf
31544d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
31644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Cache Management
31744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{
31844d362409d5469aed47d19e7908d19bd194493aThomas Graf */
31944d362409d5469aed47d19e7908d19bd194493aThomas Graf
32044d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
3218a3efffa5b3fde252675239914118664d36a2c24Thomas Graf * Build a rule cache including all rules currently configured in the kernel.
322054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @arg sock		Netlink socket.
3238a3efffa5b3fde252675239914118664d36a2c24Thomas Graf * @arg family		Address family or AF_UNSPEC.
3248a3efffa5b3fde252675239914118664d36a2c24Thomas Graf * @arg result		Pointer to store resulting cache.
32544d362409d5469aed47d19e7908d19bd194493aThomas Graf *
32644d362409d5469aed47d19e7908d19bd194493aThomas Graf * Allocates a new rule cache, initializes it properly and updates it
3278a3efffa5b3fde252675239914118664d36a2c24Thomas Graf * to include all rules currently configured in the kernel.
32844d362409d5469aed47d19e7908d19bd194493aThomas Graf *
3298a3efffa5b3fde252675239914118664d36a2c24Thomas Graf * @return 0 on success or a negative error code.
33044d362409d5469aed47d19e7908d19bd194493aThomas Graf */
3311155370f520cb64657e25153255cf7dc1424317fThomas Grafint rtnl_rule_alloc_cache(struct nl_sock *sock, int family,
3328a3efffa5b3fde252675239914118664d36a2c24Thomas Graf			  struct nl_cache **result)
33344d362409d5469aed47d19e7908d19bd194493aThomas Graf{
33444d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct nl_cache * cache;
3358a3efffa5b3fde252675239914118664d36a2c24Thomas Graf	int err;
33644d362409d5469aed47d19e7908d19bd194493aThomas Graf
3378a3efffa5b3fde252675239914118664d36a2c24Thomas Graf	if (!(cache = nl_cache_alloc(&rtnl_rule_ops)))
3388a3efffa5b3fde252675239914118664d36a2c24Thomas Graf		return -NLE_NOMEM;
33944d362409d5469aed47d19e7908d19bd194493aThomas Graf
3408a3efffa5b3fde252675239914118664d36a2c24Thomas Graf	cache->c_iarg1 = family;
34144d362409d5469aed47d19e7908d19bd194493aThomas Graf
3428a3efffa5b3fde252675239914118664d36a2c24Thomas Graf	if (sock && (err = nl_cache_refill(sock, cache)) < 0) {
34344d362409d5469aed47d19e7908d19bd194493aThomas Graf		free(cache);
3448a3efffa5b3fde252675239914118664d36a2c24Thomas Graf		return err;
34544d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
34644d362409d5469aed47d19e7908d19bd194493aThomas Graf
3478a3efffa5b3fde252675239914118664d36a2c24Thomas Graf	*result = cache;
3488a3efffa5b3fde252675239914118664d36a2c24Thomas Graf	return 0;
34944d362409d5469aed47d19e7908d19bd194493aThomas Graf}
35044d362409d5469aed47d19e7908d19bd194493aThomas Graf
35144d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */
35244d362409d5469aed47d19e7908d19bd194493aThomas Graf
35344d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
35444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Rule Addition
35544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{
35644d362409d5469aed47d19e7908d19bd194493aThomas Graf */
35744d362409d5469aed47d19e7908d19bd194493aThomas Graf
3588a3efffa5b3fde252675239914118664d36a2c24Thomas Grafstatic int build_rule_msg(struct rtnl_rule *tmpl, int cmd, int flags,
3598a3efffa5b3fde252675239914118664d36a2c24Thomas Graf			  struct nl_msg **result)
36044d362409d5469aed47d19e7908d19bd194493aThomas Graf{
36144d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct nl_msg *msg;
362054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	struct fib_rule_hdr frh = {
363054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		.family = tmpl->r_family,
364054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		.table = tmpl->r_table,
365054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		.action = tmpl->r_action,
366054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		.flags = tmpl->r_flags,
367054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		.tos = tmpl->r_dsfield,
36844d362409d5469aed47d19e7908d19bd194493aThomas Graf	};
36944d362409d5469aed47d19e7908d19bd194493aThomas Graf
370054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	if (!(tmpl->ce_mask & RULE_ATTR_FAMILY))
371054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		return -NLE_MISSING_ATTR;
37244d362409d5469aed47d19e7908d19bd194493aThomas Graf
37344d362409d5469aed47d19e7908d19bd194493aThomas Graf	msg = nlmsg_alloc_simple(cmd, flags);
37444d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (!msg)
3758a3efffa5b3fde252675239914118664d36a2c24Thomas Graf		return -NLE_NOMEM;
37644d362409d5469aed47d19e7908d19bd194493aThomas Graf
377054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	if (tmpl->ce_mask & RULE_ATTR_SRC)
378054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		frh.src_len = nl_addr_get_prefixlen(tmpl->r_src);
379054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
380054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	if (tmpl->ce_mask & RULE_ATTR_DST)
381054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		frh.dst_len = nl_addr_get_prefixlen(tmpl->r_dst);
382054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
383054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	if (nlmsg_append(msg, &frh, sizeof(frh), NLMSG_ALIGNTO) < 0)
38444d362409d5469aed47d19e7908d19bd194493aThomas Graf		goto nla_put_failure;
38544d362409d5469aed47d19e7908d19bd194493aThomas Graf
386054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	/* Additional table attribute replacing the 8bit in the header, was
387054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	 * required to allow more than 256 tables. */
388054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	NLA_PUT_U32(msg, FRA_TABLE, tmpl->r_table);
389054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
39044d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (tmpl->ce_mask & RULE_ATTR_SRC)
391054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		NLA_PUT_ADDR(msg, FRA_SRC, tmpl->r_src);
39244d362409d5469aed47d19e7908d19bd194493aThomas Graf
393054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	if (tmpl->ce_mask & RULE_ATTR_DST)
394054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		NLA_PUT_ADDR(msg, FRA_DST, tmpl->r_dst);
395054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
396054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	if (tmpl->ce_mask & RULE_ATTR_IIFNAME)
397054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		NLA_PUT_STRING(msg, FRA_IIFNAME, tmpl->r_iifname);
398054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
399054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	if (tmpl->ce_mask & RULE_ATTR_OIFNAME)
400054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		NLA_PUT_STRING(msg, FRA_OIFNAME, tmpl->r_oifname);
40144d362409d5469aed47d19e7908d19bd194493aThomas Graf
40244d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (tmpl->ce_mask & RULE_ATTR_PRIO)
403054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		NLA_PUT_U32(msg, FRA_PRIORITY, tmpl->r_prio);
40444d362409d5469aed47d19e7908d19bd194493aThomas Graf
40544d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (tmpl->ce_mask & RULE_ATTR_MARK)
406054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		NLA_PUT_U32(msg, FRA_FWMARK, tmpl->r_mark);
407054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
408054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	if (tmpl->ce_mask & RULE_ATTR_MASK)
409054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		NLA_PUT_U32(msg, FRA_FWMASK, tmpl->r_mask);
410054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
411054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	if (tmpl->ce_mask & RULE_ATTR_GOTO)
412054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		NLA_PUT_U32(msg, FRA_GOTO, tmpl->r_goto);
41344d362409d5469aed47d19e7908d19bd194493aThomas Graf
414054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	if (tmpl->ce_mask & RULE_ATTR_FLOW)
415054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		NLA_PUT_U32(msg, FRA_FLOW, tmpl->r_flow);
41644d362409d5469aed47d19e7908d19bd194493aThomas Graf
41744d362409d5469aed47d19e7908d19bd194493aThomas Graf
4188a3efffa5b3fde252675239914118664d36a2c24Thomas Graf	*result = msg;
4198a3efffa5b3fde252675239914118664d36a2c24Thomas Graf	return 0;
42044d362409d5469aed47d19e7908d19bd194493aThomas Graf
42144d362409d5469aed47d19e7908d19bd194493aThomas Grafnla_put_failure:
42244d362409d5469aed47d19e7908d19bd194493aThomas Graf	nlmsg_free(msg);
4238a3efffa5b3fde252675239914118664d36a2c24Thomas Graf	return -NLE_MSGSIZE;
42444d362409d5469aed47d19e7908d19bd194493aThomas Graf}
42544d362409d5469aed47d19e7908d19bd194493aThomas Graf
42644d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
42744d362409d5469aed47d19e7908d19bd194493aThomas Graf * Build netlink request message to add a new rule
42844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg tmpl		template with data of new rule
42944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg flags		additional netlink message flags
430054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @arg result		Result pointer
43144d362409d5469aed47d19e7908d19bd194493aThomas Graf *
43244d362409d5469aed47d19e7908d19bd194493aThomas Graf * Builds a new netlink message requesting a addition of a new
43344d362409d5469aed47d19e7908d19bd194493aThomas Graf * rule. The netlink message header isn't fully equipped with
43444d362409d5469aed47d19e7908d19bd194493aThomas Graf * all relevant fields and must thus be sent out via nl_send_auto_complete()
43544d362409d5469aed47d19e7908d19bd194493aThomas Graf * or supplemented as needed. \a tmpl must contain the attributes of the new
43644d362409d5469aed47d19e7908d19bd194493aThomas Graf * address set via \c rtnl_rule_set_* functions.
43744d362409d5469aed47d19e7908d19bd194493aThomas Graf *
438054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @return 0 on success or a negative error code.
43944d362409d5469aed47d19e7908d19bd194493aThomas Graf */
4408a3efffa5b3fde252675239914118664d36a2c24Thomas Grafint rtnl_rule_build_add_request(struct rtnl_rule *tmpl, int flags,
4418a3efffa5b3fde252675239914118664d36a2c24Thomas Graf				struct nl_msg **result)
44244d362409d5469aed47d19e7908d19bd194493aThomas Graf{
4438a3efffa5b3fde252675239914118664d36a2c24Thomas Graf	return build_rule_msg(tmpl, RTM_NEWRULE, NLM_F_CREATE | flags,
4448a3efffa5b3fde252675239914118664d36a2c24Thomas Graf			      result);
44544d362409d5469aed47d19e7908d19bd194493aThomas Graf}
44644d362409d5469aed47d19e7908d19bd194493aThomas Graf
44744d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
44844d362409d5469aed47d19e7908d19bd194493aThomas Graf * Add a new rule
4491155370f520cb64657e25153255cf7dc1424317fThomas Graf * @arg sk		Netlink socket.
45044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg tmpl		template with requested changes
45144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg flags		additional netlink message flags
45244d362409d5469aed47d19e7908d19bd194493aThomas Graf *
45344d362409d5469aed47d19e7908d19bd194493aThomas Graf * Builds a netlink message by calling rtnl_rule_build_add_request(),
45444d362409d5469aed47d19e7908d19bd194493aThomas Graf * sends the request to the kernel and waits for the next ACK to be
45544d362409d5469aed47d19e7908d19bd194493aThomas Graf * received and thus blocks until the request has been fullfilled.
45644d362409d5469aed47d19e7908d19bd194493aThomas Graf *
45744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return 0 on sucess or a negative error if an error occured.
45844d362409d5469aed47d19e7908d19bd194493aThomas Graf */
4591155370f520cb64657e25153255cf7dc1424317fThomas Grafint rtnl_rule_add(struct nl_sock *sk, struct rtnl_rule *tmpl, int flags)
46044d362409d5469aed47d19e7908d19bd194493aThomas Graf{
46144d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct nl_msg *msg;
4628a3efffa5b3fde252675239914118664d36a2c24Thomas Graf	int err;
46344d362409d5469aed47d19e7908d19bd194493aThomas Graf
4648a3efffa5b3fde252675239914118664d36a2c24Thomas Graf	if ((err = rtnl_rule_build_add_request(tmpl, flags, &msg)) < 0)
4658a3efffa5b3fde252675239914118664d36a2c24Thomas Graf		return err;
46644d362409d5469aed47d19e7908d19bd194493aThomas Graf
4671155370f520cb64657e25153255cf7dc1424317fThomas Graf	err = nl_send_auto_complete(sk, msg);
4688a3efffa5b3fde252675239914118664d36a2c24Thomas Graf	nlmsg_free(msg);
46944d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (err < 0)
47044d362409d5469aed47d19e7908d19bd194493aThomas Graf		return err;
47144d362409d5469aed47d19e7908d19bd194493aThomas Graf
472cfcfca070355b246028df60da79813f09ed65755Thomas Graf	return wait_for_ack(sk);
47344d362409d5469aed47d19e7908d19bd194493aThomas Graf}
47444d362409d5469aed47d19e7908d19bd194493aThomas Graf
47544d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */
47644d362409d5469aed47d19e7908d19bd194493aThomas Graf
47744d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
47844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Rule Deletion
47944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{
48044d362409d5469aed47d19e7908d19bd194493aThomas Graf */
48144d362409d5469aed47d19e7908d19bd194493aThomas Graf
48244d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
48344d362409d5469aed47d19e7908d19bd194493aThomas Graf * Build a netlink request message to delete a rule
48444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg rule		rule to delete
48544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg flags		additional netlink message flags
486054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @arg result		Result pointer
48744d362409d5469aed47d19e7908d19bd194493aThomas Graf *
48844d362409d5469aed47d19e7908d19bd194493aThomas Graf * Builds a new netlink message requesting a deletion of a rule.
48944d362409d5469aed47d19e7908d19bd194493aThomas Graf * The netlink message header isn't fully equipped with all relevant
49044d362409d5469aed47d19e7908d19bd194493aThomas Graf * fields and must thus be sent out via nl_send_auto_complete()
49144d362409d5469aed47d19e7908d19bd194493aThomas Graf * or supplemented as needed. \a rule must point to an existing
49244d362409d5469aed47d19e7908d19bd194493aThomas Graf * address.
49344d362409d5469aed47d19e7908d19bd194493aThomas Graf *
494054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @return 0 on success or a negative error code.
49544d362409d5469aed47d19e7908d19bd194493aThomas Graf */
4968a3efffa5b3fde252675239914118664d36a2c24Thomas Grafint rtnl_rule_build_delete_request(struct rtnl_rule *rule, int flags,
4978a3efffa5b3fde252675239914118664d36a2c24Thomas Graf				   struct nl_msg **result)
49844d362409d5469aed47d19e7908d19bd194493aThomas Graf{
4998a3efffa5b3fde252675239914118664d36a2c24Thomas Graf	return build_rule_msg(rule, RTM_DELRULE, flags, result);
50044d362409d5469aed47d19e7908d19bd194493aThomas Graf}
50144d362409d5469aed47d19e7908d19bd194493aThomas Graf
50244d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
50344d362409d5469aed47d19e7908d19bd194493aThomas Graf * Delete a rule
5041155370f520cb64657e25153255cf7dc1424317fThomas Graf * @arg sk		Netlink socket.
50544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg rule		rule to delete
50644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg flags		additional netlink message flags
50744d362409d5469aed47d19e7908d19bd194493aThomas Graf *
50844d362409d5469aed47d19e7908d19bd194493aThomas Graf * Builds a netlink message by calling rtnl_rule_build_delete_request(),
50944d362409d5469aed47d19e7908d19bd194493aThomas Graf * sends the request to the kernel and waits for the next ACK to be
51044d362409d5469aed47d19e7908d19bd194493aThomas Graf * received and thus blocks until the request has been fullfilled.
51144d362409d5469aed47d19e7908d19bd194493aThomas Graf *
51244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return 0 on sucess or a negative error if an error occured.
51344d362409d5469aed47d19e7908d19bd194493aThomas Graf */
5141155370f520cb64657e25153255cf7dc1424317fThomas Grafint rtnl_rule_delete(struct nl_sock *sk, struct rtnl_rule *rule, int flags)
51544d362409d5469aed47d19e7908d19bd194493aThomas Graf{
51644d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct nl_msg *msg;
5178a3efffa5b3fde252675239914118664d36a2c24Thomas Graf	int err;
51844d362409d5469aed47d19e7908d19bd194493aThomas Graf
5198a3efffa5b3fde252675239914118664d36a2c24Thomas Graf	if ((err = rtnl_rule_build_delete_request(rule, flags, &msg)) < 0)
5208a3efffa5b3fde252675239914118664d36a2c24Thomas Graf		return err;
52144d362409d5469aed47d19e7908d19bd194493aThomas Graf
5221155370f520cb64657e25153255cf7dc1424317fThomas Graf	err = nl_send_auto_complete(sk, msg);
5238a3efffa5b3fde252675239914118664d36a2c24Thomas Graf	nlmsg_free(msg);
52444d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (err < 0)
52544d362409d5469aed47d19e7908d19bd194493aThomas Graf		return err;
52644d362409d5469aed47d19e7908d19bd194493aThomas Graf
527cfcfca070355b246028df60da79813f09ed65755Thomas Graf	return wait_for_ack(sk);
52844d362409d5469aed47d19e7908d19bd194493aThomas Graf}
52944d362409d5469aed47d19e7908d19bd194493aThomas Graf
53044d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */
53144d362409d5469aed47d19e7908d19bd194493aThomas Graf
53244d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
53344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Attribute Modification
53444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{
53544d362409d5469aed47d19e7908d19bd194493aThomas Graf */
53644d362409d5469aed47d19e7908d19bd194493aThomas Graf
53744d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid rtnl_rule_set_family(struct rtnl_rule *rule, int family)
53844d362409d5469aed47d19e7908d19bd194493aThomas Graf{
53944d362409d5469aed47d19e7908d19bd194493aThomas Graf	rule->r_family = family;
54044d362409d5469aed47d19e7908d19bd194493aThomas Graf	rule->ce_mask |= RULE_ATTR_FAMILY;
54144d362409d5469aed47d19e7908d19bd194493aThomas Graf}
54244d362409d5469aed47d19e7908d19bd194493aThomas Graf
54344d362409d5469aed47d19e7908d19bd194493aThomas Grafint rtnl_rule_get_family(struct rtnl_rule *rule)
54444d362409d5469aed47d19e7908d19bd194493aThomas Graf{
54544d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (rule->ce_mask & RULE_ATTR_FAMILY)
54644d362409d5469aed47d19e7908d19bd194493aThomas Graf		return rule->r_family;
54744d362409d5469aed47d19e7908d19bd194493aThomas Graf	else
54844d362409d5469aed47d19e7908d19bd194493aThomas Graf		return AF_UNSPEC;
54944d362409d5469aed47d19e7908d19bd194493aThomas Graf}
55044d362409d5469aed47d19e7908d19bd194493aThomas Graf
551054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartvoid rtnl_rule_set_prio(struct rtnl_rule *rule, uint32_t prio)
55244d362409d5469aed47d19e7908d19bd194493aThomas Graf{
55344d362409d5469aed47d19e7908d19bd194493aThomas Graf	rule->r_prio = prio;
55444d362409d5469aed47d19e7908d19bd194493aThomas Graf	rule->ce_mask |= RULE_ATTR_PRIO;
55544d362409d5469aed47d19e7908d19bd194493aThomas Graf}
55644d362409d5469aed47d19e7908d19bd194493aThomas Graf
557054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartuint32_t rtnl_rule_get_prio(struct rtnl_rule *rule)
55844d362409d5469aed47d19e7908d19bd194493aThomas Graf{
559054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	return rule->r_prio;
56044d362409d5469aed47d19e7908d19bd194493aThomas Graf}
56144d362409d5469aed47d19e7908d19bd194493aThomas Graf
562054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartvoid rtnl_rule_set_mark(struct rtnl_rule *rule, uint32_t mark)
56344d362409d5469aed47d19e7908d19bd194493aThomas Graf{
56444d362409d5469aed47d19e7908d19bd194493aThomas Graf	rule->r_mark = mark;
56544d362409d5469aed47d19e7908d19bd194493aThomas Graf	rule->ce_mask |= RULE_ATTR_MARK;
56644d362409d5469aed47d19e7908d19bd194493aThomas Graf}
56744d362409d5469aed47d19e7908d19bd194493aThomas Graf
568054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartuint32_t rtnl_rule_get_mark(struct rtnl_rule *rule)
56944d362409d5469aed47d19e7908d19bd194493aThomas Graf{
570054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	return rule->r_mark;
57144d362409d5469aed47d19e7908d19bd194493aThomas Graf}
57244d362409d5469aed47d19e7908d19bd194493aThomas Graf
573054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartvoid rtnl_rule_set_mask(struct rtnl_rule *rule, uint32_t mask)
57444d362409d5469aed47d19e7908d19bd194493aThomas Graf{
575054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	rule->r_mask = mask;
576054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	rule->ce_mask |= RULE_ATTR_MASK;
57744d362409d5469aed47d19e7908d19bd194493aThomas Graf}
57844d362409d5469aed47d19e7908d19bd194493aThomas Graf
579054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartuint32_t rtnl_rule_get_mask(struct rtnl_rule *rule)
58044d362409d5469aed47d19e7908d19bd194493aThomas Graf{
581054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	return rule->r_mask;
58244d362409d5469aed47d19e7908d19bd194493aThomas Graf}
58344d362409d5469aed47d19e7908d19bd194493aThomas Graf
584054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartvoid rtnl_rule_set_table(struct rtnl_rule *rule, uint32_t table)
58544d362409d5469aed47d19e7908d19bd194493aThomas Graf{
586054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	rule->r_table = table;
587054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	rule->ce_mask |= RULE_ATTR_TABLE;
58844d362409d5469aed47d19e7908d19bd194493aThomas Graf}
58944d362409d5469aed47d19e7908d19bd194493aThomas Graf
590054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartuint32_t rtnl_rule_get_table(struct rtnl_rule *rule)
59144d362409d5469aed47d19e7908d19bd194493aThomas Graf{
592054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	return rule->r_table;
59344d362409d5469aed47d19e7908d19bd194493aThomas Graf}
59444d362409d5469aed47d19e7908d19bd194493aThomas Graf
595054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartvoid rtnl_rule_set_dsfield(struct rtnl_rule *rule, uint8_t dsfield)
59644d362409d5469aed47d19e7908d19bd194493aThomas Graf{
597054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	rule->r_dsfield = dsfield;
598054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	rule->ce_mask |= RULE_ATTR_DSFIELD;
59944d362409d5469aed47d19e7908d19bd194493aThomas Graf}
60044d362409d5469aed47d19e7908d19bd194493aThomas Graf
601054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartuint8_t rtnl_rule_get_dsfield(struct rtnl_rule *rule)
60244d362409d5469aed47d19e7908d19bd194493aThomas Graf{
603054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	return rule->r_dsfield;
60444d362409d5469aed47d19e7908d19bd194493aThomas Graf}
60544d362409d5469aed47d19e7908d19bd194493aThomas Graf
60644d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic inline int __assign_addr(struct rtnl_rule *rule, struct nl_addr **pos,
607054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart			        struct nl_addr *new, int flag)
60844d362409d5469aed47d19e7908d19bd194493aThomas Graf{
60944d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (rule->ce_mask & RULE_ATTR_FAMILY) {
61044d362409d5469aed47d19e7908d19bd194493aThomas Graf		if (new->a_family != rule->r_family)
6118a3efffa5b3fde252675239914118664d36a2c24Thomas Graf			return -NLE_AF_MISMATCH;
61244d362409d5469aed47d19e7908d19bd194493aThomas Graf	} else
61344d362409d5469aed47d19e7908d19bd194493aThomas Graf		rule->r_family = new->a_family;
61444d362409d5469aed47d19e7908d19bd194493aThomas Graf
61544d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (*pos)
61644d362409d5469aed47d19e7908d19bd194493aThomas Graf		nl_addr_put(*pos);
61744d362409d5469aed47d19e7908d19bd194493aThomas Graf
61844d362409d5469aed47d19e7908d19bd194493aThomas Graf	nl_addr_get(new);
61944d362409d5469aed47d19e7908d19bd194493aThomas Graf	*pos = new;
62044d362409d5469aed47d19e7908d19bd194493aThomas Graf
62144d362409d5469aed47d19e7908d19bd194493aThomas Graf	rule->ce_mask |= (flag | RULE_ATTR_FAMILY);
62244d362409d5469aed47d19e7908d19bd194493aThomas Graf
62344d362409d5469aed47d19e7908d19bd194493aThomas Graf	return 0;
62444d362409d5469aed47d19e7908d19bd194493aThomas Graf}
62544d362409d5469aed47d19e7908d19bd194493aThomas Graf
62644d362409d5469aed47d19e7908d19bd194493aThomas Grafint rtnl_rule_set_src(struct rtnl_rule *rule, struct nl_addr *src)
62744d362409d5469aed47d19e7908d19bd194493aThomas Graf{
628054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	return __assign_addr(rule, &rule->r_src, src, RULE_ATTR_SRC);
62944d362409d5469aed47d19e7908d19bd194493aThomas Graf}
63044d362409d5469aed47d19e7908d19bd194493aThomas Graf
63144d362409d5469aed47d19e7908d19bd194493aThomas Grafstruct nl_addr *rtnl_rule_get_src(struct rtnl_rule *rule)
63244d362409d5469aed47d19e7908d19bd194493aThomas Graf{
633054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	return rule->r_src;
63444d362409d5469aed47d19e7908d19bd194493aThomas Graf}
63544d362409d5469aed47d19e7908d19bd194493aThomas Graf
63644d362409d5469aed47d19e7908d19bd194493aThomas Grafint rtnl_rule_set_dst(struct rtnl_rule *rule, struct nl_addr *dst)
63744d362409d5469aed47d19e7908d19bd194493aThomas Graf{
638054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	return __assign_addr(rule, &rule->r_dst, dst, RULE_ATTR_DST);
63944d362409d5469aed47d19e7908d19bd194493aThomas Graf}
64044d362409d5469aed47d19e7908d19bd194493aThomas Graf
64144d362409d5469aed47d19e7908d19bd194493aThomas Grafstruct nl_addr *rtnl_rule_get_dst(struct rtnl_rule *rule)
64244d362409d5469aed47d19e7908d19bd194493aThomas Graf{
643054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	return rule->r_dst;
64444d362409d5469aed47d19e7908d19bd194493aThomas Graf}
64544d362409d5469aed47d19e7908d19bd194493aThomas Graf
64644d362409d5469aed47d19e7908d19bd194493aThomas Grafint rtnl_rule_set_iif(struct rtnl_rule *rule, const char *dev)
64744d362409d5469aed47d19e7908d19bd194493aThomas Graf{
64844d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (strlen(dev) > IFNAMSIZ-1)
6498a3efffa5b3fde252675239914118664d36a2c24Thomas Graf		return -NLE_RANGE;
65044d362409d5469aed47d19e7908d19bd194493aThomas Graf
651054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	strcpy(rule->r_iifname, dev);
652054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	rule->ce_mask |= RULE_ATTR_IIFNAME;
65344d362409d5469aed47d19e7908d19bd194493aThomas Graf	return 0;
65444d362409d5469aed47d19e7908d19bd194493aThomas Graf}
65544d362409d5469aed47d19e7908d19bd194493aThomas Graf
65644d362409d5469aed47d19e7908d19bd194493aThomas Grafchar *rtnl_rule_get_iif(struct rtnl_rule *rule)
65744d362409d5469aed47d19e7908d19bd194493aThomas Graf{
658054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	if (rule->ce_mask & RULE_ATTR_IIFNAME)
659054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		return rule->r_iifname;
66044d362409d5469aed47d19e7908d19bd194493aThomas Graf	else
66144d362409d5469aed47d19e7908d19bd194493aThomas Graf		return NULL;
66244d362409d5469aed47d19e7908d19bd194493aThomas Graf}
66344d362409d5469aed47d19e7908d19bd194493aThomas Graf
664054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartint rtnl_rule_set_oif(struct rtnl_rule *rule, const char *dev)
66544d362409d5469aed47d19e7908d19bd194493aThomas Graf{
666054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	if (strlen(dev) > IFNAMSIZ-1)
667054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		return -NLE_RANGE;
668054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
669054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	strcpy(rule->r_oifname, dev);
670054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	rule->ce_mask |= RULE_ATTR_OIFNAME;
671054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	return 0;
67244d362409d5469aed47d19e7908d19bd194493aThomas Graf}
67344d362409d5469aed47d19e7908d19bd194493aThomas Graf
674054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartchar *rtnl_rule_get_oif(struct rtnl_rule *rule)
67544d362409d5469aed47d19e7908d19bd194493aThomas Graf{
676054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	if (rule->ce_mask & RULE_ATTR_OIFNAME)
677054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		return rule->r_oifname;
67844d362409d5469aed47d19e7908d19bd194493aThomas Graf	else
679054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart		return NULL;
680054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart}
681054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
682054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartvoid rtnl_rule_set_action(struct rtnl_rule *rule, uint8_t action)
683054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart{
684054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	rule->r_action = action;
685054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	rule->ce_mask |= RULE_ATTR_ACTION;
686054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart}
687054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
688054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartuint8_t rtnl_rule_get_action(struct rtnl_rule *rule)
689054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart{
690054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	return rule->r_action;
69144d362409d5469aed47d19e7908d19bd194493aThomas Graf}
69244d362409d5469aed47d19e7908d19bd194493aThomas Graf
693535e83162249ed6274ba46bc72d8cc683ba20e17Thomas Grafvoid rtnl_rule_set_realms(struct rtnl_rule *rule, uint32_t realms)
69444d362409d5469aed47d19e7908d19bd194493aThomas Graf{
695054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	rule->r_flow = realms;
696054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	rule->ce_mask |= RULE_ATTR_FLOW;
69744d362409d5469aed47d19e7908d19bd194493aThomas Graf}
69844d362409d5469aed47d19e7908d19bd194493aThomas Graf
699535e83162249ed6274ba46bc72d8cc683ba20e17Thomas Grafuint32_t rtnl_rule_get_realms(struct rtnl_rule *rule)
70044d362409d5469aed47d19e7908d19bd194493aThomas Graf{
701054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	return rule->r_flow;
702054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart}
703054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
704054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartvoid rtnl_rule_set_goto(struct rtnl_rule *rule, uint32_t ref)
705054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart{
706054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	rule->r_goto = ref;
707054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	rule->ce_mask |= RULE_ATTR_GOTO;
708054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart}
709054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart
710054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewartuint32_t rtnl_rule_get_goto(struct rtnl_rule *rule)
711054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart{
712054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	return rule->r_goto;
71344d362409d5469aed47d19e7908d19bd194493aThomas Graf}
71444d362409d5469aed47d19e7908d19bd194493aThomas Graf
71544d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */
71644d362409d5469aed47d19e7908d19bd194493aThomas Graf
71744d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct nl_object_ops rule_obj_ops = {
71844d362409d5469aed47d19e7908d19bd194493aThomas Graf	.oo_name		= "route/rule",
71944d362409d5469aed47d19e7908d19bd194493aThomas Graf	.oo_size		= sizeof(struct rtnl_rule),
72044d362409d5469aed47d19e7908d19bd194493aThomas Graf	.oo_free_data		= rule_free_data,
72144d362409d5469aed47d19e7908d19bd194493aThomas Graf	.oo_clone		= rule_clone,
722d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf	.oo_dump = {
723d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf	    [NL_DUMP_LINE]	= rule_dump_line,
724d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf	    [NL_DUMP_DETAILS]	= rule_dump_details,
725d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf	    [NL_DUMP_STATS]	= rule_dump_stats,
726d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf	},
72744d362409d5469aed47d19e7908d19bd194493aThomas Graf	.oo_compare		= rule_compare,
72844d362409d5469aed47d19e7908d19bd194493aThomas Graf	.oo_attrs2str		= rule_attrs2str,
72944d362409d5469aed47d19e7908d19bd194493aThomas Graf	.oo_id_attrs		= ~0,
73044d362409d5469aed47d19e7908d19bd194493aThomas Graf};
73144d362409d5469aed47d19e7908d19bd194493aThomas Graf
73244d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct nl_cache_ops rtnl_rule_ops = {
73344d362409d5469aed47d19e7908d19bd194493aThomas Graf	.co_name		= "route/rule",
734054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart	.co_hdrsize		= sizeof(struct fib_rule_hdr),
73544d362409d5469aed47d19e7908d19bd194493aThomas Graf	.co_msgtypes		= {
73644d362409d5469aed47d19e7908d19bd194493aThomas Graf					{ RTM_NEWRULE, NL_ACT_NEW, "new" },
73744d362409d5469aed47d19e7908d19bd194493aThomas Graf					{ RTM_DELRULE, NL_ACT_DEL, "del" },
73844d362409d5469aed47d19e7908d19bd194493aThomas Graf					{ RTM_GETRULE, NL_ACT_GET, "get" },
73944d362409d5469aed47d19e7908d19bd194493aThomas Graf					END_OF_MSGTYPES_LIST,
74044d362409d5469aed47d19e7908d19bd194493aThomas Graf				  },
74144d362409d5469aed47d19e7908d19bd194493aThomas Graf	.co_protocol		= NETLINK_ROUTE,
74244d362409d5469aed47d19e7908d19bd194493aThomas Graf	.co_request_update	= rule_request_update,
74344d362409d5469aed47d19e7908d19bd194493aThomas Graf	.co_msg_parser		= rule_msg_parser,
74444d362409d5469aed47d19e7908d19bd194493aThomas Graf	.co_obj_ops		= &rule_obj_ops,
74544d362409d5469aed47d19e7908d19bd194493aThomas Graf};
74644d362409d5469aed47d19e7908d19bd194493aThomas Graf
74744d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic void __init rule_init(void)
74844d362409d5469aed47d19e7908d19bd194493aThomas Graf{
74944d362409d5469aed47d19e7908d19bd194493aThomas Graf	nl_cache_mngt_register(&rtnl_rule_ops);
75044d362409d5469aed47d19e7908d19bd194493aThomas Graf}
75144d362409d5469aed47d19e7908d19bd194493aThomas Graf
75244d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic void __exit rule_exit(void)
75344d362409d5469aed47d19e7908d19bd194493aThomas Graf{
75444d362409d5469aed47d19e7908d19bd194493aThomas Graf	nl_cache_mngt_unregister(&rtnl_rule_ops);
75544d362409d5469aed47d19e7908d19bd194493aThomas Graf}
75644d362409d5469aed47d19e7908d19bd194493aThomas Graf
75744d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */
758