libnl  3.2.3
/build/buildd/libnl3-3.2.3/lib/route/rule.c
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 /** @} */