libnl
3.2.3
|
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 sock 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 (tmpl->ce_mask & RULE_ATTR_SRC) 00378 frh.src_len = nl_addr_get_prefixlen(tmpl->r_src); 00379 00380 if (tmpl->ce_mask & RULE_ATTR_DST) 00381 frh.dst_len = nl_addr_get_prefixlen(tmpl->r_dst); 00382 00383 if (nlmsg_append(msg, &frh, sizeof(frh), NLMSG_ALIGNTO) < 0) 00384 goto nla_put_failure; 00385 00386 if (tmpl->ce_mask & RULE_ATTR_SRC) 00387 NLA_PUT_ADDR(msg, FRA_SRC, tmpl->r_src); 00388 00389 if (tmpl->ce_mask & RULE_ATTR_DST) 00390 NLA_PUT_ADDR(msg, FRA_DST, tmpl->r_dst); 00391 00392 if (tmpl->ce_mask & RULE_ATTR_IIFNAME) 00393 NLA_PUT_STRING(msg, FRA_IIFNAME, tmpl->r_iifname); 00394 00395 if (tmpl->ce_mask & RULE_ATTR_OIFNAME) 00396 NLA_PUT_STRING(msg, FRA_OIFNAME, tmpl->r_oifname); 00397 00398 if (tmpl->ce_mask & RULE_ATTR_PRIO) 00399 NLA_PUT_U32(msg, FRA_PRIORITY, tmpl->r_prio); 00400 00401 if (tmpl->ce_mask & RULE_ATTR_MARK) 00402 NLA_PUT_U32(msg, FRA_FWMARK, tmpl->r_mark); 00403 00404 if (tmpl->ce_mask & RULE_ATTR_MASK) 00405 NLA_PUT_U32(msg, FRA_FWMASK, tmpl->r_mask); 00406 00407 if (tmpl->ce_mask & RULE_ATTR_GOTO) 00408 NLA_PUT_U32(msg, FRA_GOTO, tmpl->r_goto); 00409 00410 if (tmpl->ce_mask & RULE_ATTR_FLOW) 00411 NLA_PUT_U32(msg, FRA_FLOW, tmpl->r_flow); 00412 00413 00414 *result = msg; 00415 return 0; 00416 00417 nla_put_failure: 00418 nlmsg_free(msg); 00419 return -NLE_MSGSIZE; 00420 } 00421 00422 /** 00423 * Build netlink request message to add a new rule 00424 * @arg tmpl template with data of new rule 00425 * @arg flags additional netlink message flags 00426 * @arg result Result pointer 00427 * 00428 * Builds a new netlink message requesting a addition of a new 00429 * rule. The netlink message header isn't fully equipped with 00430 * all relevant fields and must thus be sent out via nl_send_auto_complete() 00431 * or supplemented as needed. \a tmpl must contain the attributes of the new 00432 * address set via \c rtnl_rule_set_* functions. 00433 * 00434 * @return 0 on success or a negative error code. 00435 */ 00436 int rtnl_rule_build_add_request(struct rtnl_rule *tmpl, int flags, 00437 struct nl_msg **result) 00438 { 00439 return build_rule_msg(tmpl, RTM_NEWRULE, NLM_F_CREATE | flags, 00440 result); 00441 } 00442 00443 /** 00444 * Add a new rule 00445 * @arg sk Netlink socket. 00446 * @arg tmpl template with requested changes 00447 * @arg flags additional netlink message flags 00448 * 00449 * Builds a netlink message by calling rtnl_rule_build_add_request(), 00450 * sends the request to the kernel and waits for the next ACK to be 00451 * received and thus blocks until the request has been fullfilled. 00452 * 00453 * @return 0 on sucess or a negative error if an error occured. 00454 */ 00455 int rtnl_rule_add(struct nl_sock *sk, struct rtnl_rule *tmpl, int flags) 00456 { 00457 struct nl_msg *msg; 00458 int err; 00459 00460 if ((err = rtnl_rule_build_add_request(tmpl, flags, &msg)) < 0) 00461 return err; 00462 00463 err = nl_send_auto_complete(sk, msg); 00464 nlmsg_free(msg); 00465 if (err < 0) 00466 return err; 00467 00468 return wait_for_ack(sk); 00469 } 00470 00471 /** @} */ 00472 00473 /** 00474 * @name Rule Deletion 00475 * @{ 00476 */ 00477 00478 /** 00479 * Build a netlink request message to delete a rule 00480 * @arg rule rule to delete 00481 * @arg flags additional netlink message flags 00482 * @arg result Result pointer 00483 * 00484 * Builds a new netlink message requesting a deletion of a rule. 00485 * The netlink message header isn't fully equipped with all relevant 00486 * fields and must thus be sent out via nl_send_auto_complete() 00487 * or supplemented as needed. \a rule must point to an existing 00488 * address. 00489 * 00490 * @return 0 on success or a negative error code. 00491 */ 00492 int rtnl_rule_build_delete_request(struct rtnl_rule *rule, int flags, 00493 struct nl_msg **result) 00494 { 00495 return build_rule_msg(rule, RTM_DELRULE, flags, result); 00496 } 00497 00498 /** 00499 * Delete a rule 00500 * @arg sk Netlink socket. 00501 * @arg rule rule to delete 00502 * @arg flags additional netlink message flags 00503 * 00504 * Builds a netlink message by calling rtnl_rule_build_delete_request(), 00505 * sends the request to the kernel and waits for the next ACK to be 00506 * received and thus blocks until the request has been fullfilled. 00507 * 00508 * @return 0 on sucess or a negative error if an error occured. 00509 */ 00510 int rtnl_rule_delete(struct nl_sock *sk, struct rtnl_rule *rule, int flags) 00511 { 00512 struct nl_msg *msg; 00513 int err; 00514 00515 if ((err = rtnl_rule_build_delete_request(rule, flags, &msg)) < 0) 00516 return err; 00517 00518 err = nl_send_auto_complete(sk, msg); 00519 nlmsg_free(msg); 00520 if (err < 0) 00521 return err; 00522 00523 return wait_for_ack(sk); 00524 } 00525 00526 /** @} */ 00527 00528 /** 00529 * @name Attribute Modification 00530 * @{ 00531 */ 00532 00533 void rtnl_rule_set_family(struct rtnl_rule *rule, int family) 00534 { 00535 rule->r_family = family; 00536 rule->ce_mask |= RULE_ATTR_FAMILY; 00537 } 00538 00539 int rtnl_rule_get_family(struct rtnl_rule *rule) 00540 { 00541 if (rule->ce_mask & RULE_ATTR_FAMILY) 00542 return rule->r_family; 00543 else 00544 return AF_UNSPEC; 00545 } 00546 00547 void rtnl_rule_set_prio(struct rtnl_rule *rule, uint32_t prio) 00548 { 00549 rule->r_prio = prio; 00550 rule->ce_mask |= RULE_ATTR_PRIO; 00551 } 00552 00553 uint32_t rtnl_rule_get_prio(struct rtnl_rule *rule) 00554 { 00555 return rule->r_prio; 00556 } 00557 00558 void rtnl_rule_set_mark(struct rtnl_rule *rule, uint32_t mark) 00559 { 00560 rule->r_mark = mark; 00561 rule->ce_mask |= RULE_ATTR_MARK; 00562 } 00563 00564 uint32_t rtnl_rule_get_mark(struct rtnl_rule *rule) 00565 { 00566 return rule->r_mark; 00567 } 00568 00569 void rtnl_rule_set_mask(struct rtnl_rule *rule, uint32_t mask) 00570 { 00571 rule->r_mask = mask; 00572 rule->ce_mask |= RULE_ATTR_MASK; 00573 } 00574 00575 uint32_t rtnl_rule_get_mask(struct rtnl_rule *rule) 00576 { 00577 return rule->r_mask; 00578 } 00579 00580 void rtnl_rule_set_table(struct rtnl_rule *rule, uint32_t table) 00581 { 00582 rule->r_table = table; 00583 rule->ce_mask |= RULE_ATTR_TABLE; 00584 } 00585 00586 uint32_t rtnl_rule_get_table(struct rtnl_rule *rule) 00587 { 00588 return rule->r_table; 00589 } 00590 00591 void rtnl_rule_set_dsfield(struct rtnl_rule *rule, uint8_t dsfield) 00592 { 00593 rule->r_dsfield = dsfield; 00594 rule->ce_mask |= RULE_ATTR_DSFIELD; 00595 } 00596 00597 uint8_t rtnl_rule_get_dsfield(struct rtnl_rule *rule) 00598 { 00599 return rule->r_dsfield; 00600 } 00601 00602 static inline int __assign_addr(struct rtnl_rule *rule, struct nl_addr **pos, 00603 struct nl_addr *new, int flag) 00604 { 00605 if (rule->ce_mask & RULE_ATTR_FAMILY) { 00606 if (new->a_family != rule->r_family) 00607 return -NLE_AF_MISMATCH; 00608 } else 00609 rule->r_family = new->a_family; 00610 00611 if (*pos) 00612 nl_addr_put(*pos); 00613 00614 nl_addr_get(new); 00615 *pos = new; 00616 00617 rule->ce_mask |= (flag | RULE_ATTR_FAMILY); 00618 00619 return 0; 00620 } 00621 00622 int rtnl_rule_set_src(struct rtnl_rule *rule, struct nl_addr *src) 00623 { 00624 return __assign_addr(rule, &rule->r_src, src, RULE_ATTR_SRC); 00625 } 00626 00627 struct nl_addr *rtnl_rule_get_src(struct rtnl_rule *rule) 00628 { 00629 return rule->r_src; 00630 } 00631 00632 int rtnl_rule_set_dst(struct rtnl_rule *rule, struct nl_addr *dst) 00633 { 00634 return __assign_addr(rule, &rule->r_dst, dst, RULE_ATTR_DST); 00635 } 00636 00637 struct nl_addr *rtnl_rule_get_dst(struct rtnl_rule *rule) 00638 { 00639 return rule->r_dst; 00640 } 00641 00642 int rtnl_rule_set_iif(struct rtnl_rule *rule, const char *dev) 00643 { 00644 if (strlen(dev) > IFNAMSIZ-1) 00645 return -NLE_RANGE; 00646 00647 strcpy(rule->r_iifname, dev); 00648 rule->ce_mask |= RULE_ATTR_IIFNAME; 00649 return 0; 00650 } 00651 00652 char *rtnl_rule_get_iif(struct rtnl_rule *rule) 00653 { 00654 if (rule->ce_mask & RULE_ATTR_IIFNAME) 00655 return rule->r_iifname; 00656 else 00657 return NULL; 00658 } 00659 00660 int rtnl_rule_set_oif(struct rtnl_rule *rule, const char *dev) 00661 { 00662 if (strlen(dev) > IFNAMSIZ-1) 00663 return -NLE_RANGE; 00664 00665 strcpy(rule->r_oifname, dev); 00666 rule->ce_mask |= RULE_ATTR_OIFNAME; 00667 return 0; 00668 } 00669 00670 char *rtnl_rule_get_oif(struct rtnl_rule *rule) 00671 { 00672 if (rule->ce_mask & RULE_ATTR_OIFNAME) 00673 return rule->r_oifname; 00674 else 00675 return NULL; 00676 } 00677 00678 void rtnl_rule_set_action(struct rtnl_rule *rule, uint8_t action) 00679 { 00680 rule->r_action = action; 00681 rule->ce_mask |= RULE_ATTR_ACTION; 00682 } 00683 00684 uint8_t rtnl_rule_get_action(struct rtnl_rule *rule) 00685 { 00686 return rule->r_action; 00687 } 00688 00689 void rtnl_rule_set_realms(struct rtnl_rule *rule, uint32_t realms) 00690 { 00691 rule->r_flow = realms; 00692 rule->ce_mask |= RULE_ATTR_FLOW; 00693 } 00694 00695 uint32_t rtnl_rule_get_realms(struct rtnl_rule *rule) 00696 { 00697 return rule->r_flow; 00698 } 00699 00700 void rtnl_rule_set_goto(struct rtnl_rule *rule, uint32_t ref) 00701 { 00702 rule->r_goto = ref; 00703 rule->ce_mask |= RULE_ATTR_GOTO; 00704 } 00705 00706 uint32_t rtnl_rule_get_goto(struct rtnl_rule *rule) 00707 { 00708 return rule->r_goto; 00709 } 00710 00711 /** @} */ 00712 00713 static struct nl_object_ops rule_obj_ops = { 00714 .oo_name = "route/rule", 00715 .oo_size = sizeof(struct rtnl_rule), 00716 .oo_free_data = rule_free_data, 00717 .oo_clone = rule_clone, 00718 .oo_dump = { 00719 [NL_DUMP_LINE] = rule_dump_line, 00720 [NL_DUMP_DETAILS] = rule_dump_details, 00721 [NL_DUMP_STATS] = rule_dump_stats, 00722 }, 00723 .oo_compare = rule_compare, 00724 .oo_attrs2str = rule_attrs2str, 00725 .oo_id_attrs = ~0, 00726 }; 00727 00728 static struct nl_cache_ops rtnl_rule_ops = { 00729 .co_name = "route/rule", 00730 .co_hdrsize = sizeof(struct fib_rule_hdr), 00731 .co_msgtypes = { 00732 { RTM_NEWRULE, NL_ACT_NEW, "new" }, 00733 { RTM_DELRULE, NL_ACT_DEL, "del" }, 00734 { RTM_GETRULE, NL_ACT_GET, "get" }, 00735 END_OF_MSGTYPES_LIST, 00736 }, 00737 .co_protocol = NETLINK_ROUTE, 00738 .co_request_update = rule_request_update, 00739 .co_msg_parser = rule_msg_parser, 00740 .co_obj_ops = &rule_obj_ops, 00741 }; 00742 00743 static void __init rule_init(void) 00744 { 00745 nl_cache_mngt_register(&rtnl_rule_ops); 00746 } 00747 00748 static void __exit rule_exit(void) 00749 { 00750 nl_cache_mngt_unregister(&rtnl_rule_ops); 00751 } 00752 00753 /** @} */