xref: /aosp_15_r20/external/libnl/lib/route/rule.c (revision 4dc78e53d49367fa8e61b07018507c90983a077d)
1*4dc78e53SAndroid Build Coastguard Worker /* SPDX-License-Identifier: LGPL-2.1-only */
2*4dc78e53SAndroid Build Coastguard Worker /*
3*4dc78e53SAndroid Build Coastguard Worker  * Copyright (c) 2003-2010 Thomas Graf <[email protected]>
4*4dc78e53SAndroid Build Coastguard Worker  */
5*4dc78e53SAndroid Build Coastguard Worker 
6*4dc78e53SAndroid Build Coastguard Worker /**
7*4dc78e53SAndroid Build Coastguard Worker  * @ingroup rtnl
8*4dc78e53SAndroid Build Coastguard Worker  * @defgroup rule Routing Rules
9*4dc78e53SAndroid Build Coastguard Worker  * @brief
10*4dc78e53SAndroid Build Coastguard Worker  * @{
11*4dc78e53SAndroid Build Coastguard Worker  */
12*4dc78e53SAndroid Build Coastguard Worker 
13*4dc78e53SAndroid Build Coastguard Worker #include "nl-default.h"
14*4dc78e53SAndroid Build Coastguard Worker 
15*4dc78e53SAndroid Build Coastguard Worker #include <linux/fib_rules.h>
16*4dc78e53SAndroid Build Coastguard Worker 
17*4dc78e53SAndroid Build Coastguard Worker #include <netlink/netlink.h>
18*4dc78e53SAndroid Build Coastguard Worker #include <netlink/utils.h>
19*4dc78e53SAndroid Build Coastguard Worker #include <netlink/route/rtnl.h>
20*4dc78e53SAndroid Build Coastguard Worker #include <netlink/route/rule.h>
21*4dc78e53SAndroid Build Coastguard Worker 
22*4dc78e53SAndroid Build Coastguard Worker #include "nl-route.h"
23*4dc78e53SAndroid Build Coastguard Worker #include "nl-priv-dynamic-core/nl-core.h"
24*4dc78e53SAndroid Build Coastguard Worker #include "nl-priv-dynamic-core/cache-api.h"
25*4dc78e53SAndroid Build Coastguard Worker 
26*4dc78e53SAndroid Build Coastguard Worker /** @cond SKIP */
27*4dc78e53SAndroid Build Coastguard Worker struct rtnl_rule {
28*4dc78e53SAndroid Build Coastguard Worker 	NLHDR_COMMON
29*4dc78e53SAndroid Build Coastguard Worker 	uint8_t r_family;
30*4dc78e53SAndroid Build Coastguard Worker 	uint8_t r_action;
31*4dc78e53SAndroid Build Coastguard Worker 	uint8_t r_dsfield; /* ipv4 only */
32*4dc78e53SAndroid Build Coastguard Worker 	uint8_t r_l3mdev;
33*4dc78e53SAndroid Build Coastguard Worker 	uint8_t r_protocol; /* protocol that installed rule */
34*4dc78e53SAndroid Build Coastguard Worker 	uint8_t r_ip_proto; /* IP/IPv6 protocol */
35*4dc78e53SAndroid Build Coastguard Worker 	uint32_t r_table;
36*4dc78e53SAndroid Build Coastguard Worker 	uint32_t r_flags;
37*4dc78e53SAndroid Build Coastguard Worker 	uint32_t r_prio;
38*4dc78e53SAndroid Build Coastguard Worker 	uint32_t r_mark;
39*4dc78e53SAndroid Build Coastguard Worker 	uint32_t r_mask;
40*4dc78e53SAndroid Build Coastguard Worker 	uint32_t r_goto;
41*4dc78e53SAndroid Build Coastguard Worker 	uint32_t r_flow; /* ipv4 only */
42*4dc78e53SAndroid Build Coastguard Worker 	struct nl_addr *r_src;
43*4dc78e53SAndroid Build Coastguard Worker 	struct nl_addr *r_dst;
44*4dc78e53SAndroid Build Coastguard Worker 	char r_iifname[IFNAMSIZ];
45*4dc78e53SAndroid Build Coastguard Worker 	char r_oifname[IFNAMSIZ];
46*4dc78e53SAndroid Build Coastguard Worker 
47*4dc78e53SAndroid Build Coastguard Worker 	struct fib_rule_port_range r_sport;
48*4dc78e53SAndroid Build Coastguard Worker 	struct fib_rule_port_range r_dport;
49*4dc78e53SAndroid Build Coastguard Worker };
50*4dc78e53SAndroid Build Coastguard Worker 
51*4dc78e53SAndroid Build Coastguard Worker #define RULE_ATTR_FAMILY	0x000001
52*4dc78e53SAndroid Build Coastguard Worker #define RULE_ATTR_TABLE		0x000002
53*4dc78e53SAndroid Build Coastguard Worker #define RULE_ATTR_ACTION	0x000004
54*4dc78e53SAndroid Build Coastguard Worker #define RULE_ATTR_FLAGS		0x000008
55*4dc78e53SAndroid Build Coastguard Worker #define RULE_ATTR_IIFNAME	0x000010
56*4dc78e53SAndroid Build Coastguard Worker #define RULE_ATTR_OIFNAME	0x000020
57*4dc78e53SAndroid Build Coastguard Worker #define RULE_ATTR_PRIO		0x000040
58*4dc78e53SAndroid Build Coastguard Worker #define RULE_ATTR_MARK		0x000080
59*4dc78e53SAndroid Build Coastguard Worker #define RULE_ATTR_MASK		0x000100
60*4dc78e53SAndroid Build Coastguard Worker #define RULE_ATTR_GOTO		0x000200
61*4dc78e53SAndroid Build Coastguard Worker #define RULE_ATTR_SRC		0x000400
62*4dc78e53SAndroid Build Coastguard Worker #define RULE_ATTR_DST		0x000800
63*4dc78e53SAndroid Build Coastguard Worker #define RULE_ATTR_DSFIELD	0x001000
64*4dc78e53SAndroid Build Coastguard Worker #define RULE_ATTR_FLOW		0x002000
65*4dc78e53SAndroid Build Coastguard Worker #define RULE_ATTR_L3MDEV	0x004000
66*4dc78e53SAndroid Build Coastguard Worker #define RULE_ATTR_PROTOCOL	0x008000
67*4dc78e53SAndroid Build Coastguard Worker #define RULE_ATTR_IP_PROTO	0x010000
68*4dc78e53SAndroid Build Coastguard Worker #define RULE_ATTR_SPORT		0x020000
69*4dc78e53SAndroid Build Coastguard Worker #define RULE_ATTR_DPORT		0x040000
70*4dc78e53SAndroid Build Coastguard Worker 
71*4dc78e53SAndroid Build Coastguard Worker static struct nl_cache_ops rtnl_rule_ops;
72*4dc78e53SAndroid Build Coastguard Worker static struct nl_object_ops rule_obj_ops;
73*4dc78e53SAndroid Build Coastguard Worker /** @endcond */
74*4dc78e53SAndroid Build Coastguard Worker 
rule_free_data(struct nl_object * c)75*4dc78e53SAndroid Build Coastguard Worker static void rule_free_data(struct nl_object *c)
76*4dc78e53SAndroid Build Coastguard Worker {
77*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_rule *rule = nl_object_priv(c);
78*4dc78e53SAndroid Build Coastguard Worker 
79*4dc78e53SAndroid Build Coastguard Worker 	if (!rule)
80*4dc78e53SAndroid Build Coastguard Worker 		return;
81*4dc78e53SAndroid Build Coastguard Worker 
82*4dc78e53SAndroid Build Coastguard Worker 	nl_addr_put(rule->r_src);
83*4dc78e53SAndroid Build Coastguard Worker 	nl_addr_put(rule->r_dst);
84*4dc78e53SAndroid Build Coastguard Worker }
85*4dc78e53SAndroid Build Coastguard Worker 
rule_clone(struct nl_object * _dst,struct nl_object * _src)86*4dc78e53SAndroid Build Coastguard Worker static int rule_clone(struct nl_object *_dst, struct nl_object *_src)
87*4dc78e53SAndroid Build Coastguard Worker {
88*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_rule *dst = nl_object_priv(_dst);
89*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_rule *src = nl_object_priv(_src);
90*4dc78e53SAndroid Build Coastguard Worker 
91*4dc78e53SAndroid Build Coastguard Worker 	dst->r_src = NULL;
92*4dc78e53SAndroid Build Coastguard Worker 	dst->r_dst = NULL;
93*4dc78e53SAndroid Build Coastguard Worker 
94*4dc78e53SAndroid Build Coastguard Worker 	if (src->r_src)
95*4dc78e53SAndroid Build Coastguard Worker 		if (!(dst->r_src = nl_addr_clone(src->r_src)))
96*4dc78e53SAndroid Build Coastguard Worker 			return -NLE_NOMEM;
97*4dc78e53SAndroid Build Coastguard Worker 
98*4dc78e53SAndroid Build Coastguard Worker 	if (src->r_dst)
99*4dc78e53SAndroid Build Coastguard Worker 		if (!(dst->r_dst = nl_addr_clone(src->r_dst)))
100*4dc78e53SAndroid Build Coastguard Worker 			return -NLE_NOMEM;
101*4dc78e53SAndroid Build Coastguard Worker 
102*4dc78e53SAndroid Build Coastguard Worker 	return 0;
103*4dc78e53SAndroid Build Coastguard Worker }
104*4dc78e53SAndroid Build Coastguard Worker 
105*4dc78e53SAndroid Build Coastguard Worker static struct nla_policy rule_policy[FRA_MAX+1] = {
106*4dc78e53SAndroid Build Coastguard Worker 	[FRA_TABLE]	= { .type = NLA_U32 },
107*4dc78e53SAndroid Build Coastguard Worker 	[FRA_IIFNAME]	= { .type = NLA_STRING, .maxlen = IFNAMSIZ },
108*4dc78e53SAndroid Build Coastguard Worker 	[FRA_OIFNAME]	= { .type = NLA_STRING, .maxlen = IFNAMSIZ },
109*4dc78e53SAndroid Build Coastguard Worker 	[FRA_PRIORITY]	= { .type = NLA_U32 },
110*4dc78e53SAndroid Build Coastguard Worker 	[FRA_FWMARK]	= { .type = NLA_U32 },
111*4dc78e53SAndroid Build Coastguard Worker 	[FRA_FWMASK]	= { .type = NLA_U32 },
112*4dc78e53SAndroid Build Coastguard Worker 	[FRA_GOTO]	= { .type = NLA_U32 },
113*4dc78e53SAndroid Build Coastguard Worker 	[FRA_FLOW]	= { .type = NLA_U32 },
114*4dc78e53SAndroid Build Coastguard Worker 	[FRA_L3MDEV]	= { .type = NLA_U8 },
115*4dc78e53SAndroid Build Coastguard Worker 	[FRA_PROTOCOL]	= { .type = NLA_U8 },
116*4dc78e53SAndroid Build Coastguard Worker 	[FRA_IP_PROTO]	= { .type = NLA_U8 },
117*4dc78e53SAndroid Build Coastguard Worker 	[FRA_SPORT_RANGE] = { .minlen = sizeof(struct fib_rule_port_range),
118*4dc78e53SAndroid Build Coastguard Worker 			      .maxlen = sizeof(struct fib_rule_port_range) },
119*4dc78e53SAndroid Build Coastguard Worker 	[FRA_DPORT_RANGE] = { .minlen = sizeof(struct fib_rule_port_range),
120*4dc78e53SAndroid Build Coastguard Worker 			      .maxlen = sizeof(struct fib_rule_port_range) },
121*4dc78e53SAndroid Build Coastguard Worker };
122*4dc78e53SAndroid Build Coastguard Worker 
rule_msg_parser(struct nl_cache_ops * ops,struct sockaddr_nl * who,struct nlmsghdr * n,struct nl_parser_param * pp)123*4dc78e53SAndroid Build Coastguard Worker static int rule_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
124*4dc78e53SAndroid Build Coastguard Worker 			   struct nlmsghdr *n, struct nl_parser_param *pp)
125*4dc78e53SAndroid Build Coastguard Worker {
126*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_rule *rule;
127*4dc78e53SAndroid Build Coastguard Worker 	struct fib_rule_hdr *frh;
128*4dc78e53SAndroid Build Coastguard Worker 	struct nlattr *tb[FRA_MAX+1];
129*4dc78e53SAndroid Build Coastguard Worker 	int err = 1, family;
130*4dc78e53SAndroid Build Coastguard Worker 
131*4dc78e53SAndroid Build Coastguard Worker 	rule = rtnl_rule_alloc();
132*4dc78e53SAndroid Build Coastguard Worker 	if (!rule) {
133*4dc78e53SAndroid Build Coastguard Worker 		err = -NLE_NOMEM;
134*4dc78e53SAndroid Build Coastguard Worker 		goto errout;
135*4dc78e53SAndroid Build Coastguard Worker 	}
136*4dc78e53SAndroid Build Coastguard Worker 
137*4dc78e53SAndroid Build Coastguard Worker 	rule->ce_msgtype = n->nlmsg_type;
138*4dc78e53SAndroid Build Coastguard Worker 	frh = nlmsg_data(n);
139*4dc78e53SAndroid Build Coastguard Worker 
140*4dc78e53SAndroid Build Coastguard Worker 	err = nlmsg_parse(n, sizeof(*frh), tb, FRA_MAX, rule_policy);
141*4dc78e53SAndroid Build Coastguard Worker 	if (err < 0)
142*4dc78e53SAndroid Build Coastguard Worker 		goto errout;
143*4dc78e53SAndroid Build Coastguard Worker 
144*4dc78e53SAndroid Build Coastguard Worker 	rule->r_family = family = frh->family;
145*4dc78e53SAndroid Build Coastguard Worker 	rule->r_table = frh->table;
146*4dc78e53SAndroid Build Coastguard Worker 	rule->r_action = frh->action;
147*4dc78e53SAndroid Build Coastguard Worker 	rule->r_flags = frh->flags;
148*4dc78e53SAndroid Build Coastguard Worker 
149*4dc78e53SAndroid Build Coastguard Worker 	rule->ce_mask = (RULE_ATTR_FAMILY | RULE_ATTR_ACTION | RULE_ATTR_FLAGS);
150*4dc78e53SAndroid Build Coastguard Worker 	if (rule->r_table)
151*4dc78e53SAndroid Build Coastguard Worker 		rule->ce_mask |= RULE_ATTR_TABLE;
152*4dc78e53SAndroid Build Coastguard Worker 
153*4dc78e53SAndroid Build Coastguard Worker 	/* ipv4 only */
154*4dc78e53SAndroid Build Coastguard Worker 	if (frh->tos) {
155*4dc78e53SAndroid Build Coastguard Worker 		rule->r_dsfield = frh->tos;
156*4dc78e53SAndroid Build Coastguard Worker 		rule->ce_mask |= RULE_ATTR_DSFIELD;
157*4dc78e53SAndroid Build Coastguard Worker 	}
158*4dc78e53SAndroid Build Coastguard Worker 
159*4dc78e53SAndroid Build Coastguard Worker 	if (tb[FRA_TABLE]) {
160*4dc78e53SAndroid Build Coastguard Worker 		rule->r_table = nla_get_u32(tb[FRA_TABLE]);
161*4dc78e53SAndroid Build Coastguard Worker 		if (rule->r_table)
162*4dc78e53SAndroid Build Coastguard Worker 			rule->ce_mask |= RULE_ATTR_TABLE;
163*4dc78e53SAndroid Build Coastguard Worker 	}
164*4dc78e53SAndroid Build Coastguard Worker 
165*4dc78e53SAndroid Build Coastguard Worker 	if (tb[FRA_IIFNAME]) {
166*4dc78e53SAndroid Build Coastguard Worker 		nla_strlcpy(rule->r_iifname, tb[FRA_IIFNAME], IFNAMSIZ);
167*4dc78e53SAndroid Build Coastguard Worker 		rule->ce_mask |= RULE_ATTR_IIFNAME;
168*4dc78e53SAndroid Build Coastguard Worker 	}
169*4dc78e53SAndroid Build Coastguard Worker 
170*4dc78e53SAndroid Build Coastguard Worker 	if (tb[FRA_OIFNAME]) {
171*4dc78e53SAndroid Build Coastguard Worker 		nla_strlcpy(rule->r_oifname, tb[FRA_OIFNAME], IFNAMSIZ);
172*4dc78e53SAndroid Build Coastguard Worker 		rule->ce_mask |= RULE_ATTR_OIFNAME;
173*4dc78e53SAndroid Build Coastguard Worker 	}
174*4dc78e53SAndroid Build Coastguard Worker 
175*4dc78e53SAndroid Build Coastguard Worker 	if (tb[FRA_PRIORITY]) {
176*4dc78e53SAndroid Build Coastguard Worker 		rule->r_prio = nla_get_u32(tb[FRA_PRIORITY]);
177*4dc78e53SAndroid Build Coastguard Worker 		rule->ce_mask |= RULE_ATTR_PRIO;
178*4dc78e53SAndroid Build Coastguard Worker 	}
179*4dc78e53SAndroid Build Coastguard Worker 
180*4dc78e53SAndroid Build Coastguard Worker 	if (tb[FRA_FWMARK]) {
181*4dc78e53SAndroid Build Coastguard Worker 		rule->r_mark = nla_get_u32(tb[FRA_FWMARK]);
182*4dc78e53SAndroid Build Coastguard Worker 		rule->ce_mask |= RULE_ATTR_MARK;
183*4dc78e53SAndroid Build Coastguard Worker 	}
184*4dc78e53SAndroid Build Coastguard Worker 
185*4dc78e53SAndroid Build Coastguard Worker 	if (tb[FRA_FWMASK]) {
186*4dc78e53SAndroid Build Coastguard Worker 		rule->r_mask = nla_get_u32(tb[FRA_FWMASK]);
187*4dc78e53SAndroid Build Coastguard Worker 		rule->ce_mask |= RULE_ATTR_MASK;
188*4dc78e53SAndroid Build Coastguard Worker 	}
189*4dc78e53SAndroid Build Coastguard Worker 
190*4dc78e53SAndroid Build Coastguard Worker 	if (tb[FRA_GOTO]) {
191*4dc78e53SAndroid Build Coastguard Worker 		rule->r_goto = nla_get_u32(tb[FRA_GOTO]);
192*4dc78e53SAndroid Build Coastguard Worker 		rule->ce_mask |= RULE_ATTR_GOTO;
193*4dc78e53SAndroid Build Coastguard Worker 	}
194*4dc78e53SAndroid Build Coastguard Worker 
195*4dc78e53SAndroid Build Coastguard Worker 	if (tb[FRA_SRC]) {
196*4dc78e53SAndroid Build Coastguard Worker 		if (!(rule->r_src = nl_addr_alloc_attr(tb[FRA_SRC], family)))
197*4dc78e53SAndroid Build Coastguard Worker 			goto errout_enomem;
198*4dc78e53SAndroid Build Coastguard Worker 
199*4dc78e53SAndroid Build Coastguard Worker 		nl_addr_set_prefixlen(rule->r_src, frh->src_len);
200*4dc78e53SAndroid Build Coastguard Worker 		rule->ce_mask |= RULE_ATTR_SRC;
201*4dc78e53SAndroid Build Coastguard Worker 	}
202*4dc78e53SAndroid Build Coastguard Worker 
203*4dc78e53SAndroid Build Coastguard Worker 	if (tb[FRA_DST]) {
204*4dc78e53SAndroid Build Coastguard Worker 		if (!(rule->r_dst = nl_addr_alloc_attr(tb[FRA_DST], family)))
205*4dc78e53SAndroid Build Coastguard Worker 			goto errout_enomem;
206*4dc78e53SAndroid Build Coastguard Worker 		nl_addr_set_prefixlen(rule->r_dst, frh->dst_len);
207*4dc78e53SAndroid Build Coastguard Worker 		rule->ce_mask |= RULE_ATTR_DST;
208*4dc78e53SAndroid Build Coastguard Worker 	}
209*4dc78e53SAndroid Build Coastguard Worker 
210*4dc78e53SAndroid Build Coastguard Worker 	/* ipv4 only */
211*4dc78e53SAndroid Build Coastguard Worker 	if (tb[FRA_FLOW]) {
212*4dc78e53SAndroid Build Coastguard Worker 		rule->r_flow = nla_get_u32(tb[FRA_FLOW]);
213*4dc78e53SAndroid Build Coastguard Worker 		rule->ce_mask |= RULE_ATTR_FLOW;
214*4dc78e53SAndroid Build Coastguard Worker 	}
215*4dc78e53SAndroid Build Coastguard Worker 
216*4dc78e53SAndroid Build Coastguard Worker 	if (tb[FRA_L3MDEV]) {
217*4dc78e53SAndroid Build Coastguard Worker 		rule->r_l3mdev = nla_get_u8(tb[FRA_L3MDEV]);
218*4dc78e53SAndroid Build Coastguard Worker 		rule->ce_mask |= RULE_ATTR_L3MDEV;
219*4dc78e53SAndroid Build Coastguard Worker 	}
220*4dc78e53SAndroid Build Coastguard Worker 
221*4dc78e53SAndroid Build Coastguard Worker 	if (tb[FRA_PROTOCOL]) {
222*4dc78e53SAndroid Build Coastguard Worker 		rule->r_protocol = nla_get_u8(tb[FRA_PROTOCOL]);
223*4dc78e53SAndroid Build Coastguard Worker 		rule->ce_mask |= RULE_ATTR_PROTOCOL;
224*4dc78e53SAndroid Build Coastguard Worker 	}
225*4dc78e53SAndroid Build Coastguard Worker 
226*4dc78e53SAndroid Build Coastguard Worker 	if (tb[FRA_IP_PROTO]) {
227*4dc78e53SAndroid Build Coastguard Worker 		rule->r_ip_proto = nla_get_u8(tb[FRA_IP_PROTO]);
228*4dc78e53SAndroid Build Coastguard Worker 		rule->ce_mask |= RULE_ATTR_IP_PROTO;
229*4dc78e53SAndroid Build Coastguard Worker 	}
230*4dc78e53SAndroid Build Coastguard Worker 
231*4dc78e53SAndroid Build Coastguard Worker 	if (tb[FRA_SPORT_RANGE]) {
232*4dc78e53SAndroid Build Coastguard Worker 		struct fib_rule_port_range *pr;
233*4dc78e53SAndroid Build Coastguard Worker 
234*4dc78e53SAndroid Build Coastguard Worker 		pr = nla_data(tb[FRA_SPORT_RANGE]);
235*4dc78e53SAndroid Build Coastguard Worker 		rule->r_sport = *pr;
236*4dc78e53SAndroid Build Coastguard Worker 		rule->ce_mask |= RULE_ATTR_SPORT;
237*4dc78e53SAndroid Build Coastguard Worker 	}
238*4dc78e53SAndroid Build Coastguard Worker 
239*4dc78e53SAndroid Build Coastguard Worker 	if (tb[FRA_DPORT_RANGE]) {
240*4dc78e53SAndroid Build Coastguard Worker 		struct fib_rule_port_range *pr;
241*4dc78e53SAndroid Build Coastguard Worker 
242*4dc78e53SAndroid Build Coastguard Worker 		pr = nla_data(tb[FRA_DPORT_RANGE]);
243*4dc78e53SAndroid Build Coastguard Worker 		rule->r_dport = *pr;
244*4dc78e53SAndroid Build Coastguard Worker 		rule->ce_mask |= RULE_ATTR_DPORT;
245*4dc78e53SAndroid Build Coastguard Worker 	}
246*4dc78e53SAndroid Build Coastguard Worker 
247*4dc78e53SAndroid Build Coastguard Worker 	err = pp->pp_cb((struct nl_object *) rule, pp);
248*4dc78e53SAndroid Build Coastguard Worker errout:
249*4dc78e53SAndroid Build Coastguard Worker 	rtnl_rule_put(rule);
250*4dc78e53SAndroid Build Coastguard Worker 	return err;
251*4dc78e53SAndroid Build Coastguard Worker 
252*4dc78e53SAndroid Build Coastguard Worker errout_enomem:
253*4dc78e53SAndroid Build Coastguard Worker 	err = -NLE_NOMEM;
254*4dc78e53SAndroid Build Coastguard Worker 	goto errout;
255*4dc78e53SAndroid Build Coastguard Worker }
256*4dc78e53SAndroid Build Coastguard Worker 
rule_request_update(struct nl_cache * c,struct nl_sock * h)257*4dc78e53SAndroid Build Coastguard Worker static int rule_request_update(struct nl_cache *c, struct nl_sock *h)
258*4dc78e53SAndroid Build Coastguard Worker {
259*4dc78e53SAndroid Build Coastguard Worker 	return nl_rtgen_request(h, RTM_GETRULE, AF_UNSPEC, NLM_F_DUMP);
260*4dc78e53SAndroid Build Coastguard Worker }
261*4dc78e53SAndroid Build Coastguard Worker 
rule_dump_line(struct nl_object * o,struct nl_dump_params * p)262*4dc78e53SAndroid Build Coastguard Worker static void rule_dump_line(struct nl_object *o, struct nl_dump_params *p)
263*4dc78e53SAndroid Build Coastguard Worker {
264*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_rule *r = (struct rtnl_rule *) o;
265*4dc78e53SAndroid Build Coastguard Worker 	char buf[128];
266*4dc78e53SAndroid Build Coastguard Worker 
267*4dc78e53SAndroid Build Coastguard Worker 	nl_dump_line(p, "%8d ", (r->ce_mask & RULE_ATTR_PRIO) ? r->r_prio : 0);
268*4dc78e53SAndroid Build Coastguard Worker 	nl_dump(p, "%s ", nl_af2str(r->r_family, buf, sizeof(buf)));
269*4dc78e53SAndroid Build Coastguard Worker 
270*4dc78e53SAndroid Build Coastguard Worker 	if (r->ce_mask & RULE_ATTR_SRC)
271*4dc78e53SAndroid Build Coastguard Worker 		nl_dump(p, "from %s ",
272*4dc78e53SAndroid Build Coastguard Worker 			nl_addr2str(r->r_src, buf, sizeof(buf)));
273*4dc78e53SAndroid Build Coastguard Worker 
274*4dc78e53SAndroid Build Coastguard Worker 	if (r->ce_mask & RULE_ATTR_DST)
275*4dc78e53SAndroid Build Coastguard Worker 		nl_dump(p, "to %s ",
276*4dc78e53SAndroid Build Coastguard Worker 			nl_addr2str(r->r_dst, buf, sizeof(buf)));
277*4dc78e53SAndroid Build Coastguard Worker 
278*4dc78e53SAndroid Build Coastguard Worker 	if (r->ce_mask & RULE_ATTR_DSFIELD)
279*4dc78e53SAndroid Build Coastguard Worker 		nl_dump(p, "tos %u ", r->r_dsfield);
280*4dc78e53SAndroid Build Coastguard Worker 
281*4dc78e53SAndroid Build Coastguard Worker 	if (r->ce_mask & (RULE_ATTR_MARK | RULE_ATTR_MASK))
282*4dc78e53SAndroid Build Coastguard Worker 		nl_dump(p, "mark %#x/%#x", r->r_mark, r->r_mask);
283*4dc78e53SAndroid Build Coastguard Worker 
284*4dc78e53SAndroid Build Coastguard Worker 	if (r->ce_mask & RULE_ATTR_IIFNAME)
285*4dc78e53SAndroid Build Coastguard Worker 		nl_dump(p, "iif %s ", r->r_iifname);
286*4dc78e53SAndroid Build Coastguard Worker 
287*4dc78e53SAndroid Build Coastguard Worker 	if (r->ce_mask & RULE_ATTR_OIFNAME)
288*4dc78e53SAndroid Build Coastguard Worker 		nl_dump(p, "oif %s ", r->r_oifname);
289*4dc78e53SAndroid Build Coastguard Worker 
290*4dc78e53SAndroid Build Coastguard Worker 	if (r->ce_mask & RULE_ATTR_TABLE)
291*4dc78e53SAndroid Build Coastguard Worker 		nl_dump(p, "lookup %s ",
292*4dc78e53SAndroid Build Coastguard Worker 			rtnl_route_table2str(r->r_table, buf, sizeof(buf)));
293*4dc78e53SAndroid Build Coastguard Worker 
294*4dc78e53SAndroid Build Coastguard Worker 	if (r->ce_mask & RULE_ATTR_L3MDEV)
295*4dc78e53SAndroid Build Coastguard Worker 		nl_dump(p, "lookup [l3mdev-table] ");
296*4dc78e53SAndroid Build Coastguard Worker 
297*4dc78e53SAndroid Build Coastguard Worker 	if (r->ce_mask & RULE_ATTR_IP_PROTO)
298*4dc78e53SAndroid Build Coastguard Worker 		nl_dump(p, "ipproto %s ",
299*4dc78e53SAndroid Build Coastguard Worker 			nl_ip_proto2str(r->r_ip_proto, buf, sizeof(buf)));
300*4dc78e53SAndroid Build Coastguard Worker 
301*4dc78e53SAndroid Build Coastguard Worker 	if (r->ce_mask & RULE_ATTR_SPORT) {
302*4dc78e53SAndroid Build Coastguard Worker 		if (r->r_sport.start == r->r_sport.end)
303*4dc78e53SAndroid Build Coastguard Worker 			nl_dump(p, "sport %u ", r->r_sport.start);
304*4dc78e53SAndroid Build Coastguard Worker 		else
305*4dc78e53SAndroid Build Coastguard Worker 			nl_dump(p, "sport %u-%u ",
306*4dc78e53SAndroid Build Coastguard Worker 				r->r_sport.start, r->r_sport.end);
307*4dc78e53SAndroid Build Coastguard Worker 	}
308*4dc78e53SAndroid Build Coastguard Worker 
309*4dc78e53SAndroid Build Coastguard Worker 	if (r->ce_mask & RULE_ATTR_DPORT) {
310*4dc78e53SAndroid Build Coastguard Worker 		if (r->r_dport.start == r->r_dport.end)
311*4dc78e53SAndroid Build Coastguard Worker 			nl_dump(p, "dport %u ", r->r_dport.start);
312*4dc78e53SAndroid Build Coastguard Worker 		else
313*4dc78e53SAndroid Build Coastguard Worker 			nl_dump(p, "dport %u-%u ",
314*4dc78e53SAndroid Build Coastguard Worker 				r->r_dport.start, r->r_dport.end);
315*4dc78e53SAndroid Build Coastguard Worker 	}
316*4dc78e53SAndroid Build Coastguard Worker 
317*4dc78e53SAndroid Build Coastguard Worker 	if (r->ce_mask & RULE_ATTR_PROTOCOL)
318*4dc78e53SAndroid Build Coastguard Worker 		nl_dump(p, "protocol %s ",
319*4dc78e53SAndroid Build Coastguard Worker 			rtnl_route_proto2str(r->r_protocol, buf, sizeof(buf)));
320*4dc78e53SAndroid Build Coastguard Worker 
321*4dc78e53SAndroid Build Coastguard Worker 	if (r->ce_mask & RULE_ATTR_FLOW)
322*4dc78e53SAndroid Build Coastguard Worker 		nl_dump(p, "flow %s ",
323*4dc78e53SAndroid Build Coastguard Worker 			rtnl_realms2str(r->r_flow, buf, sizeof(buf)));
324*4dc78e53SAndroid Build Coastguard Worker 
325*4dc78e53SAndroid Build Coastguard Worker 	if (r->ce_mask & RULE_ATTR_GOTO)
326*4dc78e53SAndroid Build Coastguard Worker 		nl_dump(p, "goto %u ", r->r_goto);
327*4dc78e53SAndroid Build Coastguard Worker 
328*4dc78e53SAndroid Build Coastguard Worker 	if (r->ce_mask & RULE_ATTR_ACTION)
329*4dc78e53SAndroid Build Coastguard Worker 		nl_dump(p, "action %s",
330*4dc78e53SAndroid Build Coastguard Worker 			nl_rtntype2str(r->r_action, buf, sizeof(buf)));
331*4dc78e53SAndroid Build Coastguard Worker 
332*4dc78e53SAndroid Build Coastguard Worker 	nl_dump(p, "\n");
333*4dc78e53SAndroid Build Coastguard Worker }
334*4dc78e53SAndroid Build Coastguard Worker 
rule_dump_details(struct nl_object * obj,struct nl_dump_params * p)335*4dc78e53SAndroid Build Coastguard Worker static void rule_dump_details(struct nl_object *obj, struct nl_dump_params *p)
336*4dc78e53SAndroid Build Coastguard Worker {
337*4dc78e53SAndroid Build Coastguard Worker 	rule_dump_line(obj, p);
338*4dc78e53SAndroid Build Coastguard Worker }
339*4dc78e53SAndroid Build Coastguard Worker 
rule_dump_stats(struct nl_object * obj,struct nl_dump_params * p)340*4dc78e53SAndroid Build Coastguard Worker static void rule_dump_stats(struct nl_object *obj, struct nl_dump_params *p)
341*4dc78e53SAndroid Build Coastguard Worker {
342*4dc78e53SAndroid Build Coastguard Worker 	rule_dump_details(obj, p);
343*4dc78e53SAndroid Build Coastguard Worker }
344*4dc78e53SAndroid Build Coastguard Worker 
rule_compare(struct nl_object * _a,struct nl_object * _b,uint64_t attrs,int flags)345*4dc78e53SAndroid Build Coastguard Worker static uint64_t rule_compare(struct nl_object *_a, struct nl_object *_b,
346*4dc78e53SAndroid Build Coastguard Worker 			     uint64_t attrs, int flags)
347*4dc78e53SAndroid Build Coastguard Worker {
348*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_rule *a = (struct rtnl_rule *) _a;
349*4dc78e53SAndroid Build Coastguard Worker 	struct rtnl_rule *b = (struct rtnl_rule *) _b;
350*4dc78e53SAndroid Build Coastguard Worker 	uint64_t diff = 0;
351*4dc78e53SAndroid Build Coastguard Worker 
352*4dc78e53SAndroid Build Coastguard Worker #define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR)
353*4dc78e53SAndroid Build Coastguard Worker 	diff |= _DIFF(RULE_ATTR_FAMILY, a->r_family != b->r_family);
354*4dc78e53SAndroid Build Coastguard Worker 	diff |= _DIFF(RULE_ATTR_TABLE, a->r_table != b->r_table);
355*4dc78e53SAndroid Build Coastguard Worker 	diff |= _DIFF(RULE_ATTR_ACTION, a->r_action != b->r_action);
356*4dc78e53SAndroid Build Coastguard Worker 	diff |= _DIFF(RULE_ATTR_IIFNAME, strcmp(a->r_iifname, b->r_iifname));
357*4dc78e53SAndroid Build Coastguard Worker 	diff |= _DIFF(RULE_ATTR_OIFNAME, strcmp(a->r_oifname, b->r_oifname));
358*4dc78e53SAndroid Build Coastguard Worker 	diff |= _DIFF(RULE_ATTR_PRIO, a->r_prio != b->r_prio);
359*4dc78e53SAndroid Build Coastguard Worker 	diff |= _DIFF(RULE_ATTR_MARK, a->r_mark != b->r_mark);
360*4dc78e53SAndroid Build Coastguard Worker 	diff |= _DIFF(RULE_ATTR_MASK, a->r_mask != b->r_mask);
361*4dc78e53SAndroid Build Coastguard Worker 	diff |= _DIFF(RULE_ATTR_GOTO, a->r_goto != b->r_goto);
362*4dc78e53SAndroid Build Coastguard Worker 	diff |= _DIFF(RULE_ATTR_SRC, nl_addr_cmp(a->r_src, b->r_src));
363*4dc78e53SAndroid Build Coastguard Worker 	diff |= _DIFF(RULE_ATTR_DST, nl_addr_cmp(a->r_dst, b->r_dst));
364*4dc78e53SAndroid Build Coastguard Worker 	diff |= _DIFF(RULE_ATTR_DSFIELD, a->r_dsfield != b->r_dsfield);
365*4dc78e53SAndroid Build Coastguard Worker 	diff |= _DIFF(RULE_ATTR_FLOW, a->r_flow != b->r_flow);
366*4dc78e53SAndroid Build Coastguard Worker #undef _DIFF
367*4dc78e53SAndroid Build Coastguard Worker 
368*4dc78e53SAndroid Build Coastguard Worker 	return diff;
369*4dc78e53SAndroid Build Coastguard Worker }
370*4dc78e53SAndroid Build Coastguard Worker 
371*4dc78e53SAndroid Build Coastguard Worker static const struct trans_tbl rule_attrs[] = {
372*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RULE_ATTR_FAMILY, family),
373*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RULE_ATTR_TABLE, table),
374*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RULE_ATTR_ACTION, action),
375*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RULE_ATTR_IIFNAME, iifname),
376*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RULE_ATTR_OIFNAME, oifname),
377*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RULE_ATTR_PRIO, prio),
378*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RULE_ATTR_MARK, mark),
379*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RULE_ATTR_MASK, mask),
380*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RULE_ATTR_GOTO, goto),
381*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RULE_ATTR_SRC, src),
382*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RULE_ATTR_DST, dst),
383*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RULE_ATTR_DSFIELD, dsfield),
384*4dc78e53SAndroid Build Coastguard Worker 	__ADD(RULE_ATTR_FLOW, flow),
385*4dc78e53SAndroid Build Coastguard Worker };
386*4dc78e53SAndroid Build Coastguard Worker 
rule_attrs2str(int attrs,char * buf,size_t len)387*4dc78e53SAndroid Build Coastguard Worker static char *rule_attrs2str(int attrs, char *buf, size_t len)
388*4dc78e53SAndroid Build Coastguard Worker {
389*4dc78e53SAndroid Build Coastguard Worker 	return __flags2str(attrs, buf, len, rule_attrs,
390*4dc78e53SAndroid Build Coastguard Worker 			   ARRAY_SIZE(rule_attrs));
391*4dc78e53SAndroid Build Coastguard Worker }
392*4dc78e53SAndroid Build Coastguard Worker 
393*4dc78e53SAndroid Build Coastguard Worker /**
394*4dc78e53SAndroid Build Coastguard Worker  * @name Allocation/Freeing
395*4dc78e53SAndroid Build Coastguard Worker  * @{
396*4dc78e53SAndroid Build Coastguard Worker  */
397*4dc78e53SAndroid Build Coastguard Worker 
rtnl_rule_alloc(void)398*4dc78e53SAndroid Build Coastguard Worker struct rtnl_rule *rtnl_rule_alloc(void)
399*4dc78e53SAndroid Build Coastguard Worker {
400*4dc78e53SAndroid Build Coastguard Worker 	return (struct rtnl_rule *) nl_object_alloc(&rule_obj_ops);
401*4dc78e53SAndroid Build Coastguard Worker }
402*4dc78e53SAndroid Build Coastguard Worker 
rtnl_rule_put(struct rtnl_rule * rule)403*4dc78e53SAndroid Build Coastguard Worker void rtnl_rule_put(struct rtnl_rule *rule)
404*4dc78e53SAndroid Build Coastguard Worker {
405*4dc78e53SAndroid Build Coastguard Worker 	nl_object_put((struct nl_object *) rule);
406*4dc78e53SAndroid Build Coastguard Worker }
407*4dc78e53SAndroid Build Coastguard Worker 
408*4dc78e53SAndroid Build Coastguard Worker /** @} */
409*4dc78e53SAndroid Build Coastguard Worker 
410*4dc78e53SAndroid Build Coastguard Worker /**
411*4dc78e53SAndroid Build Coastguard Worker  * @name Cache Management
412*4dc78e53SAndroid Build Coastguard Worker  * @{
413*4dc78e53SAndroid Build Coastguard Worker  */
414*4dc78e53SAndroid Build Coastguard Worker 
415*4dc78e53SAndroid Build Coastguard Worker /**
416*4dc78e53SAndroid Build Coastguard Worker  * Build a rule cache including all rules currently configured in the kernel.
417*4dc78e53SAndroid Build Coastguard Worker  * @arg sock		Netlink socket.
418*4dc78e53SAndroid Build Coastguard Worker  * @arg family		Address family or AF_UNSPEC.
419*4dc78e53SAndroid Build Coastguard Worker  * @arg result		Pointer to store resulting cache.
420*4dc78e53SAndroid Build Coastguard Worker  *
421*4dc78e53SAndroid Build Coastguard Worker  * Allocates a new rule cache, initializes it properly and updates it
422*4dc78e53SAndroid Build Coastguard Worker  * to include all rules currently configured in the kernel.
423*4dc78e53SAndroid Build Coastguard Worker  *
424*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or a negative error code.
425*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_rule_alloc_cache(struct nl_sock * sock,int family,struct nl_cache ** result)426*4dc78e53SAndroid Build Coastguard Worker int rtnl_rule_alloc_cache(struct nl_sock *sock, int family,
427*4dc78e53SAndroid Build Coastguard Worker 			  struct nl_cache **result)
428*4dc78e53SAndroid Build Coastguard Worker {
429*4dc78e53SAndroid Build Coastguard Worker 	struct nl_cache * cache;
430*4dc78e53SAndroid Build Coastguard Worker 	int err;
431*4dc78e53SAndroid Build Coastguard Worker 
432*4dc78e53SAndroid Build Coastguard Worker 	if (!(cache = nl_cache_alloc(&rtnl_rule_ops)))
433*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_NOMEM;
434*4dc78e53SAndroid Build Coastguard Worker 
435*4dc78e53SAndroid Build Coastguard Worker 	cache->c_iarg1 = family;
436*4dc78e53SAndroid Build Coastguard Worker 
437*4dc78e53SAndroid Build Coastguard Worker 	if (sock && (err = nl_cache_refill(sock, cache)) < 0) {
438*4dc78e53SAndroid Build Coastguard Worker 		free(cache);
439*4dc78e53SAndroid Build Coastguard Worker 		return err;
440*4dc78e53SAndroid Build Coastguard Worker 	}
441*4dc78e53SAndroid Build Coastguard Worker 
442*4dc78e53SAndroid Build Coastguard Worker 	*result = cache;
443*4dc78e53SAndroid Build Coastguard Worker 	return 0;
444*4dc78e53SAndroid Build Coastguard Worker }
445*4dc78e53SAndroid Build Coastguard Worker 
446*4dc78e53SAndroid Build Coastguard Worker /** @} */
447*4dc78e53SAndroid Build Coastguard Worker 
448*4dc78e53SAndroid Build Coastguard Worker /**
449*4dc78e53SAndroid Build Coastguard Worker  * @name Rule Addition
450*4dc78e53SAndroid Build Coastguard Worker  * @{
451*4dc78e53SAndroid Build Coastguard Worker  */
452*4dc78e53SAndroid Build Coastguard Worker 
build_rule_msg(struct rtnl_rule * tmpl,int cmd,int flags,struct nl_msg ** result)453*4dc78e53SAndroid Build Coastguard Worker static int build_rule_msg(struct rtnl_rule *tmpl, int cmd, int flags,
454*4dc78e53SAndroid Build Coastguard Worker 			  struct nl_msg **result)
455*4dc78e53SAndroid Build Coastguard Worker {
456*4dc78e53SAndroid Build Coastguard Worker 	struct nl_msg *msg;
457*4dc78e53SAndroid Build Coastguard Worker 	struct fib_rule_hdr frh = {
458*4dc78e53SAndroid Build Coastguard Worker 		.family = tmpl->r_family,
459*4dc78e53SAndroid Build Coastguard Worker 		.table = tmpl->r_table,
460*4dc78e53SAndroid Build Coastguard Worker 		.action = tmpl->r_action,
461*4dc78e53SAndroid Build Coastguard Worker 		.flags = tmpl->r_flags,
462*4dc78e53SAndroid Build Coastguard Worker 		.tos = tmpl->r_dsfield,
463*4dc78e53SAndroid Build Coastguard Worker 	};
464*4dc78e53SAndroid Build Coastguard Worker 
465*4dc78e53SAndroid Build Coastguard Worker 	if (!(tmpl->ce_mask & RULE_ATTR_FAMILY))
466*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_MISSING_ATTR;
467*4dc78e53SAndroid Build Coastguard Worker 
468*4dc78e53SAndroid Build Coastguard Worker 	msg = nlmsg_alloc_simple(cmd, flags);
469*4dc78e53SAndroid Build Coastguard Worker 	if (!msg)
470*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_NOMEM;
471*4dc78e53SAndroid Build Coastguard Worker 
472*4dc78e53SAndroid Build Coastguard Worker 	if (tmpl->ce_mask & RULE_ATTR_SRC)
473*4dc78e53SAndroid Build Coastguard Worker 		frh.src_len = nl_addr_get_prefixlen(tmpl->r_src);
474*4dc78e53SAndroid Build Coastguard Worker 
475*4dc78e53SAndroid Build Coastguard Worker 	if (tmpl->ce_mask & RULE_ATTR_DST)
476*4dc78e53SAndroid Build Coastguard Worker 		frh.dst_len = nl_addr_get_prefixlen(tmpl->r_dst);
477*4dc78e53SAndroid Build Coastguard Worker 
478*4dc78e53SAndroid Build Coastguard Worker 	if (nlmsg_append(msg, &frh, sizeof(frh), NLMSG_ALIGNTO) < 0)
479*4dc78e53SAndroid Build Coastguard Worker 		goto nla_put_failure;
480*4dc78e53SAndroid Build Coastguard Worker 
481*4dc78e53SAndroid Build Coastguard Worker 	/* Additional table attribute replacing the 8bit in the header, was
482*4dc78e53SAndroid Build Coastguard Worker 	 * required to allow more than 256 tables. */
483*4dc78e53SAndroid Build Coastguard Worker 	NLA_PUT_U32(msg, FRA_TABLE, tmpl->r_table);
484*4dc78e53SAndroid Build Coastguard Worker 
485*4dc78e53SAndroid Build Coastguard Worker 	if (tmpl->ce_mask & RULE_ATTR_SRC)
486*4dc78e53SAndroid Build Coastguard Worker 		NLA_PUT_ADDR(msg, FRA_SRC, tmpl->r_src);
487*4dc78e53SAndroid Build Coastguard Worker 
488*4dc78e53SAndroid Build Coastguard Worker 	if (tmpl->ce_mask & RULE_ATTR_DST)
489*4dc78e53SAndroid Build Coastguard Worker 		NLA_PUT_ADDR(msg, FRA_DST, tmpl->r_dst);
490*4dc78e53SAndroid Build Coastguard Worker 
491*4dc78e53SAndroid Build Coastguard Worker 	if (tmpl->ce_mask & RULE_ATTR_IIFNAME)
492*4dc78e53SAndroid Build Coastguard Worker 		NLA_PUT_STRING(msg, FRA_IIFNAME, tmpl->r_iifname);
493*4dc78e53SAndroid Build Coastguard Worker 
494*4dc78e53SAndroid Build Coastguard Worker 	if (tmpl->ce_mask & RULE_ATTR_OIFNAME)
495*4dc78e53SAndroid Build Coastguard Worker 		NLA_PUT_STRING(msg, FRA_OIFNAME, tmpl->r_oifname);
496*4dc78e53SAndroid Build Coastguard Worker 
497*4dc78e53SAndroid Build Coastguard Worker 	if (tmpl->ce_mask & RULE_ATTR_PRIO)
498*4dc78e53SAndroid Build Coastguard Worker 		NLA_PUT_U32(msg, FRA_PRIORITY, tmpl->r_prio);
499*4dc78e53SAndroid Build Coastguard Worker 
500*4dc78e53SAndroid Build Coastguard Worker 	if (tmpl->ce_mask & RULE_ATTR_MARK)
501*4dc78e53SAndroid Build Coastguard Worker 		NLA_PUT_U32(msg, FRA_FWMARK, tmpl->r_mark);
502*4dc78e53SAndroid Build Coastguard Worker 
503*4dc78e53SAndroid Build Coastguard Worker 	if (tmpl->ce_mask & RULE_ATTR_MASK)
504*4dc78e53SAndroid Build Coastguard Worker 		NLA_PUT_U32(msg, FRA_FWMASK, tmpl->r_mask);
505*4dc78e53SAndroid Build Coastguard Worker 
506*4dc78e53SAndroid Build Coastguard Worker 	if (tmpl->ce_mask & RULE_ATTR_GOTO)
507*4dc78e53SAndroid Build Coastguard Worker 		NLA_PUT_U32(msg, FRA_GOTO, tmpl->r_goto);
508*4dc78e53SAndroid Build Coastguard Worker 
509*4dc78e53SAndroid Build Coastguard Worker 	if (tmpl->ce_mask & RULE_ATTR_FLOW)
510*4dc78e53SAndroid Build Coastguard Worker 		NLA_PUT_U32(msg, FRA_FLOW, tmpl->r_flow);
511*4dc78e53SAndroid Build Coastguard Worker 
512*4dc78e53SAndroid Build Coastguard Worker 	if (tmpl->ce_mask & RULE_ATTR_L3MDEV)
513*4dc78e53SAndroid Build Coastguard Worker 		NLA_PUT_U8(msg, FRA_L3MDEV, tmpl->r_l3mdev);
514*4dc78e53SAndroid Build Coastguard Worker 
515*4dc78e53SAndroid Build Coastguard Worker 	if (tmpl->ce_mask & RULE_ATTR_IP_PROTO)
516*4dc78e53SAndroid Build Coastguard Worker 		NLA_PUT_U8(msg, FRA_IP_PROTO, tmpl->r_ip_proto);
517*4dc78e53SAndroid Build Coastguard Worker 
518*4dc78e53SAndroid Build Coastguard Worker 	if (tmpl->ce_mask & RULE_ATTR_SPORT)
519*4dc78e53SAndroid Build Coastguard Worker 		NLA_PUT(msg, FRA_SPORT_RANGE, sizeof(tmpl->r_sport),
520*4dc78e53SAndroid Build Coastguard Worker 			&tmpl->r_sport);
521*4dc78e53SAndroid Build Coastguard Worker 
522*4dc78e53SAndroid Build Coastguard Worker 	if (tmpl->ce_mask & RULE_ATTR_DPORT)
523*4dc78e53SAndroid Build Coastguard Worker 		NLA_PUT(msg, FRA_DPORT_RANGE, sizeof(tmpl->r_dport),
524*4dc78e53SAndroid Build Coastguard Worker 			&tmpl->r_dport);
525*4dc78e53SAndroid Build Coastguard Worker 
526*4dc78e53SAndroid Build Coastguard Worker 	if (tmpl->ce_mask & RULE_ATTR_PROTOCOL)
527*4dc78e53SAndroid Build Coastguard Worker 		NLA_PUT_U8(msg, FRA_PROTOCOL, tmpl->r_protocol);
528*4dc78e53SAndroid Build Coastguard Worker 
529*4dc78e53SAndroid Build Coastguard Worker 	*result = msg;
530*4dc78e53SAndroid Build Coastguard Worker 	return 0;
531*4dc78e53SAndroid Build Coastguard Worker 
532*4dc78e53SAndroid Build Coastguard Worker nla_put_failure:
533*4dc78e53SAndroid Build Coastguard Worker 	nlmsg_free(msg);
534*4dc78e53SAndroid Build Coastguard Worker 	return -NLE_MSGSIZE;
535*4dc78e53SAndroid Build Coastguard Worker }
536*4dc78e53SAndroid Build Coastguard Worker 
537*4dc78e53SAndroid Build Coastguard Worker /**
538*4dc78e53SAndroid Build Coastguard Worker  * Build netlink request message to add a new rule
539*4dc78e53SAndroid Build Coastguard Worker  * @arg tmpl		template with data of new rule
540*4dc78e53SAndroid Build Coastguard Worker  * @arg flags		additional netlink message flags
541*4dc78e53SAndroid Build Coastguard Worker  * @arg result		Result pointer
542*4dc78e53SAndroid Build Coastguard Worker  *
543*4dc78e53SAndroid Build Coastguard Worker  * Builds a new netlink message requesting a addition of a new
544*4dc78e53SAndroid Build Coastguard Worker  * rule. The netlink message header isn't fully equipped with
545*4dc78e53SAndroid Build Coastguard Worker  * all relevant fields and must thus be sent out via nl_send_auto_complete()
546*4dc78e53SAndroid Build Coastguard Worker  * or supplemented as needed. \a tmpl must contain the attributes of the new
547*4dc78e53SAndroid Build Coastguard Worker  * address set via \c rtnl_rule_set_* functions.
548*4dc78e53SAndroid Build Coastguard Worker  *
549*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or a negative error code.
550*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_rule_build_add_request(struct rtnl_rule * tmpl,int flags,struct nl_msg ** result)551*4dc78e53SAndroid Build Coastguard Worker int rtnl_rule_build_add_request(struct rtnl_rule *tmpl, int flags,
552*4dc78e53SAndroid Build Coastguard Worker 				struct nl_msg **result)
553*4dc78e53SAndroid Build Coastguard Worker {
554*4dc78e53SAndroid Build Coastguard Worker 	return build_rule_msg(tmpl, RTM_NEWRULE, NLM_F_CREATE | flags,
555*4dc78e53SAndroid Build Coastguard Worker 			      result);
556*4dc78e53SAndroid Build Coastguard Worker }
557*4dc78e53SAndroid Build Coastguard Worker 
558*4dc78e53SAndroid Build Coastguard Worker /**
559*4dc78e53SAndroid Build Coastguard Worker  * Add a new rule
560*4dc78e53SAndroid Build Coastguard Worker  * @arg sk		Netlink socket.
561*4dc78e53SAndroid Build Coastguard Worker  * @arg tmpl		template with requested changes
562*4dc78e53SAndroid Build Coastguard Worker  * @arg flags		additional netlink message flags
563*4dc78e53SAndroid Build Coastguard Worker  *
564*4dc78e53SAndroid Build Coastguard Worker  * Builds a netlink message by calling rtnl_rule_build_add_request(),
565*4dc78e53SAndroid Build Coastguard Worker  * sends the request to the kernel and waits for the next ACK to be
566*4dc78e53SAndroid Build Coastguard Worker  * received and thus blocks until the request has been fullfilled.
567*4dc78e53SAndroid Build Coastguard Worker  *
568*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or a negative error if an error occured.
569*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_rule_add(struct nl_sock * sk,struct rtnl_rule * tmpl,int flags)570*4dc78e53SAndroid Build Coastguard Worker int rtnl_rule_add(struct nl_sock *sk, struct rtnl_rule *tmpl, int flags)
571*4dc78e53SAndroid Build Coastguard Worker {
572*4dc78e53SAndroid Build Coastguard Worker 	struct nl_msg *msg;
573*4dc78e53SAndroid Build Coastguard Worker 	int err;
574*4dc78e53SAndroid Build Coastguard Worker 
575*4dc78e53SAndroid Build Coastguard Worker 	if ((err = rtnl_rule_build_add_request(tmpl, flags, &msg)) < 0)
576*4dc78e53SAndroid Build Coastguard Worker 		return err;
577*4dc78e53SAndroid Build Coastguard Worker 
578*4dc78e53SAndroid Build Coastguard Worker 	err = nl_send_auto_complete(sk, msg);
579*4dc78e53SAndroid Build Coastguard Worker 	nlmsg_free(msg);
580*4dc78e53SAndroid Build Coastguard Worker 	if (err < 0)
581*4dc78e53SAndroid Build Coastguard Worker 		return err;
582*4dc78e53SAndroid Build Coastguard Worker 
583*4dc78e53SAndroid Build Coastguard Worker 	return wait_for_ack(sk);
584*4dc78e53SAndroid Build Coastguard Worker }
585*4dc78e53SAndroid Build Coastguard Worker 
586*4dc78e53SAndroid Build Coastguard Worker /** @} */
587*4dc78e53SAndroid Build Coastguard Worker 
588*4dc78e53SAndroid Build Coastguard Worker /**
589*4dc78e53SAndroid Build Coastguard Worker  * @name Rule Deletion
590*4dc78e53SAndroid Build Coastguard Worker  * @{
591*4dc78e53SAndroid Build Coastguard Worker  */
592*4dc78e53SAndroid Build Coastguard Worker 
593*4dc78e53SAndroid Build Coastguard Worker /**
594*4dc78e53SAndroid Build Coastguard Worker  * Build a netlink request message to delete a rule
595*4dc78e53SAndroid Build Coastguard Worker  * @arg rule		rule to delete
596*4dc78e53SAndroid Build Coastguard Worker  * @arg flags		additional netlink message flags
597*4dc78e53SAndroid Build Coastguard Worker  * @arg result		Result pointer
598*4dc78e53SAndroid Build Coastguard Worker  *
599*4dc78e53SAndroid Build Coastguard Worker  * Builds a new netlink message requesting a deletion of a rule.
600*4dc78e53SAndroid Build Coastguard Worker  * The netlink message header isn't fully equipped with all relevant
601*4dc78e53SAndroid Build Coastguard Worker  * fields and must thus be sent out via nl_send_auto_complete()
602*4dc78e53SAndroid Build Coastguard Worker  * or supplemented as needed. \a rule must point to an existing
603*4dc78e53SAndroid Build Coastguard Worker  * address.
604*4dc78e53SAndroid Build Coastguard Worker  *
605*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or a negative error code.
606*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_rule_build_delete_request(struct rtnl_rule * rule,int flags,struct nl_msg ** result)607*4dc78e53SAndroid Build Coastguard Worker int rtnl_rule_build_delete_request(struct rtnl_rule *rule, int flags,
608*4dc78e53SAndroid Build Coastguard Worker 				   struct nl_msg **result)
609*4dc78e53SAndroid Build Coastguard Worker {
610*4dc78e53SAndroid Build Coastguard Worker 	return build_rule_msg(rule, RTM_DELRULE, flags, result);
611*4dc78e53SAndroid Build Coastguard Worker }
612*4dc78e53SAndroid Build Coastguard Worker 
613*4dc78e53SAndroid Build Coastguard Worker /**
614*4dc78e53SAndroid Build Coastguard Worker  * Delete a rule
615*4dc78e53SAndroid Build Coastguard Worker  * @arg sk		Netlink socket.
616*4dc78e53SAndroid Build Coastguard Worker  * @arg rule		rule to delete
617*4dc78e53SAndroid Build Coastguard Worker  * @arg flags		additional netlink message flags
618*4dc78e53SAndroid Build Coastguard Worker  *
619*4dc78e53SAndroid Build Coastguard Worker  * Builds a netlink message by calling rtnl_rule_build_delete_request(),
620*4dc78e53SAndroid Build Coastguard Worker  * sends the request to the kernel and waits for the next ACK to be
621*4dc78e53SAndroid Build Coastguard Worker  * received and thus blocks until the request has been fullfilled.
622*4dc78e53SAndroid Build Coastguard Worker  *
623*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or a negative error if an error occured.
624*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_rule_delete(struct nl_sock * sk,struct rtnl_rule * rule,int flags)625*4dc78e53SAndroid Build Coastguard Worker int rtnl_rule_delete(struct nl_sock *sk, struct rtnl_rule *rule, int flags)
626*4dc78e53SAndroid Build Coastguard Worker {
627*4dc78e53SAndroid Build Coastguard Worker 	struct nl_msg *msg;
628*4dc78e53SAndroid Build Coastguard Worker 	int err;
629*4dc78e53SAndroid Build Coastguard Worker 
630*4dc78e53SAndroid Build Coastguard Worker 	if ((err = rtnl_rule_build_delete_request(rule, flags, &msg)) < 0)
631*4dc78e53SAndroid Build Coastguard Worker 		return err;
632*4dc78e53SAndroid Build Coastguard Worker 
633*4dc78e53SAndroid Build Coastguard Worker 	err = nl_send_auto_complete(sk, msg);
634*4dc78e53SAndroid Build Coastguard Worker 	nlmsg_free(msg);
635*4dc78e53SAndroid Build Coastguard Worker 	if (err < 0)
636*4dc78e53SAndroid Build Coastguard Worker 		return err;
637*4dc78e53SAndroid Build Coastguard Worker 
638*4dc78e53SAndroid Build Coastguard Worker 	return wait_for_ack(sk);
639*4dc78e53SAndroid Build Coastguard Worker }
640*4dc78e53SAndroid Build Coastguard Worker 
641*4dc78e53SAndroid Build Coastguard Worker /** @} */
642*4dc78e53SAndroid Build Coastguard Worker 
643*4dc78e53SAndroid Build Coastguard Worker /**
644*4dc78e53SAndroid Build Coastguard Worker  * @name Attribute Modification
645*4dc78e53SAndroid Build Coastguard Worker  * @{
646*4dc78e53SAndroid Build Coastguard Worker  */
647*4dc78e53SAndroid Build Coastguard Worker 
rtnl_rule_set_family(struct rtnl_rule * rule,int family)648*4dc78e53SAndroid Build Coastguard Worker void rtnl_rule_set_family(struct rtnl_rule *rule, int family)
649*4dc78e53SAndroid Build Coastguard Worker {
650*4dc78e53SAndroid Build Coastguard Worker 	rule->r_family = family;
651*4dc78e53SAndroid Build Coastguard Worker 	rule->ce_mask |= RULE_ATTR_FAMILY;
652*4dc78e53SAndroid Build Coastguard Worker }
653*4dc78e53SAndroid Build Coastguard Worker 
rtnl_rule_get_family(struct rtnl_rule * rule)654*4dc78e53SAndroid Build Coastguard Worker int rtnl_rule_get_family(struct rtnl_rule *rule)
655*4dc78e53SAndroid Build Coastguard Worker {
656*4dc78e53SAndroid Build Coastguard Worker 	if (rule->ce_mask & RULE_ATTR_FAMILY)
657*4dc78e53SAndroid Build Coastguard Worker 		return rule->r_family;
658*4dc78e53SAndroid Build Coastguard Worker 	else
659*4dc78e53SAndroid Build Coastguard Worker 		return AF_UNSPEC;
660*4dc78e53SAndroid Build Coastguard Worker }
661*4dc78e53SAndroid Build Coastguard Worker 
rtnl_rule_set_prio(struct rtnl_rule * rule,uint32_t prio)662*4dc78e53SAndroid Build Coastguard Worker void rtnl_rule_set_prio(struct rtnl_rule *rule, uint32_t prio)
663*4dc78e53SAndroid Build Coastguard Worker {
664*4dc78e53SAndroid Build Coastguard Worker 	rule->r_prio = prio;
665*4dc78e53SAndroid Build Coastguard Worker 	rule->ce_mask |= RULE_ATTR_PRIO;
666*4dc78e53SAndroid Build Coastguard Worker }
667*4dc78e53SAndroid Build Coastguard Worker 
rtnl_rule_get_prio(struct rtnl_rule * rule)668*4dc78e53SAndroid Build Coastguard Worker uint32_t rtnl_rule_get_prio(struct rtnl_rule *rule)
669*4dc78e53SAndroid Build Coastguard Worker {
670*4dc78e53SAndroid Build Coastguard Worker 	return rule->r_prio;
671*4dc78e53SAndroid Build Coastguard Worker }
672*4dc78e53SAndroid Build Coastguard Worker 
rtnl_rule_set_mark(struct rtnl_rule * rule,uint32_t mark)673*4dc78e53SAndroid Build Coastguard Worker void rtnl_rule_set_mark(struct rtnl_rule *rule, uint32_t mark)
674*4dc78e53SAndroid Build Coastguard Worker {
675*4dc78e53SAndroid Build Coastguard Worker 	rule->r_mark = mark;
676*4dc78e53SAndroid Build Coastguard Worker 	rule->ce_mask |= RULE_ATTR_MARK;
677*4dc78e53SAndroid Build Coastguard Worker }
678*4dc78e53SAndroid Build Coastguard Worker 
rtnl_rule_get_mark(struct rtnl_rule * rule)679*4dc78e53SAndroid Build Coastguard Worker uint32_t rtnl_rule_get_mark(struct rtnl_rule *rule)
680*4dc78e53SAndroid Build Coastguard Worker {
681*4dc78e53SAndroid Build Coastguard Worker 	return rule->r_mark;
682*4dc78e53SAndroid Build Coastguard Worker }
683*4dc78e53SAndroid Build Coastguard Worker 
rtnl_rule_set_mask(struct rtnl_rule * rule,uint32_t mask)684*4dc78e53SAndroid Build Coastguard Worker void rtnl_rule_set_mask(struct rtnl_rule *rule, uint32_t mask)
685*4dc78e53SAndroid Build Coastguard Worker {
686*4dc78e53SAndroid Build Coastguard Worker 	rule->r_mask = mask;
687*4dc78e53SAndroid Build Coastguard Worker 	rule->ce_mask |= RULE_ATTR_MASK;
688*4dc78e53SAndroid Build Coastguard Worker }
689*4dc78e53SAndroid Build Coastguard Worker 
rtnl_rule_get_mask(struct rtnl_rule * rule)690*4dc78e53SAndroid Build Coastguard Worker uint32_t rtnl_rule_get_mask(struct rtnl_rule *rule)
691*4dc78e53SAndroid Build Coastguard Worker {
692*4dc78e53SAndroid Build Coastguard Worker 	return rule->r_mask;
693*4dc78e53SAndroid Build Coastguard Worker }
694*4dc78e53SAndroid Build Coastguard Worker 
rtnl_rule_set_table(struct rtnl_rule * rule,uint32_t table)695*4dc78e53SAndroid Build Coastguard Worker void rtnl_rule_set_table(struct rtnl_rule *rule, uint32_t table)
696*4dc78e53SAndroid Build Coastguard Worker {
697*4dc78e53SAndroid Build Coastguard Worker 	rule->r_table = table;
698*4dc78e53SAndroid Build Coastguard Worker 	rule->ce_mask |= RULE_ATTR_TABLE;
699*4dc78e53SAndroid Build Coastguard Worker }
700*4dc78e53SAndroid Build Coastguard Worker 
rtnl_rule_get_table(struct rtnl_rule * rule)701*4dc78e53SAndroid Build Coastguard Worker uint32_t rtnl_rule_get_table(struct rtnl_rule *rule)
702*4dc78e53SAndroid Build Coastguard Worker {
703*4dc78e53SAndroid Build Coastguard Worker 	return rule->r_table;
704*4dc78e53SAndroid Build Coastguard Worker }
705*4dc78e53SAndroid Build Coastguard Worker 
rtnl_rule_set_dsfield(struct rtnl_rule * rule,uint8_t dsfield)706*4dc78e53SAndroid Build Coastguard Worker void rtnl_rule_set_dsfield(struct rtnl_rule *rule, uint8_t dsfield)
707*4dc78e53SAndroid Build Coastguard Worker {
708*4dc78e53SAndroid Build Coastguard Worker 	rule->r_dsfield = dsfield;
709*4dc78e53SAndroid Build Coastguard Worker 	rule->ce_mask |= RULE_ATTR_DSFIELD;
710*4dc78e53SAndroid Build Coastguard Worker }
711*4dc78e53SAndroid Build Coastguard Worker 
rtnl_rule_get_dsfield(struct rtnl_rule * rule)712*4dc78e53SAndroid Build Coastguard Worker uint8_t rtnl_rule_get_dsfield(struct rtnl_rule *rule)
713*4dc78e53SAndroid Build Coastguard Worker {
714*4dc78e53SAndroid Build Coastguard Worker 	return rule->r_dsfield;
715*4dc78e53SAndroid Build Coastguard Worker }
716*4dc78e53SAndroid Build Coastguard Worker 
__assign_addr(struct rtnl_rule * rule,struct nl_addr ** pos,struct nl_addr * new,int flag)717*4dc78e53SAndroid Build Coastguard Worker static inline int __assign_addr(struct rtnl_rule *rule, struct nl_addr **pos,
718*4dc78e53SAndroid Build Coastguard Worker 			        struct nl_addr *new, int flag)
719*4dc78e53SAndroid Build Coastguard Worker {
720*4dc78e53SAndroid Build Coastguard Worker 	if (rule->ce_mask & RULE_ATTR_FAMILY) {
721*4dc78e53SAndroid Build Coastguard Worker 		if (new->a_family != rule->r_family)
722*4dc78e53SAndroid Build Coastguard Worker 			return -NLE_AF_MISMATCH;
723*4dc78e53SAndroid Build Coastguard Worker 	} else
724*4dc78e53SAndroid Build Coastguard Worker 		rule->r_family = new->a_family;
725*4dc78e53SAndroid Build Coastguard Worker 
726*4dc78e53SAndroid Build Coastguard Worker 	if (*pos)
727*4dc78e53SAndroid Build Coastguard Worker 		nl_addr_put(*pos);
728*4dc78e53SAndroid Build Coastguard Worker 
729*4dc78e53SAndroid Build Coastguard Worker 	nl_addr_get(new);
730*4dc78e53SAndroid Build Coastguard Worker 	*pos = new;
731*4dc78e53SAndroid Build Coastguard Worker 
732*4dc78e53SAndroid Build Coastguard Worker 	rule->ce_mask |= (flag | RULE_ATTR_FAMILY);
733*4dc78e53SAndroid Build Coastguard Worker 
734*4dc78e53SAndroid Build Coastguard Worker 	return 0;
735*4dc78e53SAndroid Build Coastguard Worker }
736*4dc78e53SAndroid Build Coastguard Worker 
rtnl_rule_set_src(struct rtnl_rule * rule,struct nl_addr * src)737*4dc78e53SAndroid Build Coastguard Worker int rtnl_rule_set_src(struct rtnl_rule *rule, struct nl_addr *src)
738*4dc78e53SAndroid Build Coastguard Worker {
739*4dc78e53SAndroid Build Coastguard Worker 	return __assign_addr(rule, &rule->r_src, src, RULE_ATTR_SRC);
740*4dc78e53SAndroid Build Coastguard Worker }
741*4dc78e53SAndroid Build Coastguard Worker 
rtnl_rule_get_src(struct rtnl_rule * rule)742*4dc78e53SAndroid Build Coastguard Worker struct nl_addr *rtnl_rule_get_src(struct rtnl_rule *rule)
743*4dc78e53SAndroid Build Coastguard Worker {
744*4dc78e53SAndroid Build Coastguard Worker 	return rule->r_src;
745*4dc78e53SAndroid Build Coastguard Worker }
746*4dc78e53SAndroid Build Coastguard Worker 
rtnl_rule_set_dst(struct rtnl_rule * rule,struct nl_addr * dst)747*4dc78e53SAndroid Build Coastguard Worker int rtnl_rule_set_dst(struct rtnl_rule *rule, struct nl_addr *dst)
748*4dc78e53SAndroid Build Coastguard Worker {
749*4dc78e53SAndroid Build Coastguard Worker 	return __assign_addr(rule, &rule->r_dst, dst, RULE_ATTR_DST);
750*4dc78e53SAndroid Build Coastguard Worker }
751*4dc78e53SAndroid Build Coastguard Worker 
rtnl_rule_get_dst(struct rtnl_rule * rule)752*4dc78e53SAndroid Build Coastguard Worker struct nl_addr *rtnl_rule_get_dst(struct rtnl_rule *rule)
753*4dc78e53SAndroid Build Coastguard Worker {
754*4dc78e53SAndroid Build Coastguard Worker 	return rule->r_dst;
755*4dc78e53SAndroid Build Coastguard Worker }
756*4dc78e53SAndroid Build Coastguard Worker 
rtnl_rule_set_iif(struct rtnl_rule * rule,const char * dev)757*4dc78e53SAndroid Build Coastguard Worker int rtnl_rule_set_iif(struct rtnl_rule *rule, const char *dev)
758*4dc78e53SAndroid Build Coastguard Worker {
759*4dc78e53SAndroid Build Coastguard Worker 	if (strlen(dev) > IFNAMSIZ-1)
760*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_RANGE;
761*4dc78e53SAndroid Build Coastguard Worker 
762*4dc78e53SAndroid Build Coastguard Worker 	strcpy(rule->r_iifname, dev);
763*4dc78e53SAndroid Build Coastguard Worker 	rule->ce_mask |= RULE_ATTR_IIFNAME;
764*4dc78e53SAndroid Build Coastguard Worker 	return 0;
765*4dc78e53SAndroid Build Coastguard Worker }
766*4dc78e53SAndroid Build Coastguard Worker 
rtnl_rule_get_iif(struct rtnl_rule * rule)767*4dc78e53SAndroid Build Coastguard Worker char *rtnl_rule_get_iif(struct rtnl_rule *rule)
768*4dc78e53SAndroid Build Coastguard Worker {
769*4dc78e53SAndroid Build Coastguard Worker 	if (rule->ce_mask & RULE_ATTR_IIFNAME)
770*4dc78e53SAndroid Build Coastguard Worker 		return rule->r_iifname;
771*4dc78e53SAndroid Build Coastguard Worker 	else
772*4dc78e53SAndroid Build Coastguard Worker 		return NULL;
773*4dc78e53SAndroid Build Coastguard Worker }
774*4dc78e53SAndroid Build Coastguard Worker 
rtnl_rule_set_oif(struct rtnl_rule * rule,const char * dev)775*4dc78e53SAndroid Build Coastguard Worker int rtnl_rule_set_oif(struct rtnl_rule *rule, const char *dev)
776*4dc78e53SAndroid Build Coastguard Worker {
777*4dc78e53SAndroid Build Coastguard Worker 	if (strlen(dev) > IFNAMSIZ-1)
778*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_RANGE;
779*4dc78e53SAndroid Build Coastguard Worker 
780*4dc78e53SAndroid Build Coastguard Worker 	strcpy(rule->r_oifname, dev);
781*4dc78e53SAndroid Build Coastguard Worker 	rule->ce_mask |= RULE_ATTR_OIFNAME;
782*4dc78e53SAndroid Build Coastguard Worker 	return 0;
783*4dc78e53SAndroid Build Coastguard Worker }
784*4dc78e53SAndroid Build Coastguard Worker 
rtnl_rule_get_oif(struct rtnl_rule * rule)785*4dc78e53SAndroid Build Coastguard Worker char *rtnl_rule_get_oif(struct rtnl_rule *rule)
786*4dc78e53SAndroid Build Coastguard Worker {
787*4dc78e53SAndroid Build Coastguard Worker 	if (rule->ce_mask & RULE_ATTR_OIFNAME)
788*4dc78e53SAndroid Build Coastguard Worker 		return rule->r_oifname;
789*4dc78e53SAndroid Build Coastguard Worker 	else
790*4dc78e53SAndroid Build Coastguard Worker 		return NULL;
791*4dc78e53SAndroid Build Coastguard Worker }
792*4dc78e53SAndroid Build Coastguard Worker 
rtnl_rule_set_action(struct rtnl_rule * rule,uint8_t action)793*4dc78e53SAndroid Build Coastguard Worker void rtnl_rule_set_action(struct rtnl_rule *rule, uint8_t action)
794*4dc78e53SAndroid Build Coastguard Worker {
795*4dc78e53SAndroid Build Coastguard Worker 	rule->r_action = action;
796*4dc78e53SAndroid Build Coastguard Worker 	rule->ce_mask |= RULE_ATTR_ACTION;
797*4dc78e53SAndroid Build Coastguard Worker }
798*4dc78e53SAndroid Build Coastguard Worker 
rtnl_rule_get_action(struct rtnl_rule * rule)799*4dc78e53SAndroid Build Coastguard Worker uint8_t rtnl_rule_get_action(struct rtnl_rule *rule)
800*4dc78e53SAndroid Build Coastguard Worker {
801*4dc78e53SAndroid Build Coastguard Worker 	return rule->r_action;
802*4dc78e53SAndroid Build Coastguard Worker }
803*4dc78e53SAndroid Build Coastguard Worker 
804*4dc78e53SAndroid Build Coastguard Worker /**
805*4dc78e53SAndroid Build Coastguard Worker  * Set l3mdev value of the rule (FRA_L3MDEV)
806*4dc78e53SAndroid Build Coastguard Worker  * @arg rule		rule
807*4dc78e53SAndroid Build Coastguard Worker  * @arg value		value to set
808*4dc78e53SAndroid Build Coastguard Worker  *
809*4dc78e53SAndroid Build Coastguard Worker  * Set the l3mdev value to value. Currently supported values
810*4dc78e53SAndroid Build Coastguard Worker  * are only 1 (set it) and -1 (unset it). All other values
811*4dc78e53SAndroid Build Coastguard Worker  * are reserved.
812*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_rule_set_l3mdev(struct rtnl_rule * rule,int value)813*4dc78e53SAndroid Build Coastguard Worker void rtnl_rule_set_l3mdev(struct rtnl_rule *rule, int value)
814*4dc78e53SAndroid Build Coastguard Worker {
815*4dc78e53SAndroid Build Coastguard Worker 	if (value >= 0) {
816*4dc78e53SAndroid Build Coastguard Worker 		rule->r_l3mdev = (uint8_t) value;
817*4dc78e53SAndroid Build Coastguard Worker 		rule->ce_mask |= RULE_ATTR_L3MDEV;
818*4dc78e53SAndroid Build Coastguard Worker 	} else {
819*4dc78e53SAndroid Build Coastguard Worker 		rule->r_l3mdev = 0;
820*4dc78e53SAndroid Build Coastguard Worker 		rule->ce_mask &= ~((uint32_t) RULE_ATTR_L3MDEV);
821*4dc78e53SAndroid Build Coastguard Worker 	}
822*4dc78e53SAndroid Build Coastguard Worker }
823*4dc78e53SAndroid Build Coastguard Worker 
824*4dc78e53SAndroid Build Coastguard Worker /**
825*4dc78e53SAndroid Build Coastguard Worker  * Get l3mdev value of the rule (FRA_L3MDEV)
826*4dc78e53SAndroid Build Coastguard Worker  * @arg rule		rule
827*4dc78e53SAndroid Build Coastguard Worker  *
828*4dc78e53SAndroid Build Coastguard Worker  * @return a negative error code, including -NLE_MISSING_ATTR
829*4dc78e53SAndroid Build Coastguard Worker  *   if the property is unset. Otherwise returns a non-negative
830*4dc78e53SAndroid Build Coastguard Worker  *   value. As FRA_L3MDEV is a boolean, the only expected
831*4dc78e53SAndroid Build Coastguard Worker  *   value at the moment is 1.
832*4dc78e53SAndroid Build Coastguard Worker  */
rtnl_rule_get_l3mdev(struct rtnl_rule * rule)833*4dc78e53SAndroid Build Coastguard Worker int rtnl_rule_get_l3mdev(struct rtnl_rule *rule)
834*4dc78e53SAndroid Build Coastguard Worker {
835*4dc78e53SAndroid Build Coastguard Worker 	if (!rule)
836*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_INVAL;
837*4dc78e53SAndroid Build Coastguard Worker 	if (!(rule->ce_mask & RULE_ATTR_L3MDEV))
838*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_MISSING_ATTR;
839*4dc78e53SAndroid Build Coastguard Worker 	return rule->r_l3mdev;
840*4dc78e53SAndroid Build Coastguard Worker }
841*4dc78e53SAndroid Build Coastguard Worker 
rtnl_rule_set_protocol(struct rtnl_rule * rule,uint8_t protocol)842*4dc78e53SAndroid Build Coastguard Worker int rtnl_rule_set_protocol(struct rtnl_rule *rule, uint8_t protocol)
843*4dc78e53SAndroid Build Coastguard Worker {
844*4dc78e53SAndroid Build Coastguard Worker 	if (protocol) {
845*4dc78e53SAndroid Build Coastguard Worker 		rule->r_protocol = protocol;
846*4dc78e53SAndroid Build Coastguard Worker 		rule->ce_mask |= RULE_ATTR_PROTOCOL;
847*4dc78e53SAndroid Build Coastguard Worker 	} else {
848*4dc78e53SAndroid Build Coastguard Worker 		rule->r_protocol = 0;
849*4dc78e53SAndroid Build Coastguard Worker 		rule->ce_mask &= ~((uint32_t) RULE_ATTR_PROTOCOL);
850*4dc78e53SAndroid Build Coastguard Worker 	}
851*4dc78e53SAndroid Build Coastguard Worker 	return 0;
852*4dc78e53SAndroid Build Coastguard Worker }
853*4dc78e53SAndroid Build Coastguard Worker 
rtnl_rule_get_protocol(struct rtnl_rule * rule,uint8_t * protocol)854*4dc78e53SAndroid Build Coastguard Worker int rtnl_rule_get_protocol(struct rtnl_rule *rule, uint8_t *protocol)
855*4dc78e53SAndroid Build Coastguard Worker {
856*4dc78e53SAndroid Build Coastguard Worker 	if (!(rule->ce_mask & RULE_ATTR_PROTOCOL))
857*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_INVAL;
858*4dc78e53SAndroid Build Coastguard Worker 
859*4dc78e53SAndroid Build Coastguard Worker 	*protocol = rule->r_protocol;
860*4dc78e53SAndroid Build Coastguard Worker 	return 0;
861*4dc78e53SAndroid Build Coastguard Worker }
862*4dc78e53SAndroid Build Coastguard Worker 
rtnl_rule_set_ipproto(struct rtnl_rule * rule,uint8_t ip_proto)863*4dc78e53SAndroid Build Coastguard Worker int rtnl_rule_set_ipproto(struct rtnl_rule *rule, uint8_t ip_proto)
864*4dc78e53SAndroid Build Coastguard Worker {
865*4dc78e53SAndroid Build Coastguard Worker 	if (ip_proto) {
866*4dc78e53SAndroid Build Coastguard Worker 		rule->r_ip_proto = ip_proto;
867*4dc78e53SAndroid Build Coastguard Worker 		rule->ce_mask |= RULE_ATTR_IP_PROTO;
868*4dc78e53SAndroid Build Coastguard Worker 	} else {
869*4dc78e53SAndroid Build Coastguard Worker 		rule->r_ip_proto = 0;
870*4dc78e53SAndroid Build Coastguard Worker 		rule->ce_mask &= ~((uint32_t) RULE_ATTR_IP_PROTO);
871*4dc78e53SAndroid Build Coastguard Worker 	}
872*4dc78e53SAndroid Build Coastguard Worker 	return 0;
873*4dc78e53SAndroid Build Coastguard Worker }
874*4dc78e53SAndroid Build Coastguard Worker 
rtnl_rule_get_ipproto(struct rtnl_rule * rule,uint8_t * ip_proto)875*4dc78e53SAndroid Build Coastguard Worker int rtnl_rule_get_ipproto(struct rtnl_rule *rule, uint8_t *ip_proto)
876*4dc78e53SAndroid Build Coastguard Worker {
877*4dc78e53SAndroid Build Coastguard Worker 	if (!(rule->ce_mask & RULE_ATTR_IP_PROTO))
878*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_INVAL;
879*4dc78e53SAndroid Build Coastguard Worker 
880*4dc78e53SAndroid Build Coastguard Worker 	*ip_proto = rule->r_ip_proto;
881*4dc78e53SAndroid Build Coastguard Worker 	return 0;
882*4dc78e53SAndroid Build Coastguard Worker }
883*4dc78e53SAndroid Build Coastguard Worker 
__rtnl_rule_set_port(struct fib_rule_port_range * prange,uint16_t start,uint16_t end,uint64_t attr,uint64_t * mask)884*4dc78e53SAndroid Build Coastguard Worker static int __rtnl_rule_set_port(struct fib_rule_port_range *prange,
885*4dc78e53SAndroid Build Coastguard Worker 				uint16_t start, uint16_t end,
886*4dc78e53SAndroid Build Coastguard Worker 				uint64_t attr, uint64_t *mask)
887*4dc78e53SAndroid Build Coastguard Worker {
888*4dc78e53SAndroid Build Coastguard Worker 	if ((start && end < start) || (end && !start))
889*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_INVAL;
890*4dc78e53SAndroid Build Coastguard Worker 
891*4dc78e53SAndroid Build Coastguard Worker 	if (start) {
892*4dc78e53SAndroid Build Coastguard Worker 		prange->start = start;
893*4dc78e53SAndroid Build Coastguard Worker 		prange->end = end;
894*4dc78e53SAndroid Build Coastguard Worker 		*mask |= attr;
895*4dc78e53SAndroid Build Coastguard Worker 	} else {
896*4dc78e53SAndroid Build Coastguard Worker 		prange->start = 0;
897*4dc78e53SAndroid Build Coastguard Worker 		prange->end = 0;
898*4dc78e53SAndroid Build Coastguard Worker 		*mask &= ~attr;
899*4dc78e53SAndroid Build Coastguard Worker 
900*4dc78e53SAndroid Build Coastguard Worker 	}
901*4dc78e53SAndroid Build Coastguard Worker 	return 0;
902*4dc78e53SAndroid Build Coastguard Worker }
903*4dc78e53SAndroid Build Coastguard Worker 
rtnl_rule_set_sport(struct rtnl_rule * rule,uint16_t sport)904*4dc78e53SAndroid Build Coastguard Worker int rtnl_rule_set_sport(struct rtnl_rule *rule, uint16_t sport)
905*4dc78e53SAndroid Build Coastguard Worker {
906*4dc78e53SAndroid Build Coastguard Worker 	return __rtnl_rule_set_port(&rule->r_sport, sport, sport,
907*4dc78e53SAndroid Build Coastguard Worker 				    RULE_ATTR_SPORT, &rule->ce_mask);
908*4dc78e53SAndroid Build Coastguard Worker }
909*4dc78e53SAndroid Build Coastguard Worker 
rtnl_rule_set_sport_range(struct rtnl_rule * rule,uint16_t start,uint16_t end)910*4dc78e53SAndroid Build Coastguard Worker int rtnl_rule_set_sport_range(struct rtnl_rule *rule, uint16_t start,
911*4dc78e53SAndroid Build Coastguard Worker 			      uint16_t end)
912*4dc78e53SAndroid Build Coastguard Worker {
913*4dc78e53SAndroid Build Coastguard Worker 	return __rtnl_rule_set_port(&rule->r_sport, start, end,
914*4dc78e53SAndroid Build Coastguard Worker 				    RULE_ATTR_SPORT, &rule->ce_mask);
915*4dc78e53SAndroid Build Coastguard Worker }
916*4dc78e53SAndroid Build Coastguard Worker 
rtnl_rule_get_sport(struct rtnl_rule * rule,uint16_t * start,uint16_t * end)917*4dc78e53SAndroid Build Coastguard Worker int rtnl_rule_get_sport(struct rtnl_rule *rule, uint16_t *start, uint16_t *end)
918*4dc78e53SAndroid Build Coastguard Worker {
919*4dc78e53SAndroid Build Coastguard Worker 	if (!(rule->ce_mask & RULE_ATTR_SPORT))
920*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_INVAL;
921*4dc78e53SAndroid Build Coastguard Worker 
922*4dc78e53SAndroid Build Coastguard Worker 	*start = rule->r_sport.start;
923*4dc78e53SAndroid Build Coastguard Worker 	*end = rule->r_sport.end;
924*4dc78e53SAndroid Build Coastguard Worker 	return 0;
925*4dc78e53SAndroid Build Coastguard Worker }
926*4dc78e53SAndroid Build Coastguard Worker 
rtnl_rule_set_dport(struct rtnl_rule * rule,uint16_t dport)927*4dc78e53SAndroid Build Coastguard Worker int rtnl_rule_set_dport(struct rtnl_rule *rule, uint16_t dport)
928*4dc78e53SAndroid Build Coastguard Worker {
929*4dc78e53SAndroid Build Coastguard Worker 	return __rtnl_rule_set_port(&rule->r_dport, dport, dport,
930*4dc78e53SAndroid Build Coastguard Worker 				    RULE_ATTR_DPORT, &rule->ce_mask);
931*4dc78e53SAndroid Build Coastguard Worker }
932*4dc78e53SAndroid Build Coastguard Worker 
rtnl_rule_set_dport_range(struct rtnl_rule * rule,uint16_t start,uint16_t end)933*4dc78e53SAndroid Build Coastguard Worker int rtnl_rule_set_dport_range(struct rtnl_rule *rule, uint16_t start,
934*4dc78e53SAndroid Build Coastguard Worker 			      uint16_t end)
935*4dc78e53SAndroid Build Coastguard Worker {
936*4dc78e53SAndroid Build Coastguard Worker 	return __rtnl_rule_set_port(&rule->r_dport, start, end,
937*4dc78e53SAndroid Build Coastguard Worker 				    RULE_ATTR_DPORT, &rule->ce_mask);
938*4dc78e53SAndroid Build Coastguard Worker }
939*4dc78e53SAndroid Build Coastguard Worker 
rtnl_rule_get_dport(struct rtnl_rule * rule,uint16_t * start,uint16_t * end)940*4dc78e53SAndroid Build Coastguard Worker int rtnl_rule_get_dport(struct rtnl_rule *rule, uint16_t *start, uint16_t *end)
941*4dc78e53SAndroid Build Coastguard Worker {
942*4dc78e53SAndroid Build Coastguard Worker 	if (!(rule->ce_mask & RULE_ATTR_DPORT))
943*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_INVAL;
944*4dc78e53SAndroid Build Coastguard Worker 
945*4dc78e53SAndroid Build Coastguard Worker 	*start = rule->r_dport.start;
946*4dc78e53SAndroid Build Coastguard Worker 	*end = rule->r_dport.end;
947*4dc78e53SAndroid Build Coastguard Worker 	return 0;
948*4dc78e53SAndroid Build Coastguard Worker }
949*4dc78e53SAndroid Build Coastguard Worker 
rtnl_rule_set_realms(struct rtnl_rule * rule,uint32_t realms)950*4dc78e53SAndroid Build Coastguard Worker void rtnl_rule_set_realms(struct rtnl_rule *rule, uint32_t realms)
951*4dc78e53SAndroid Build Coastguard Worker {
952*4dc78e53SAndroid Build Coastguard Worker 	rule->r_flow = realms;
953*4dc78e53SAndroid Build Coastguard Worker 	rule->ce_mask |= RULE_ATTR_FLOW;
954*4dc78e53SAndroid Build Coastguard Worker }
955*4dc78e53SAndroid Build Coastguard Worker 
rtnl_rule_get_realms(struct rtnl_rule * rule)956*4dc78e53SAndroid Build Coastguard Worker uint32_t rtnl_rule_get_realms(struct rtnl_rule *rule)
957*4dc78e53SAndroid Build Coastguard Worker {
958*4dc78e53SAndroid Build Coastguard Worker 	return rule->r_flow;
959*4dc78e53SAndroid Build Coastguard Worker }
960*4dc78e53SAndroid Build Coastguard Worker 
rtnl_rule_set_goto(struct rtnl_rule * rule,uint32_t ref)961*4dc78e53SAndroid Build Coastguard Worker void rtnl_rule_set_goto(struct rtnl_rule *rule, uint32_t ref)
962*4dc78e53SAndroid Build Coastguard Worker {
963*4dc78e53SAndroid Build Coastguard Worker 	rule->r_goto = ref;
964*4dc78e53SAndroid Build Coastguard Worker 	rule->ce_mask |= RULE_ATTR_GOTO;
965*4dc78e53SAndroid Build Coastguard Worker }
966*4dc78e53SAndroid Build Coastguard Worker 
rtnl_rule_get_goto(struct rtnl_rule * rule)967*4dc78e53SAndroid Build Coastguard Worker uint32_t rtnl_rule_get_goto(struct rtnl_rule *rule)
968*4dc78e53SAndroid Build Coastguard Worker {
969*4dc78e53SAndroid Build Coastguard Worker 	return rule->r_goto;
970*4dc78e53SAndroid Build Coastguard Worker }
971*4dc78e53SAndroid Build Coastguard Worker 
972*4dc78e53SAndroid Build Coastguard Worker /** @} */
973*4dc78e53SAndroid Build Coastguard Worker 
974*4dc78e53SAndroid Build Coastguard Worker static struct nl_object_ops rule_obj_ops = {
975*4dc78e53SAndroid Build Coastguard Worker 	.oo_name		= "route/rule",
976*4dc78e53SAndroid Build Coastguard Worker 	.oo_size		= sizeof(struct rtnl_rule),
977*4dc78e53SAndroid Build Coastguard Worker 	.oo_free_data		= rule_free_data,
978*4dc78e53SAndroid Build Coastguard Worker 	.oo_clone		= rule_clone,
979*4dc78e53SAndroid Build Coastguard Worker 	.oo_dump = {
980*4dc78e53SAndroid Build Coastguard Worker 	    [NL_DUMP_LINE]	= rule_dump_line,
981*4dc78e53SAndroid Build Coastguard Worker 	    [NL_DUMP_DETAILS]	= rule_dump_details,
982*4dc78e53SAndroid Build Coastguard Worker 	    [NL_DUMP_STATS]	= rule_dump_stats,
983*4dc78e53SAndroid Build Coastguard Worker 	},
984*4dc78e53SAndroid Build Coastguard Worker 	.oo_compare		= rule_compare,
985*4dc78e53SAndroid Build Coastguard Worker 	.oo_attrs2str		= rule_attrs2str,
986*4dc78e53SAndroid Build Coastguard Worker 	.oo_id_attrs		= ~0,
987*4dc78e53SAndroid Build Coastguard Worker };
988*4dc78e53SAndroid Build Coastguard Worker 
989*4dc78e53SAndroid Build Coastguard Worker static struct nl_af_group rule_groups[] = {
990*4dc78e53SAndroid Build Coastguard Worker 	{ AF_INET,	RTNLGRP_IPV4_RULE },
991*4dc78e53SAndroid Build Coastguard Worker 	{ AF_INET6,	RTNLGRP_IPV6_RULE },
992*4dc78e53SAndroid Build Coastguard Worker 	{ END_OF_GROUP_LIST },
993*4dc78e53SAndroid Build Coastguard Worker };
994*4dc78e53SAndroid Build Coastguard Worker 
995*4dc78e53SAndroid Build Coastguard Worker static struct nl_cache_ops rtnl_rule_ops = {
996*4dc78e53SAndroid Build Coastguard Worker 	.co_name		= "route/rule",
997*4dc78e53SAndroid Build Coastguard Worker 	.co_hdrsize		= sizeof(struct fib_rule_hdr),
998*4dc78e53SAndroid Build Coastguard Worker 	.co_msgtypes		= {
999*4dc78e53SAndroid Build Coastguard Worker 					{ RTM_NEWRULE, NL_ACT_NEW, "new" },
1000*4dc78e53SAndroid Build Coastguard Worker 					{ RTM_DELRULE, NL_ACT_DEL, "del" },
1001*4dc78e53SAndroid Build Coastguard Worker 					{ RTM_GETRULE, NL_ACT_GET, "get" },
1002*4dc78e53SAndroid Build Coastguard Worker 					END_OF_MSGTYPES_LIST,
1003*4dc78e53SAndroid Build Coastguard Worker 				  },
1004*4dc78e53SAndroid Build Coastguard Worker 	.co_protocol		= NETLINK_ROUTE,
1005*4dc78e53SAndroid Build Coastguard Worker 	.co_request_update	= rule_request_update,
1006*4dc78e53SAndroid Build Coastguard Worker 	.co_msg_parser		= rule_msg_parser,
1007*4dc78e53SAndroid Build Coastguard Worker 	.co_obj_ops		= &rule_obj_ops,
1008*4dc78e53SAndroid Build Coastguard Worker 	.co_groups		= rule_groups,
1009*4dc78e53SAndroid Build Coastguard Worker };
1010*4dc78e53SAndroid Build Coastguard Worker 
rule_init(void)1011*4dc78e53SAndroid Build Coastguard Worker static void _nl_init rule_init(void)
1012*4dc78e53SAndroid Build Coastguard Worker {
1013*4dc78e53SAndroid Build Coastguard Worker 	nl_cache_mngt_register(&rtnl_rule_ops);
1014*4dc78e53SAndroid Build Coastguard Worker }
1015*4dc78e53SAndroid Build Coastguard Worker 
rule_exit(void)1016*4dc78e53SAndroid Build Coastguard Worker static void _nl_exit rule_exit(void)
1017*4dc78e53SAndroid Build Coastguard Worker {
1018*4dc78e53SAndroid Build Coastguard Worker 	nl_cache_mngt_unregister(&rtnl_rule_ops);
1019*4dc78e53SAndroid Build Coastguard Worker }
1020*4dc78e53SAndroid Build Coastguard Worker 
1021*4dc78e53SAndroid Build Coastguard Worker /** @} */
1022