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