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