Imported Upstream version 1.1
[platform/upstream/libnl1.git] / lib / route / rule.c
1 /*
2  * lib/route/rule.c          Routing Rules
3  *
4  *      This library is free software; you can redistribute it and/or
5  *      modify it under the terms of the GNU Lesser General Public
6  *      License as published by the Free Software Foundation version 2.1
7  *      of the License.
8  *
9  * Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
10  */
11
12 /**
13  * @ingroup rtnl
14  * @defgroup rule Routing Rules
15  * @brief
16  * @{
17  */
18
19 #include <netlink-local.h>
20 #include <netlink/netlink.h>
21 #include <netlink/utils.h>
22 #include <netlink/route/rtnl.h>
23 #include <netlink/route/rule.h>
24 #include <inttypes.h>
25
26 /** @cond SKIP */
27 #define RULE_ATTR_FAMILY        0x0001
28 #define RULE_ATTR_PRIO          0x0002
29 #define RULE_ATTR_MARK          0x0004
30 #define RULE_ATTR_IIF           0x0008
31 #define RULE_ATTR_REALMS        0x0010
32 #define RULE_ATTR_SRC           0x0020
33 #define RULE_ATTR_DST           0x0040
34 #define RULE_ATTR_DSFIELD       0x0080
35 #define RULE_ATTR_TABLE         0x0100
36 #define RULE_ATTR_TYPE          0x0200
37 #define RULE_ATTR_SRC_LEN       0x0400
38 #define RULE_ATTR_DST_LEN       0x0800
39 #define RULE_ATTR_SRCMAP        0x1000
40
41 static struct nl_cache_ops rtnl_rule_ops;
42 static struct nl_object_ops rule_obj_ops;
43 /** @endcond */
44
45 static void rule_free_data(struct nl_object *c)
46 {
47         struct rtnl_rule *rule = nl_object_priv(c);
48
49         if (!rule)
50                 return;
51
52         nl_addr_put(rule->r_src);
53         nl_addr_put(rule->r_dst);
54 }
55
56 static int rule_clone(struct nl_object *_dst, struct nl_object *_src)
57 {
58         struct rtnl_rule *dst = nl_object_priv(_dst);
59         struct rtnl_rule *src = nl_object_priv(_src);
60
61         if (src->r_src)
62                 if (!(dst->r_src = nl_addr_clone(src->r_src)))
63                         goto errout;
64
65         if (src->r_dst)
66                 if (!(dst->r_dst = nl_addr_clone(src->r_dst)))
67                         goto errout;
68
69         return 0;
70 errout:
71         return nl_get_errno();
72 }
73
74 static struct nla_policy rule_policy[RTA_MAX+1] = {
75         [RTA_PRIORITY]  = { .type = NLA_U32 },
76         [RTA_FLOW]      = { .type = NLA_U32 },
77         [RTA_PROTOINFO] = { .type = NLA_U32 },
78         [RTA_IIF]       = { .type = NLA_STRING,
79                             .maxlen = IFNAMSIZ, },
80 };
81
82 static int rule_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
83                            struct nlmsghdr *n, struct nl_parser_param *pp)
84 {
85         struct rtnl_rule *rule;
86         struct rtmsg *r;
87         struct nlattr *tb[RTA_MAX+1];
88         int err = 1;
89
90         rule = rtnl_rule_alloc();
91         if (!rule) {
92                 err = nl_errno(ENOMEM);
93                 goto errout;
94         }
95
96         rule->ce_msgtype = n->nlmsg_type;
97         r = nlmsg_data(n);
98
99         err = nlmsg_parse(n, sizeof(*r), tb, RTA_MAX, rule_policy);
100         if (err < 0)
101                 goto errout;
102
103         rule->r_family = r->rtm_family;
104         rule->r_type = r->rtm_type;
105         rule->r_dsfield = r->rtm_tos;
106         rule->r_src_len = r->rtm_src_len;
107         rule->r_dst_len = r->rtm_dst_len;
108         rule->r_table = r->rtm_table;
109         rule->ce_mask = (RULE_ATTR_FAMILY | RULE_ATTR_TYPE | RULE_ATTR_DSFIELD |
110                          RULE_ATTR_SRC_LEN | RULE_ATTR_DST_LEN |RULE_ATTR_TYPE);
111
112         if (tb[RTA_PRIORITY]) {
113                 rule->r_prio = nla_get_u32(tb[RTA_PRIORITY]);
114                 rule->ce_mask |= RULE_ATTR_PRIO;
115         }
116
117         if (tb[RTA_SRC]) {
118                 rule->r_src = nla_get_addr(tb[RTA_SRC], r->rtm_family);
119                 if (!rule->r_src) {
120                         err = nl_errno(ENOMEM);
121                         goto errout;
122                 }
123                 nl_addr_set_prefixlen(rule->r_src, r->rtm_src_len);
124                 rule->ce_mask |= RULE_ATTR_SRC;
125         }
126
127         if (tb[RTA_DST]) {
128                 rule->r_dst = nla_get_addr(tb[RTA_DST], r->rtm_family);
129                 if (!rule->r_dst) {
130                         err = nl_errno(ENOMEM);
131                         goto errout;
132                 }
133                 nl_addr_set_prefixlen(rule->r_dst, r->rtm_dst_len);
134                 rule->ce_mask |= RULE_ATTR_DST;
135         }
136
137         if (tb[RTA_PROTOINFO]) {
138                 rule->r_mark = nla_get_u32(tb[RTA_PROTOINFO]);
139                 rule->ce_mask |= RULE_ATTR_MARK;
140         }
141
142         if (tb[RTA_IIF]) {
143                 nla_strlcpy(rule->r_iif, tb[RTA_IIF], IFNAMSIZ);
144                 rule->ce_mask |= RULE_ATTR_IIF;
145         }
146
147         if (tb[RTA_FLOW]) {
148                 rule->r_realms = nla_get_u32(tb[RTA_FLOW]);
149                 rule->ce_mask |= RULE_ATTR_REALMS;
150         }
151
152         if (tb[RTA_GATEWAY]) {
153                 rule->r_srcmap = nla_get_addr(tb[RTA_GATEWAY], r->rtm_family);
154                 if (!rule->r_srcmap) {
155                         err = nl_errno(ENOMEM);
156                         goto errout;
157                 }
158                 rule->ce_mask |= RULE_ATTR_SRCMAP;
159         }
160
161         err = pp->pp_cb((struct nl_object *) rule, pp);
162         if (err < 0)
163                 goto errout;
164
165         err = P_ACCEPT;
166
167 errout:
168         rtnl_rule_put(rule);
169         return err;
170 }
171
172 static int rule_request_update(struct nl_cache *c, struct nl_handle *h)
173 {
174         return nl_rtgen_request(h, RTM_GETRULE, AF_UNSPEC, NLM_F_DUMP);
175 }
176
177 static int rule_dump_brief(struct nl_object *o, struct nl_dump_params *p)
178 {
179         struct rtnl_rule *r = (struct rtnl_rule *) o;
180         char buf[128];
181
182         if (r->ce_mask & RULE_ATTR_PRIO)
183                 dp_dump(p, "%d:\t", r->r_prio);
184         else
185                 dp_dump(p, "0:\t");
186
187         if (r->ce_mask & RULE_ATTR_SRC)
188                 dp_dump(p, "from %s ",
189                         nl_addr2str(r->r_src, buf, sizeof(buf)));
190         else if (r->ce_mask & RULE_ATTR_SRC_LEN && r->r_src_len)
191                 dp_dump(p, "from 0/%d ", r->r_src_len);
192
193         if (r->ce_mask & RULE_ATTR_DST)
194                 dp_dump(p, "to %s ",
195                         nl_addr2str(r->r_dst, buf, sizeof(buf)));
196         else if (r->ce_mask & RULE_ATTR_DST_LEN && r->r_dst_len)
197                 dp_dump(p, "to 0/%d ", r->r_dst_len);
198
199         if (r->ce_mask & RULE_ATTR_DSFIELD && r->r_dsfield)
200                 dp_dump(p, "tos %d ", r->r_dsfield);
201
202         if (r->ce_mask & RULE_ATTR_MARK)
203                 dp_dump(p, "mark %" PRIx64 , r->r_mark);
204
205         if (r->ce_mask & RULE_ATTR_IIF)
206                 dp_dump(p, "iif %s ", r->r_iif);
207
208         if (r->ce_mask & RULE_ATTR_TABLE)
209                 dp_dump(p, "lookup %s ",
210                         rtnl_route_table2str(r->r_table, buf, sizeof(buf)));
211
212         if (r->ce_mask & RULE_ATTR_REALMS)
213                 dp_dump(p, "realms %s ",
214                         rtnl_realms2str(r->r_realms, buf, sizeof(buf)));
215
216         dp_dump(p, "action %s\n",
217                 nl_rtntype2str(r->r_type, buf, sizeof(buf)));
218
219         return 1;
220 }
221
222 static int rule_dump_full(struct nl_object *obj, struct nl_dump_params *p)
223 {
224         struct rtnl_rule *rule = (struct rtnl_rule *) obj;
225         char buf[128];
226         int line;
227
228         line = rule_dump_brief(obj, p);
229
230         dp_dump_line(p, line++, "  family %s",
231                      nl_af2str(rule->r_family, buf, sizeof(buf)));
232
233         if (rule->ce_mask & RULE_ATTR_SRCMAP)
234                 dp_dump(p, " srcmap %s",
235                         nl_addr2str(rule->r_srcmap, buf, sizeof(buf)));
236
237         dp_dump(p, "\n");
238
239         return line;
240 }
241
242 static int rule_dump_stats(struct nl_object *obj, struct nl_dump_params *p)
243 {
244         return rule_dump_full(obj, p);
245 }
246
247 static int rule_dump_xml(struct nl_object *obj, struct nl_dump_params *p)
248 {
249         struct rtnl_rule *rule = (struct rtnl_rule *) obj;
250         char buf[128];
251         int line = 0;
252         
253         dp_dump_line(p, line++, "<rule>\n");
254
255         dp_dump_line(p, line++, "  <priority>%u</priority>\n",
256                      rule->r_prio);
257         dp_dump_line(p, line++, "  <family>%s</family>\n",
258                      nl_af2str(rule->r_family, buf, sizeof(buf)));
259
260         if (rule->ce_mask & RULE_ATTR_DST)
261                 dp_dump_line(p, line++, "  <dst>%s</dst>\n",
262                              nl_addr2str(rule->r_dst, buf, sizeof(buf)));
263
264         if (rule->ce_mask & RULE_ATTR_DST_LEN)
265                 dp_dump_line(p, line++, "  <dstlen>%u</dstlen>\n",
266                              rule->r_dst_len);
267
268         if (rule->ce_mask & RULE_ATTR_SRC)
269                 dp_dump_line(p, line++, "  <src>%s</src>\n",
270                              nl_addr2str(rule->r_src, buf, sizeof(buf)));
271
272         if (rule->ce_mask & RULE_ATTR_SRC_LEN)
273                 dp_dump_line(p, line++, "  <srclen>%u</srclen>\n",
274                              rule->r_src_len);
275
276         if (rule->ce_mask & RULE_ATTR_IIF)
277                 dp_dump_line(p, line++, "  <iif>%s</iif>\n", rule->r_iif);
278
279         if (rule->ce_mask & RULE_ATTR_TABLE)
280                 dp_dump_line(p, line++, "  <table>%u</table>\n",
281                              rule->r_table);
282
283         if (rule->ce_mask & RULE_ATTR_REALMS)
284                 dp_dump_line(p, line++, "  <realms>%u</realms>\n",
285                              rule->r_realms);
286
287         if (rule->ce_mask & RULE_ATTR_MARK)
288                 dp_dump_line(p, line++, "  <mark>%" PRIx64 "</mark>\n",
289                              rule->r_mark);
290
291         if (rule->ce_mask & RULE_ATTR_DSFIELD)
292                 dp_dump_line(p, line++, "  <dsfield>%u</dsfield>\n",
293                              rule->r_dsfield);
294
295         if (rule->ce_mask & RULE_ATTR_TYPE)
296                 dp_dump_line(p, line++, "<type>%s</type>\n",
297                              nl_rtntype2str(rule->r_type, buf, sizeof(buf)));
298
299         if (rule->ce_mask & RULE_ATTR_SRCMAP)
300                 dp_dump_line(p, line++, "<srcmap>%s</srcmap>\n",
301                              nl_addr2str(rule->r_srcmap, buf, sizeof(buf)));
302
303         dp_dump_line(p, line++, "</rule>\n");
304
305         return line;
306 }
307
308 static int rule_dump_env(struct nl_object *obj, struct nl_dump_params *p)
309 {
310         struct rtnl_rule *rule = (struct rtnl_rule *) obj;
311         char buf[128];
312         int line = 0;
313
314         dp_dump_line(p, line++, "RULE_PRIORITY=%u\n",
315                      rule->r_prio);
316         dp_dump_line(p, line++, "RULE_FAMILY=%s\n",
317                      nl_af2str(rule->r_family, buf, sizeof(buf)));
318
319         if (rule->ce_mask & RULE_ATTR_DST)
320                 dp_dump_line(p, line++, "RULE_DST=%s\n",
321                              nl_addr2str(rule->r_dst, buf, sizeof(buf)));
322
323         if (rule->ce_mask & RULE_ATTR_DST_LEN)
324                 dp_dump_line(p, line++, "RULE_DSTLEN=%u\n",
325                              rule->r_dst_len);
326
327         if (rule->ce_mask & RULE_ATTR_SRC)
328                 dp_dump_line(p, line++, "RULE_SRC=%s\n",
329                              nl_addr2str(rule->r_src, buf, sizeof(buf)));
330
331         if (rule->ce_mask & RULE_ATTR_SRC_LEN)
332                 dp_dump_line(p, line++, "RULE_SRCLEN=%u\n",
333                              rule->r_src_len);
334
335         if (rule->ce_mask & RULE_ATTR_IIF)
336                 dp_dump_line(p, line++, "RULE_IIF=%s\n", rule->r_iif);
337
338         if (rule->ce_mask & RULE_ATTR_TABLE)
339                 dp_dump_line(p, line++, "RULE_TABLE=%u\n",
340                              rule->r_table);
341
342         if (rule->ce_mask & RULE_ATTR_REALMS)
343                 dp_dump_line(p, line++, "RULE_REALM=%u\n",
344                              rule->r_realms);
345
346         if (rule->ce_mask & RULE_ATTR_MARK)
347                 dp_dump_line(p, line++, "RULE_MARK=0x%" PRIx64 "\n",
348                              rule->r_mark);
349
350         if (rule->ce_mask & RULE_ATTR_DSFIELD)
351                 dp_dump_line(p, line++, "RULE_DSFIELD=%u\n",
352                              rule->r_dsfield);
353
354         if (rule->ce_mask & RULE_ATTR_TYPE)
355                 dp_dump_line(p, line++, "RULE_TYPE=%s\n",
356                              nl_rtntype2str(rule->r_type, buf, sizeof(buf)));
357
358         if (rule->ce_mask & RULE_ATTR_SRCMAP)
359                 dp_dump_line(p, line++, "RULE_SRCMAP=%s\n",
360                              nl_addr2str(rule->r_srcmap, buf, sizeof(buf)));
361
362         return line;
363 }
364
365 static int rule_compare(struct nl_object *_a, struct nl_object *_b,
366                         uint32_t attrs, int flags)
367 {
368         struct rtnl_rule *a = (struct rtnl_rule *) _a;
369         struct rtnl_rule *b = (struct rtnl_rule *) _b;
370         int diff = 0;
371
372 #define RULE_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, RULE_ATTR_##ATTR, a, b, EXPR)
373
374         diff |= RULE_DIFF(FAMILY,       a->r_family != b->r_family);
375         diff |= RULE_DIFF(TABLE,        a->r_table != b->r_table);
376         diff |= RULE_DIFF(REALMS,       a->r_realms != b->r_realms);
377         diff |= RULE_DIFF(DSFIELD,      a->r_dsfield != b->r_dsfield);
378         diff |= RULE_DIFF(TYPE,         a->r_type != b->r_type);
379         diff |= RULE_DIFF(PRIO,         a->r_prio != b->r_prio);
380         diff |= RULE_DIFF(MARK,         a->r_mark != b->r_mark);
381         diff |= RULE_DIFF(SRC_LEN,      a->r_src_len != b->r_src_len);
382         diff |= RULE_DIFF(DST_LEN,      a->r_dst_len != b->r_dst_len);
383         diff |= RULE_DIFF(SRC,          nl_addr_cmp(a->r_src, b->r_src));
384         diff |= RULE_DIFF(DST,          nl_addr_cmp(a->r_dst, b->r_dst));
385         diff |= RULE_DIFF(IIF,          strcmp(a->r_iif, b->r_iif));
386         
387 #undef RULE_DIFF
388
389         return diff;
390 }
391
392 static struct trans_tbl rule_attrs[] = {
393         __ADD(RULE_ATTR_FAMILY, family)
394         __ADD(RULE_ATTR_PRIO, prio)
395         __ADD(RULE_ATTR_MARK, mark)
396         __ADD(RULE_ATTR_IIF, iif)
397         __ADD(RULE_ATTR_REALMS, realms)
398         __ADD(RULE_ATTR_SRC, src)
399         __ADD(RULE_ATTR_DST, dst)
400         __ADD(RULE_ATTR_DSFIELD, dsfield)
401         __ADD(RULE_ATTR_TABLE, table)
402         __ADD(RULE_ATTR_TYPE, type)
403         __ADD(RULE_ATTR_SRC_LEN, src_len)
404         __ADD(RULE_ATTR_DST_LEN, dst_len)
405         __ADD(RULE_ATTR_SRCMAP, srcmap)
406 };
407
408 static char *rule_attrs2str(int attrs, char *buf, size_t len)
409 {
410         return __flags2str(attrs, buf, len, rule_attrs,
411                            ARRAY_SIZE(rule_attrs));
412 }
413
414 /**
415  * @name Allocation/Freeing
416  * @{
417  */
418
419 struct rtnl_rule *rtnl_rule_alloc(void)
420 {
421         return (struct rtnl_rule *) nl_object_alloc(&rule_obj_ops);
422 }
423
424 void rtnl_rule_put(struct rtnl_rule *rule)
425 {
426         nl_object_put((struct nl_object *) rule);
427 }
428
429 /** @} */
430
431 /**
432  * @name Cache Management
433  * @{
434  */
435
436 /**
437  * Build a rule cache including all rules of the specified family currently configured in the kernel.
438  * @arg handle          netlink handle
439  * @arg family          address family
440  *
441  * Allocates a new rule cache, initializes it properly and updates it
442  * to include all rules of the specified address family currently
443  * configured in the kernel.
444  *
445  * @note The caller is responsible for destroying and freeing the
446  *       cache after using it. (nl_cache_destroy_and_free())
447  * @return The new cache or NULL if an error occured.
448  */
449 struct nl_cache * rtnl_rule_alloc_cache_by_family(struct nl_handle *handle,
450                                                   int family)
451 {
452         struct nl_cache * cache;
453
454         cache = nl_cache_alloc(&rtnl_rule_ops);
455         if (cache == NULL)
456                 return NULL;
457
458         /* XXX RULE_CACHE_FAMILY(cache) = family; */
459
460         if (handle && nl_cache_refill(handle, cache) < 0) {
461                 free(cache);
462                 return NULL;
463         }
464
465         return cache;
466 }
467
468 /**
469  * Build a rule cache including all rules currently configured in the kernel.
470  * @arg handle          netlink handle
471  *
472  * Allocates a new rule cache, initializes it properly and updates it
473  * to include all rules currently configured in the kernel.
474  *
475  * @note The caller is responsible for destroying and freeing the
476  *       cache after using it. (nl_cache_destroy_and_free())
477  * @return The new cache or NULL if an error occured.
478  */
479 struct nl_cache * rtnl_rule_alloc_cache(struct nl_handle *handle)
480 {
481         return rtnl_rule_alloc_cache_by_family(handle, AF_UNSPEC);
482 }
483
484 /** @} */
485
486 /**
487  * @name Rule Addition
488  * @{
489  */
490
491 static struct nl_msg *build_rule_msg(struct rtnl_rule *tmpl, int cmd, int flags)
492 {
493         struct nl_msg *msg;
494         struct rtmsg rtm = {
495                 .rtm_type = RTN_UNSPEC
496         };
497
498         if (cmd == RTM_NEWRULE)
499                 rtm.rtm_type = RTN_UNICAST;
500                 
501         if (tmpl->ce_mask & RULE_ATTR_FAMILY)
502                 rtm.rtm_family = tmpl->r_family;
503
504         if (tmpl->ce_mask & RULE_ATTR_TABLE)
505                 rtm.rtm_table = tmpl->r_table;
506
507         if (tmpl->ce_mask & RULE_ATTR_DSFIELD)
508                 rtm.rtm_tos = tmpl->r_dsfield;
509
510         if (tmpl->ce_mask & RULE_ATTR_TYPE)
511                 rtm.rtm_type = tmpl->r_type;
512
513         if (tmpl->ce_mask & RULE_ATTR_SRC_LEN)
514                 rtm.rtm_src_len = tmpl->r_src_len;
515
516         if (tmpl->ce_mask & RULE_ATTR_DST_LEN)
517                 rtm.rtm_dst_len = tmpl->r_dst_len;
518
519         msg = nlmsg_alloc_simple(cmd, flags);
520         if (!msg)
521                 goto nla_put_failure;
522
523         if (nlmsg_append(msg, &rtm, sizeof(rtm), NLMSG_ALIGNTO) < 0)
524                 goto nla_put_failure;
525
526         if (tmpl->ce_mask & RULE_ATTR_SRC)
527                 NLA_PUT_ADDR(msg, RTA_SRC, tmpl->r_src);
528
529         if (tmpl->ce_mask & RULE_ATTR_DST)
530                 NLA_PUT_ADDR(msg, RTA_DST, tmpl->r_dst);
531
532         if (tmpl->ce_mask & RULE_ATTR_PRIO)
533                 NLA_PUT_U32(msg, RTA_PRIORITY, tmpl->r_prio);
534
535         if (tmpl->ce_mask & RULE_ATTR_MARK)
536                 NLA_PUT_U32(msg, RTA_PROTOINFO, tmpl->r_mark);
537
538         if (tmpl->ce_mask & RULE_ATTR_REALMS)
539                 NLA_PUT_U32(msg, RTA_FLOW, tmpl->r_realms);
540
541         if (tmpl->ce_mask & RULE_ATTR_IIF)
542                 NLA_PUT_STRING(msg, RTA_IIF, tmpl->r_iif);
543
544         return msg;
545
546 nla_put_failure:
547         nlmsg_free(msg);
548         return NULL;
549 }
550
551 /**
552  * Build netlink request message to add a new rule
553  * @arg tmpl            template with data of new rule
554  * @arg flags           additional netlink message flags
555  *
556  * Builds a new netlink message requesting a addition of a new
557  * rule. The netlink message header isn't fully equipped with
558  * all relevant fields and must thus be sent out via nl_send_auto_complete()
559  * or supplemented as needed. \a tmpl must contain the attributes of the new
560  * address set via \c rtnl_rule_set_* functions.
561  * 
562  * @return The netlink message
563  */
564 struct nl_msg *rtnl_rule_build_add_request(struct rtnl_rule *tmpl, int flags)
565 {
566         return build_rule_msg(tmpl, RTM_NEWRULE, NLM_F_CREATE | flags);
567 }
568
569 /**
570  * Add a new rule
571  * @arg handle          netlink handle
572  * @arg tmpl            template with requested changes
573  * @arg flags           additional netlink message flags
574  *
575  * Builds a netlink message by calling rtnl_rule_build_add_request(),
576  * sends the request to the kernel and waits for the next ACK to be
577  * received and thus blocks until the request has been fullfilled.
578  *
579  * @return 0 on sucess or a negative error if an error occured.
580  */
581 int rtnl_rule_add(struct nl_handle *handle, struct rtnl_rule *tmpl, int flags)
582 {
583         int err;
584         struct nl_msg *msg;
585         
586         msg = rtnl_rule_build_add_request(tmpl, flags);
587         if (!msg)
588                 return nl_errno(ENOMEM);
589
590         err = nl_send_auto_complete(handle, msg);
591         if (err < 0)
592                 return err;
593
594         nlmsg_free(msg);
595         return nl_wait_for_ack(handle);
596 }
597
598 /** @} */
599
600 /**
601  * @name Rule Deletion
602  * @{
603  */
604
605 /**
606  * Build a netlink request message to delete a rule
607  * @arg rule            rule to delete
608  * @arg flags           additional netlink message flags
609  *
610  * Builds a new netlink message requesting a deletion of a rule.
611  * The netlink message header isn't fully equipped with all relevant
612  * fields and must thus be sent out via nl_send_auto_complete()
613  * or supplemented as needed. \a rule must point to an existing
614  * address.
615  *
616  * @return The netlink message
617  */
618 struct nl_msg *rtnl_rule_build_delete_request(struct rtnl_rule *rule, int flags)
619 {
620         return build_rule_msg(rule, RTM_DELRULE, flags);
621 }
622
623 /**
624  * Delete a rule
625  * @arg handle          netlink handle
626  * @arg rule            rule to delete
627  * @arg flags           additional netlink message flags
628  *
629  * Builds a netlink message by calling rtnl_rule_build_delete_request(),
630  * sends the request to the kernel and waits for the next ACK to be
631  * received and thus blocks until the request has been fullfilled.
632  *
633  * @return 0 on sucess or a negative error if an error occured.
634  */
635 int rtnl_rule_delete(struct nl_handle *handle, struct rtnl_rule *rule,
636                      int flags)
637 {
638         int err;
639         struct nl_msg *msg;
640         
641         msg = rtnl_rule_build_delete_request(rule, flags);
642         if (!msg)
643                 return nl_errno(ENOMEM);
644
645         err = nl_send_auto_complete(handle, msg);
646         if (err < 0)
647                 return err;
648
649         nlmsg_free(msg);
650         return nl_wait_for_ack(handle);
651 }
652
653 /** @} */
654
655 /**
656  * @name Attribute Modification
657  * @{
658  */
659
660 void rtnl_rule_set_family(struct rtnl_rule *rule, int family)
661 {
662         rule->r_family = family;
663         rule->ce_mask |= RULE_ATTR_FAMILY;
664 }
665
666 int rtnl_rule_get_family(struct rtnl_rule *rule)
667 {
668         if (rule->ce_mask & RULE_ATTR_FAMILY)
669                 return rule->r_family;
670         else
671                 return AF_UNSPEC;
672 }
673
674 void rtnl_rule_set_prio(struct rtnl_rule *rule, int prio)
675 {
676         rule->r_prio = prio;
677         rule->ce_mask |= RULE_ATTR_PRIO;
678 }
679
680 int rtnl_rule_get_prio(struct rtnl_rule *rule)
681 {
682         if (rule->ce_mask & RULE_ATTR_PRIO)
683                 return rule->r_prio;
684         else
685                 return -1;
686 }
687
688 void rtnl_rule_set_mark(struct rtnl_rule *rule, uint64_t mark)
689 {
690         rule->r_mark = mark;
691         rule->ce_mask |= RULE_ATTR_MARK;
692 }
693
694 uint64_t rtnl_rule_get_mark(struct rtnl_rule *rule)
695 {
696         if (rule->ce_mask & RULE_ATTR_MARK)
697                 return rule->r_mark;
698         else
699                 return UINT_LEAST64_MAX;
700 }
701
702 void rtnl_rule_set_table(struct rtnl_rule *rule, int table)
703 {
704         rule->r_table = table;
705         rule->ce_mask |= RULE_ATTR_TABLE;
706 }
707
708 int rtnl_rule_get_table(struct rtnl_rule *rule)
709 {
710         if (rule->ce_mask & RULE_ATTR_TABLE)
711                 return rule->r_table;
712         else
713                 return -1;
714 }
715
716 void rtnl_rule_set_dsfield(struct rtnl_rule *rule, int dsfield)
717 {
718         rule->r_dsfield = dsfield;
719         rule->ce_mask |= RULE_ATTR_DSFIELD;
720 }
721
722 int rtnl_rule_get_dsfield(struct rtnl_rule *rule)
723 {
724         if (rule->ce_mask & RULE_ATTR_DSFIELD)
725                 return rule->r_dsfield;
726         else
727                 return -1;
728 }
729
730 void rtnl_rule_set_src_len(struct rtnl_rule *rule, int len)
731 {
732         rule->r_src_len = len;
733         if (rule->ce_mask & RULE_ATTR_SRC)
734                 nl_addr_set_prefixlen(rule->r_src, len);
735         rule->ce_mask |= RULE_ATTR_SRC_LEN;
736 }
737
738 int rtnl_rule_get_src_len(struct rtnl_rule *rule)
739 {
740         if (rule->ce_mask & RULE_ATTR_SRC_LEN)
741                 return rule->r_src_len;
742         else
743                 return -1;
744 }
745
746 void rtnl_rule_set_dst_len(struct rtnl_rule *rule, int len)
747 {
748         rule->r_dst_len = len;
749         if (rule->ce_mask & RULE_ATTR_DST)
750                 nl_addr_set_prefixlen(rule->r_dst, len);
751         rule->ce_mask |= RULE_ATTR_DST_LEN;
752 }
753
754 int rtnl_rule_get_dst_len(struct rtnl_rule *rule)
755 {
756         if (rule->ce_mask & RULE_ATTR_DST_LEN)
757                 return rule->r_dst_len;
758         else
759                 return -1;
760 }
761
762 static inline int __assign_addr(struct rtnl_rule *rule, struct nl_addr **pos,
763                                 struct nl_addr *new, uint8_t *len, int flag)
764 {
765         if (rule->ce_mask & RULE_ATTR_FAMILY) {
766                 if (new->a_family != rule->r_family)
767                         return nl_error(EINVAL, "Address family mismatch");
768         } else
769                 rule->r_family = new->a_family;
770
771         if (*pos)
772                 nl_addr_put(*pos);
773
774         nl_addr_get(new);
775         *pos = new;
776         *len = nl_addr_get_prefixlen(new);
777
778         rule->ce_mask |= (flag | RULE_ATTR_FAMILY);
779
780         return 0;
781 }
782
783 int rtnl_rule_set_src(struct rtnl_rule *rule, struct nl_addr *src)
784 {
785         return __assign_addr(rule, &rule->r_src, src, &rule->r_src_len,
786                              RULE_ATTR_SRC | RULE_ATTR_SRC_LEN);
787 }
788
789 struct nl_addr *rtnl_rule_get_src(struct rtnl_rule *rule)
790 {
791         if (rule->ce_mask & RULE_ATTR_SRC)
792                 return rule->r_src;
793         else
794                 return NULL;
795 }
796
797 int rtnl_rule_set_dst(struct rtnl_rule *rule, struct nl_addr *dst)
798 {
799         return __assign_addr(rule, &rule->r_dst, dst, &rule->r_dst_len,
800                              RULE_ATTR_DST | RULE_ATTR_DST_LEN);
801 }
802
803 struct nl_addr *rtnl_rule_get_dst(struct rtnl_rule *rule)
804 {
805         if (rule->ce_mask & RULE_ATTR_DST)
806                 return rule->r_dst;
807         else
808                 return NULL;
809 }
810
811 int rtnl_rule_set_iif(struct rtnl_rule *rule, const char *dev)
812 {
813         if (strlen(dev) > IFNAMSIZ-1)
814                 return nl_errno(ERANGE);
815
816         strcpy(rule->r_iif, dev);
817         rule->ce_mask |= RULE_ATTR_IIF;
818         return 0;
819 }
820
821 char *rtnl_rule_get_iif(struct rtnl_rule *rule)
822 {
823         if (rule->ce_mask & RULE_ATTR_IIF)
824                 return rule->r_iif;
825         else
826                 return NULL;
827 }
828
829 void rtnl_rule_set_action(struct rtnl_rule *rule, int type)
830 {
831         rule->r_type = type;
832         rule->ce_mask |= RULE_ATTR_TYPE;
833 }
834
835 int rtnl_rule_get_action(struct rtnl_rule *rule)
836 {
837         if (rule->ce_mask & RULE_ATTR_TYPE)
838                 return rule->r_type;
839         else
840                 return nl_errno(ENOENT);
841 }
842
843 void rtnl_rule_set_realms(struct rtnl_rule *rule, realm_t realms)
844 {
845         rule->r_realms = realms;
846         rule->ce_mask |= RULE_ATTR_REALMS;
847 }
848
849 realm_t rtnl_rule_get_realms(struct rtnl_rule *rule)
850 {
851         if (rule->ce_mask & RULE_ATTR_REALMS)
852                 return rule->r_realms;
853         else
854                 return 0;
855 }
856
857 /** @} */
858
859 static struct nl_object_ops rule_obj_ops = {
860         .oo_name                = "route/rule",
861         .oo_size                = sizeof(struct rtnl_rule),
862         .oo_free_data           = rule_free_data,
863         .oo_clone               = rule_clone,
864         .oo_dump[NL_DUMP_BRIEF] = rule_dump_brief,
865         .oo_dump[NL_DUMP_FULL]  = rule_dump_full,
866         .oo_dump[NL_DUMP_STATS] = rule_dump_stats,
867         .oo_dump[NL_DUMP_XML]   = rule_dump_xml,
868         .oo_dump[NL_DUMP_ENV]   = rule_dump_env,
869         .oo_compare             = rule_compare,
870         .oo_attrs2str           = rule_attrs2str,
871         .oo_id_attrs            = ~0,
872 };
873
874 static struct nl_cache_ops rtnl_rule_ops = {
875         .co_name                = "route/rule",
876         .co_hdrsize             = sizeof(struct rtmsg),
877         .co_msgtypes            = {
878                                         { RTM_NEWRULE, NL_ACT_NEW, "new" },
879                                         { RTM_DELRULE, NL_ACT_DEL, "del" },
880                                         { RTM_GETRULE, NL_ACT_GET, "get" },
881                                         END_OF_MSGTYPES_LIST,
882                                   },
883         .co_protocol            = NETLINK_ROUTE,
884         .co_request_update      = rule_request_update,
885         .co_msg_parser          = rule_msg_parser,
886         .co_obj_ops             = &rule_obj_ops,
887 };
888
889 static void __init rule_init(void)
890 {
891         nl_cache_mngt_register(&rtnl_rule_ops);
892 }
893
894 static void __exit rule_exit(void)
895 {
896         nl_cache_mngt_unregister(&rtnl_rule_ops);
897 }
898
899 /** @} */