libnl 3.0
|
00001 /* 00002 * lib/route/rule.c Routing Rules 00003 * 00004 * This library is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU Lesser General Public 00006 * License as published by the Free Software Foundation version 2.1 00007 * of the License. 00008 * 00009 * Copyright (c) 2003-2010 Thomas Graf <tgraf@suug.ch> 00010 */ 00011 00012 /** 00013 * @ingroup rtnl 00014 * @defgroup rule Routing Rules 00015 * @brief 00016 * @{ 00017 */ 00018 00019 #include <netlink-local.h> 00020 #include <netlink/netlink.h> 00021 #include <netlink/utils.h> 00022 #include <netlink/route/rtnl.h> 00023 #include <netlink/route/rule.h> 00024 #include <inttypes.h> 00025 00026 /** @cond SKIP */ 00027 #define RULE_ATTR_FAMILY 0x0001 00028 #define RULE_ATTR_TABLE 0x0002 00029 #define RULE_ATTR_ACTION 0x0004 00030 #define RULE_ATTR_FLAGS 0x0008 00031 #define RULE_ATTR_IIFNAME 0x0010 00032 #define RULE_ATTR_OIFNAME 0x0020 00033 #define RULE_ATTR_PRIO 0x0040 00034 #define RULE_ATTR_MARK 0x0080 00035 #define RULE_ATTR_MASK 0x0100 00036 #define RULE_ATTR_GOTO 0x0200 00037 #define RULE_ATTR_SRC 0x0400 00038 #define RULE_ATTR_DST 0x0800 00039 #define RULE_ATTR_DSFIELD 0x1000 00040 #define RULE_ATTR_FLOW 0x2000 00041 00042 static struct nl_cache_ops rtnl_rule_ops; 00043 static struct nl_object_ops rule_obj_ops; 00044 /** @endcond */ 00045 00046 static void rule_free_data(struct nl_object *c) 00047 { 00048 struct rtnl_rule *rule = nl_object_priv(c); 00049 00050 if (!rule) 00051 return; 00052 00053 nl_addr_put(rule->r_src); 00054 nl_addr_put(rule->r_dst); 00055 } 00056 00057 static int rule_clone(struct nl_object *_dst, struct nl_object *_src) 00058 { 00059 struct rtnl_rule *dst = nl_object_priv(_dst); 00060 struct rtnl_rule *src = nl_object_priv(_src); 00061 00062 if (src->r_src) 00063 if (!(dst->r_src = nl_addr_clone(src->r_src))) 00064 return -NLE_NOMEM; 00065 00066 if (src->r_dst) 00067 if (!(dst->r_dst = nl_addr_clone(src->r_dst))) 00068 return -NLE_NOMEM; 00069 00070 return 0; 00071 } 00072 00073 static struct nla_policy rule_policy[FRA_MAX+1] = { 00074 [FRA_TABLE] = { .type = NLA_U32 }, 00075 [FRA_IIFNAME] = { .type = NLA_STRING, .maxlen = IFNAMSIZ }, 00076 [FRA_OIFNAME] = { .type = NLA_STRING, .maxlen = IFNAMSIZ }, 00077 [FRA_PRIORITY] = { .type = NLA_U32 }, 00078 [FRA_FWMARK] = { .type = NLA_U32 }, 00079 [FRA_FWMASK] = { .type = NLA_U32 }, 00080 [FRA_GOTO] = { .type = NLA_U32 }, 00081 [FRA_FLOW] = { .type = NLA_U32 }, 00082 }; 00083 00084 static int rule_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, 00085 struct nlmsghdr *n, struct nl_parser_param *pp) 00086 { 00087 struct rtnl_rule *rule; 00088 struct fib_rule_hdr *frh; 00089 struct nlattr *tb[FRA_MAX+1]; 00090 int err = 1, family; 00091 00092 rule = rtnl_rule_alloc(); 00093 if (!rule) { 00094 err = -NLE_NOMEM; 00095 goto errout; 00096 } 00097 00098 rule->ce_msgtype = n->nlmsg_type; 00099 frh = nlmsg_data(n); 00100 00101 err = nlmsg_parse(n, sizeof(*frh), tb, FRA_MAX, rule_policy); 00102 if (err < 0) 00103 goto errout; 00104 00105 rule->r_family = family = frh->family; 00106 rule->r_table = frh->table; 00107 rule->r_action = frh->action; 00108 rule->r_flags = frh->flags; 00109 00110 rule->ce_mask = (RULE_ATTR_FAMILY | RULE_ATTR_TABLE | RULE_ATTR_ACTION | 00111 RULE_ATTR_FLAGS); 00112 00113 /* ipv4 only */ 00114 if (frh->tos) { 00115 rule->r_dsfield = frh->tos; 00116 rule->ce_mask |= RULE_ATTR_DSFIELD; 00117 } 00118 00119 if (tb[FRA_TABLE]) { 00120 rule->r_table = nla_get_u32(tb[FRA_TABLE]); 00121 rule->ce_mask |= RULE_ATTR_TABLE; 00122 } 00123 00124 if (tb[FRA_IIFNAME]) { 00125 nla_strlcpy(rule->r_iifname, tb[FRA_IIFNAME], IFNAMSIZ); 00126 rule->ce_mask |= RULE_ATTR_IIFNAME; 00127 } 00128 00129 if (tb[FRA_OIFNAME]) { 00130 nla_strlcpy(rule->r_oifname, tb[FRA_OIFNAME], IFNAMSIZ); 00131 rule->ce_mask |= RULE_ATTR_OIFNAME; 00132 } 00133 00134 if (tb[FRA_PRIORITY]) { 00135 rule->r_prio = nla_get_u32(tb[FRA_PRIORITY]); 00136 rule->ce_mask |= RULE_ATTR_PRIO; 00137 } 00138 00139 if (tb[FRA_FWMARK]) { 00140 rule->r_mark = nla_get_u32(tb[FRA_FWMARK]); 00141 rule->ce_mask |= RULE_ATTR_MARK; 00142 } 00143 00144 if (tb[FRA_FWMASK]) { 00145 rule->r_mask = nla_get_u32(tb[FRA_FWMASK]); 00146 rule->ce_mask |= RULE_ATTR_MASK; 00147 } 00148 00149 if (tb[FRA_GOTO]) { 00150 rule->r_goto = nla_get_u32(tb[FRA_GOTO]); 00151 rule->ce_mask |= RULE_ATTR_GOTO; 00152 } 00153 00154 if (tb[FRA_SRC]) { 00155 if (!(rule->r_src = nl_addr_alloc_attr(tb[FRA_SRC], family))) 00156 goto errout_enomem; 00157 00158 nl_addr_set_prefixlen(rule->r_src, frh->src_len); 00159 rule->ce_mask |= RULE_ATTR_SRC; 00160 } 00161 00162 if (tb[FRA_DST]) { 00163 if (!(rule->r_dst = nl_addr_alloc_attr(tb[FRA_DST], family))) 00164 goto errout_enomem; 00165 nl_addr_set_prefixlen(rule->r_dst, frh->dst_len); 00166 rule->ce_mask |= RULE_ATTR_DST; 00167 } 00168 00169 /* ipv4 only */ 00170 if (tb[FRA_FLOW]) { 00171 rule->r_flow = nla_get_u32(tb[FRA_FLOW]); 00172 rule->ce_mask |= RULE_ATTR_FLOW; 00173 } 00174 00175 err = pp->pp_cb((struct nl_object *) rule, pp); 00176 errout: 00177 rtnl_rule_put(rule); 00178 return err; 00179 00180 errout_enomem: 00181 err = -NLE_NOMEM; 00182 goto errout; 00183 } 00184 00185 static int rule_request_update(struct nl_cache *c, struct nl_sock *h) 00186 { 00187 return nl_rtgen_request(h, RTM_GETRULE, AF_UNSPEC, NLM_F_DUMP); 00188 } 00189 00190 static void rule_dump_line(struct nl_object *o, struct nl_dump_params *p) 00191 { 00192 struct rtnl_rule *r = (struct rtnl_rule *) o; 00193 char buf[128]; 00194 00195 nl_dump_line(p, "%8d ", (r->ce_mask & RULE_ATTR_PRIO) ? r->r_prio : 0); 00196 nl_dump(p, "%s ", nl_af2str(r->r_family, buf, sizeof(buf))); 00197 00198 if (r->ce_mask & RULE_ATTR_SRC) 00199 nl_dump(p, "from %s ", 00200 nl_addr2str(r->r_src, buf, sizeof(buf))); 00201 00202 if (r->ce_mask & RULE_ATTR_DST) 00203 nl_dump(p, "to %s ", 00204 nl_addr2str(r->r_dst, buf, sizeof(buf))); 00205 00206 if (r->ce_mask & RULE_ATTR_DSFIELD) 00207 nl_dump(p, "tos %u ", r->r_dsfield); 00208 00209 if (r->ce_mask & (RULE_ATTR_MARK | RULE_ATTR_MASK)) 00210 nl_dump(p, "mark %#x/%#x", r->r_mark, r->r_mask); 00211 00212 if (r->ce_mask & RULE_ATTR_IIFNAME) 00213 nl_dump(p, "iif %s ", r->r_iifname); 00214 00215 if (r->ce_mask & RULE_ATTR_OIFNAME) 00216 nl_dump(p, "oif %s ", r->r_oifname); 00217 00218 if (r->ce_mask & RULE_ATTR_TABLE) 00219 nl_dump(p, "lookup %s ", 00220 rtnl_route_table2str(r->r_table, buf, sizeof(buf))); 00221 00222 if (r->ce_mask & RULE_ATTR_FLOW) 00223 nl_dump(p, "flow %s ", 00224 rtnl_realms2str(r->r_flow, buf, sizeof(buf))); 00225 00226 if (r->ce_mask & RULE_ATTR_GOTO) 00227 nl_dump(p, "goto %u ", r->r_goto); 00228 00229 if (r->ce_mask & RULE_ATTR_ACTION) 00230 nl_dump(p, "action %s", 00231 nl_rtntype2str(r->r_action, buf, sizeof(buf))); 00232 00233 nl_dump(p, "\n"); 00234 } 00235 00236 static void rule_dump_details(struct nl_object *obj, struct nl_dump_params *p) 00237 { 00238 rule_dump_line(obj, p); 00239 } 00240 00241 static void rule_dump_stats(struct nl_object *obj, struct nl_dump_params *p) 00242 { 00243 rule_dump_details(obj, p); 00244 } 00245 00246 #define RULE_ATTR_FLAGS 0x0008 00247 00248 static int rule_compare(struct nl_object *_a, struct nl_object *_b, 00249 uint32_t attrs, int flags) 00250 { 00251 struct rtnl_rule *a = (struct rtnl_rule *) _a; 00252 struct rtnl_rule *b = (struct rtnl_rule *) _b; 00253 int diff = 0; 00254 00255 #define RULE_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, RULE_ATTR_##ATTR, a, b, EXPR) 00256 00257 diff |= RULE_DIFF(FAMILY, a->r_family != b->r_family); 00258 diff |= RULE_DIFF(TABLE, a->r_table != b->r_table); 00259 diff |= RULE_DIFF(ACTION, a->r_action != b->r_action); 00260 diff |= RULE_DIFF(IIFNAME, strcmp(a->r_iifname, b->r_iifname)); 00261 diff |= RULE_DIFF(OIFNAME, strcmp(a->r_oifname, b->r_oifname)); 00262 diff |= RULE_DIFF(PRIO, a->r_prio != b->r_prio); 00263 diff |= RULE_DIFF(MARK, a->r_mark != b->r_mark); 00264 diff |= RULE_DIFF(MASK, a->r_mask != b->r_mask); 00265 diff |= RULE_DIFF(GOTO, a->r_goto != b->r_goto); 00266 diff |= RULE_DIFF(SRC, nl_addr_cmp(a->r_src, b->r_src)); 00267 diff |= RULE_DIFF(DST, nl_addr_cmp(a->r_dst, b->r_dst)); 00268 diff |= RULE_DIFF(DSFIELD, a->r_dsfield != b->r_dsfield); 00269 diff |= RULE_DIFF(FLOW, a->r_flow != b->r_flow); 00270 00271 #undef RULE_DIFF 00272 00273 return diff; 00274 } 00275 00276 static const struct trans_tbl rule_attrs[] = { 00277 __ADD(RULE_ATTR_FAMILY, family) 00278 __ADD(RULE_ATTR_TABLE, table) 00279 __ADD(RULE_ATTR_ACTION, action) 00280 __ADD(RULE_ATTR_IIFNAME, iifname) 00281 __ADD(RULE_ATTR_OIFNAME, oifname) 00282 __ADD(RULE_ATTR_PRIO, prio) 00283 __ADD(RULE_ATTR_MARK, mark) 00284 __ADD(RULE_ATTR_MASK, mask) 00285 __ADD(RULE_ATTR_GOTO, goto) 00286 __ADD(RULE_ATTR_SRC, src) 00287 __ADD(RULE_ATTR_DST, dst) 00288 __ADD(RULE_ATTR_DSFIELD, dsfield) 00289 __ADD(RULE_ATTR_FLOW, flow) 00290 }; 00291 00292 static char *rule_attrs2str(int attrs, char *buf, size_t len) 00293 { 00294 return __flags2str(attrs, buf, len, rule_attrs, 00295 ARRAY_SIZE(rule_attrs)); 00296 } 00297 00298 /** 00299 * @name Allocation/Freeing 00300 * @{ 00301 */ 00302 00303 struct rtnl_rule *rtnl_rule_alloc(void) 00304 { 00305 return (struct rtnl_rule *) nl_object_alloc(&rule_obj_ops); 00306 } 00307 00308 void rtnl_rule_put(struct rtnl_rule *rule) 00309 { 00310 nl_object_put((struct nl_object *) rule); 00311 } 00312 00313 /** @} */ 00314 00315 /** 00316 * @name Cache Management 00317 * @{ 00318 */ 00319 00320 /** 00321 * Build a rule cache including all rules currently configured in the kernel. 00322 * @arg sk Netlink socket. 00323 * @arg family Address family or AF_UNSPEC. 00324 * @arg result Pointer to store resulting cache. 00325 * 00326 * Allocates a new rule cache, initializes it properly and updates it 00327 * to include all rules currently configured in the kernel. 00328 * 00329 * @return 0 on success or a negative error code. 00330 */ 00331 int rtnl_rule_alloc_cache(struct nl_sock *sock, int family, 00332 struct nl_cache **result) 00333 { 00334 struct nl_cache * cache; 00335 int err; 00336 00337 if (!(cache = nl_cache_alloc(&rtnl_rule_ops))) 00338 return -NLE_NOMEM; 00339 00340 cache->c_iarg1 = family; 00341 00342 if (sock && (err = nl_cache_refill(sock, cache)) < 0) { 00343 free(cache); 00344 return err; 00345 } 00346 00347 *result = cache; 00348 return 0; 00349 } 00350 00351 /** @} */ 00352 00353 /** 00354 * @name Rule Addition 00355 * @{ 00356 */ 00357 00358 static int build_rule_msg(struct rtnl_rule *tmpl, int cmd, int flags, 00359 struct nl_msg **result) 00360 { 00361 struct nl_msg *msg; 00362 struct fib_rule_hdr frh = { 00363 .family = tmpl->r_family, 00364 .table = tmpl->r_table, 00365 .action = tmpl->r_action, 00366 .flags = tmpl->r_flags, 00367 .tos = tmpl->r_dsfield, 00368 }; 00369 00370 if (!(tmpl->ce_mask & RULE_ATTR_FAMILY)) 00371 return -NLE_MISSING_ATTR; 00372 00373 msg = nlmsg_alloc_simple(cmd, flags); 00374 if (!msg) 00375 return -NLE_NOMEM; 00376 00377 if (nlmsg_append(msg, &frh, sizeof(frh), NLMSG_ALIGNTO) < 0) 00378 goto nla_put_failure; 00379 00380 if (tmpl->ce_mask & RULE_ATTR_SRC) { 00381 frh.src_len = nl_addr_get_prefixlen(tmpl->r_src); 00382 NLA_PUT_ADDR(msg, FRA_SRC, tmpl->r_src); 00383 } 00384 00385 if (tmpl->ce_mask & RULE_ATTR_DST) { 00386 frh.dst_len = nl_addr_get_prefixlen(tmpl->r_dst); 00387 NLA_PUT_ADDR(msg, FRA_DST, tmpl->r_dst); 00388 } 00389 00390 if (tmpl->ce_mask & RULE_ATTR_IIFNAME) 00391 NLA_PUT_STRING(msg, FRA_IIFNAME, tmpl->r_iifname); 00392 00393 if (tmpl->ce_mask & RULE_ATTR_OIFNAME) 00394 NLA_PUT_STRING(msg, FRA_OIFNAME, tmpl->r_oifname); 00395 00396 if (tmpl->ce_mask & RULE_ATTR_PRIO) 00397 NLA_PUT_U32(msg, FRA_PRIORITY, tmpl->r_prio); 00398 00399 if (tmpl->ce_mask & RULE_ATTR_MARK) 00400 NLA_PUT_U32(msg, FRA_FWMARK, tmpl->r_mark); 00401 00402 if (tmpl->ce_mask & RULE_ATTR_MASK) 00403 NLA_PUT_U32(msg, FRA_FWMASK, tmpl->r_mask); 00404 00405 if (tmpl->ce_mask & RULE_ATTR_GOTO) 00406 NLA_PUT_U32(msg, FRA_GOTO, tmpl->r_goto); 00407 00408 if (tmpl->ce_mask & RULE_ATTR_FLOW) 00409 NLA_PUT_U32(msg, FRA_FLOW, tmpl->r_flow); 00410 00411 00412 *result = msg; 00413 return 0; 00414 00415 nla_put_failure: 00416 nlmsg_free(msg); 00417 return -NLE_MSGSIZE; 00418 } 00419 00420 /** 00421 * Build netlink request message to add a new rule 00422 * @arg tmpl template with data of new rule 00423 * @arg flags additional netlink message flags 00424 * 00425 * Builds a new netlink message requesting a addition of a new 00426 * rule. The netlink message header isn't fully equipped with 00427 * all relevant fields and must thus be sent out via nl_send_auto_complete() 00428 * or supplemented as needed. \a tmpl must contain the attributes of the new 00429 * address set via \c rtnl_rule_set_* functions. 00430 * 00431 * @return The netlink message 00432 */ 00433 int rtnl_rule_build_add_request(struct rtnl_rule *tmpl, int flags, 00434 struct nl_msg **result) 00435 { 00436 return build_rule_msg(tmpl, RTM_NEWRULE, NLM_F_CREATE | flags, 00437 result); 00438 } 00439 00440 /** 00441 * Add a new rule 00442 * @arg sk Netlink socket. 00443 * @arg tmpl template with requested changes 00444 * @arg flags additional netlink message flags 00445 * 00446 * Builds a netlink message by calling rtnl_rule_build_add_request(), 00447 * sends the request to the kernel and waits for the next ACK to be 00448 * received and thus blocks until the request has been fullfilled. 00449 * 00450 * @return 0 on sucess or a negative error if an error occured. 00451 */ 00452 int rtnl_rule_add(struct nl_sock *sk, struct rtnl_rule *tmpl, int flags) 00453 { 00454 struct nl_msg *msg; 00455 int err; 00456 00457 if ((err = rtnl_rule_build_add_request(tmpl, flags, &msg)) < 0) 00458 return err; 00459 00460 err = nl_send_auto_complete(sk, msg); 00461 nlmsg_free(msg); 00462 if (err < 0) 00463 return err; 00464 00465 return wait_for_ack(sk); 00466 } 00467 00468 /** @} */ 00469 00470 /** 00471 * @name Rule Deletion 00472 * @{ 00473 */ 00474 00475 /** 00476 * Build a netlink request message to delete a rule 00477 * @arg rule rule to delete 00478 * @arg flags additional netlink message flags 00479 * 00480 * Builds a new netlink message requesting a deletion of a rule. 00481 * The netlink message header isn't fully equipped with all relevant 00482 * fields and must thus be sent out via nl_send_auto_complete() 00483 * or supplemented as needed. \a rule must point to an existing 00484 * address. 00485 * 00486 * @return The netlink message 00487 */ 00488 int rtnl_rule_build_delete_request(struct rtnl_rule *rule, int flags, 00489 struct nl_msg **result) 00490 { 00491 return build_rule_msg(rule, RTM_DELRULE, flags, result); 00492 } 00493 00494 /** 00495 * Delete a rule 00496 * @arg sk Netlink socket. 00497 * @arg rule rule to delete 00498 * @arg flags additional netlink message flags 00499 * 00500 * Builds a netlink message by calling rtnl_rule_build_delete_request(), 00501 * sends the request to the kernel and waits for the next ACK to be 00502 * received and thus blocks until the request has been fullfilled. 00503 * 00504 * @return 0 on sucess or a negative error if an error occured. 00505 */ 00506 int rtnl_rule_delete(struct nl_sock *sk, struct rtnl_rule *rule, int flags) 00507 { 00508 struct nl_msg *msg; 00509 int err; 00510 00511 if ((err = rtnl_rule_build_delete_request(rule, flags, &msg)) < 0) 00512 return err; 00513 00514 err = nl_send_auto_complete(sk, msg); 00515 nlmsg_free(msg); 00516 if (err < 0) 00517 return err; 00518 00519 return wait_for_ack(sk); 00520 } 00521 00522 /** @} */ 00523 00524 /** 00525 * @name Attribute Modification 00526 * @{ 00527 */ 00528 00529 void rtnl_rule_set_family(struct rtnl_rule *rule, int family) 00530 { 00531 rule->r_family = family; 00532 rule->ce_mask |= RULE_ATTR_FAMILY; 00533 } 00534 00535 int rtnl_rule_get_family(struct rtnl_rule *rule) 00536 { 00537 if (rule->ce_mask & RULE_ATTR_FAMILY) 00538 return rule->r_family; 00539 else 00540 return AF_UNSPEC; 00541 } 00542 00543 void rtnl_rule_set_prio(struct rtnl_rule *rule, uint32_t prio) 00544 { 00545 rule->r_prio = prio; 00546 rule->ce_mask |= RULE_ATTR_PRIO; 00547 } 00548 00549 uint32_t rtnl_rule_get_prio(struct rtnl_rule *rule) 00550 { 00551 return rule->r_prio; 00552 } 00553 00554 void rtnl_rule_set_mark(struct rtnl_rule *rule, uint32_t mark) 00555 { 00556 rule->r_mark = mark; 00557 rule->ce_mask |= RULE_ATTR_MARK; 00558 } 00559 00560 uint32_t rtnl_rule_get_mark(struct rtnl_rule *rule) 00561 { 00562 return rule->r_mark; 00563 } 00564 00565 void rtnl_rule_set_mask(struct rtnl_rule *rule, uint32_t mask) 00566 { 00567 rule->r_mask = mask; 00568 rule->ce_mask |= RULE_ATTR_MASK; 00569 } 00570 00571 uint32_t rtnl_rule_get_mask(struct rtnl_rule *rule) 00572 { 00573 return rule->r_mask; 00574 } 00575 00576 void rtnl_rule_set_table(struct rtnl_rule *rule, uint32_t table) 00577 { 00578 rule->r_table = table; 00579 rule->ce_mask |= RULE_ATTR_TABLE; 00580 } 00581 00582 uint32_t rtnl_rule_get_table(struct rtnl_rule *rule) 00583 { 00584 return rule->r_table; 00585 } 00586 00587 void rtnl_rule_set_dsfield(struct rtnl_rule *rule, uint8_t dsfield) 00588 { 00589 rule->r_dsfield = dsfield; 00590 rule->ce_mask |= RULE_ATTR_DSFIELD; 00591 } 00592 00593 uint8_t rtnl_rule_get_dsfield(struct rtnl_rule *rule) 00594 { 00595 return rule->r_dsfield; 00596 } 00597 00598 static inline int __assign_addr(struct rtnl_rule *rule, struct nl_addr **pos, 00599 struct nl_addr *new, int flag) 00600 { 00601 if (rule->ce_mask & RULE_ATTR_FAMILY) { 00602 if (new->a_family != rule->r_family) 00603 return -NLE_AF_MISMATCH; 00604 } else 00605 rule->r_family = new->a_family; 00606 00607 if (*pos) 00608 nl_addr_put(*pos); 00609 00610 nl_addr_get(new); 00611 *pos = new; 00612 00613 rule->ce_mask |= (flag | RULE_ATTR_FAMILY); 00614 00615 return 0; 00616 } 00617 00618 int rtnl_rule_set_src(struct rtnl_rule *rule, struct nl_addr *src) 00619 { 00620 return __assign_addr(rule, &rule->r_src, src, RULE_ATTR_SRC); 00621 } 00622 00623 struct nl_addr *rtnl_rule_get_src(struct rtnl_rule *rule) 00624 { 00625 return rule->r_src; 00626 } 00627 00628 int rtnl_rule_set_dst(struct rtnl_rule *rule, struct nl_addr *dst) 00629 { 00630 return __assign_addr(rule, &rule->r_dst, dst, RULE_ATTR_DST); 00631 } 00632 00633 struct nl_addr *rtnl_rule_get_dst(struct rtnl_rule *rule) 00634 { 00635 return rule->r_dst; 00636 } 00637 00638 int rtnl_rule_set_iif(struct rtnl_rule *rule, const char *dev) 00639 { 00640 if (strlen(dev) > IFNAMSIZ-1) 00641 return -NLE_RANGE; 00642 00643 strcpy(rule->r_iifname, dev); 00644 rule->ce_mask |= RULE_ATTR_IIFNAME; 00645 return 0; 00646 } 00647 00648 char *rtnl_rule_get_iif(struct rtnl_rule *rule) 00649 { 00650 if (rule->ce_mask & RULE_ATTR_IIFNAME) 00651 return rule->r_iifname; 00652 else 00653 return NULL; 00654 } 00655 00656 int rtnl_rule_set_oif(struct rtnl_rule *rule, const char *dev) 00657 { 00658 if (strlen(dev) > IFNAMSIZ-1) 00659 return -NLE_RANGE; 00660 00661 strcpy(rule->r_oifname, dev); 00662 rule->ce_mask |= RULE_ATTR_OIFNAME; 00663 return 0; 00664 } 00665 00666 char *rtnl_rule_get_oif(struct rtnl_rule *rule) 00667 { 00668 if (rule->ce_mask & RULE_ATTR_OIFNAME) 00669 return rule->r_oifname; 00670 else 00671 return NULL; 00672 } 00673 00674 void rtnl_rule_set_action(struct rtnl_rule *rule, uint8_t action) 00675 { 00676 rule->r_action = action; 00677 rule->ce_mask |= RULE_ATTR_ACTION; 00678 } 00679 00680 uint8_t rtnl_rule_get_action(struct rtnl_rule *rule) 00681 { 00682 return rule->r_action; 00683 } 00684 00685 void rtnl_rule_set_realms(struct rtnl_rule *rule, uint32_t realms) 00686 { 00687 rule->r_flow = realms; 00688 rule->ce_mask |= RULE_ATTR_FLOW; 00689 } 00690 00691 uint32_t rtnl_rule_get_realms(struct rtnl_rule *rule) 00692 { 00693 return rule->r_flow; 00694 } 00695 00696 void rtnl_rule_set_goto(struct rtnl_rule *rule, uint32_t ref) 00697 { 00698 rule->r_goto = ref; 00699 rule->ce_mask |= RULE_ATTR_GOTO; 00700 } 00701 00702 uint32_t rtnl_rule_get_goto(struct rtnl_rule *rule) 00703 { 00704 return rule->r_goto; 00705 } 00706 00707 /** @} */ 00708 00709 static struct nl_object_ops rule_obj_ops = { 00710 .oo_name = "route/rule", 00711 .oo_size = sizeof(struct rtnl_rule), 00712 .oo_free_data = rule_free_data, 00713 .oo_clone = rule_clone, 00714 .oo_dump = { 00715 [NL_DUMP_LINE] = rule_dump_line, 00716 [NL_DUMP_DETAILS] = rule_dump_details, 00717 [NL_DUMP_STATS] = rule_dump_stats, 00718 }, 00719 .oo_compare = rule_compare, 00720 .oo_attrs2str = rule_attrs2str, 00721 .oo_id_attrs = ~0, 00722 }; 00723 00724 static struct nl_cache_ops rtnl_rule_ops = { 00725 .co_name = "route/rule", 00726 .co_hdrsize = sizeof(struct fib_rule_hdr), 00727 .co_msgtypes = { 00728 { RTM_NEWRULE, NL_ACT_NEW, "new" }, 00729 { RTM_DELRULE, NL_ACT_DEL, "del" }, 00730 { RTM_GETRULE, NL_ACT_GET, "get" }, 00731 END_OF_MSGTYPES_LIST, 00732 }, 00733 .co_protocol = NETLINK_ROUTE, 00734 .co_request_update = rule_request_update, 00735 .co_msg_parser = rule_msg_parser, 00736 .co_obj_ops = &rule_obj_ops, 00737 }; 00738 00739 static void __init rule_init(void) 00740 { 00741 nl_cache_mngt_register(&rtnl_rule_ops); 00742 } 00743 00744 static void __exit rule_exit(void) 00745 { 00746 nl_cache_mngt_unregister(&rtnl_rule_ops); 00747 } 00748 00749 /** @} */