libnl 1.1
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-2006 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_PRIO          0x0002
00029 #define RULE_ATTR_MARK          0x0004
00030 #define RULE_ATTR_IIF           0x0008
00031 #define RULE_ATTR_REALMS        0x0010
00032 #define RULE_ATTR_SRC           0x0020
00033 #define RULE_ATTR_DST           0x0040
00034 #define RULE_ATTR_DSFIELD       0x0080
00035 #define RULE_ATTR_TABLE         0x0100
00036 #define RULE_ATTR_TYPE          0x0200
00037 #define RULE_ATTR_SRC_LEN       0x0400
00038 #define RULE_ATTR_DST_LEN       0x0800
00039 #define RULE_ATTR_SRCMAP        0x1000
00040 
00041 static struct nl_cache_ops rtnl_rule_ops;
00042 static struct nl_object_ops rule_obj_ops;
00043 /** @endcond */
00044 
00045 static void rule_free_data(struct nl_object *c)
00046 {
00047         struct rtnl_rule *rule = nl_object_priv(c);
00048 
00049         if (!rule)
00050                 return;
00051 
00052         nl_addr_put(rule->r_src);
00053         nl_addr_put(rule->r_dst);
00054 }
00055 
00056 static int rule_clone(struct nl_object *_dst, struct nl_object *_src)
00057 {
00058         struct rtnl_rule *dst = nl_object_priv(_dst);
00059         struct rtnl_rule *src = nl_object_priv(_src);
00060 
00061         if (src->r_src)
00062                 if (!(dst->r_src = nl_addr_clone(src->r_src)))
00063                         goto errout;
00064 
00065         if (src->r_dst)
00066                 if (!(dst->r_dst = nl_addr_clone(src->r_dst)))
00067                         goto errout;
00068 
00069         return 0;
00070 errout:
00071         return nl_get_errno();
00072 }
00073 
00074 static struct nla_policy rule_policy[RTA_MAX+1] = {
00075         [RTA_PRIORITY]  = { .type = NLA_U32 },
00076         [RTA_FLOW]      = { .type = NLA_U32 },
00077         [RTA_PROTOINFO] = { .type = NLA_U32 },
00078         [RTA_IIF]       = { .type = NLA_STRING,
00079                             .maxlen = IFNAMSIZ, },
00080 };
00081 
00082 static int rule_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
00083                            struct nlmsghdr *n, struct nl_parser_param *pp)
00084 {
00085         struct rtnl_rule *rule;
00086         struct rtmsg *r;
00087         struct nlattr *tb[RTA_MAX+1];
00088         int err = 1;
00089 
00090         rule = rtnl_rule_alloc();
00091         if (!rule) {
00092                 err = nl_errno(ENOMEM);
00093                 goto errout;
00094         }
00095 
00096         rule->ce_msgtype = n->nlmsg_type;
00097         r = nlmsg_data(n);
00098 
00099         err = nlmsg_parse(n, sizeof(*r), tb, RTA_MAX, rule_policy);
00100         if (err < 0)
00101                 goto errout;
00102 
00103         rule->r_family = r->rtm_family;
00104         rule->r_type = r->rtm_type;
00105         rule->r_dsfield = r->rtm_tos;
00106         rule->r_src_len = r->rtm_src_len;
00107         rule->r_dst_len = r->rtm_dst_len;
00108         rule->r_table = r->rtm_table;
00109         rule->ce_mask = (RULE_ATTR_FAMILY | RULE_ATTR_TYPE | RULE_ATTR_DSFIELD |
00110                          RULE_ATTR_SRC_LEN | RULE_ATTR_DST_LEN |RULE_ATTR_TYPE);
00111 
00112         if (tb[RTA_PRIORITY]) {
00113                 rule->r_prio = nla_get_u32(tb[RTA_PRIORITY]);
00114                 rule->ce_mask |= RULE_ATTR_PRIO;
00115         }
00116 
00117         if (tb[RTA_SRC]) {
00118                 rule->r_src = nla_get_addr(tb[RTA_SRC], r->rtm_family);
00119                 if (!rule->r_src) {
00120                         err = nl_errno(ENOMEM);
00121                         goto errout;
00122                 }
00123                 nl_addr_set_prefixlen(rule->r_src, r->rtm_src_len);
00124                 rule->ce_mask |= RULE_ATTR_SRC;
00125         }
00126 
00127         if (tb[RTA_DST]) {
00128                 rule->r_dst = nla_get_addr(tb[RTA_DST], r->rtm_family);
00129                 if (!rule->r_dst) {
00130                         err = nl_errno(ENOMEM);
00131                         goto errout;
00132                 }
00133                 nl_addr_set_prefixlen(rule->r_dst, r->rtm_dst_len);
00134                 rule->ce_mask |= RULE_ATTR_DST;
00135         }
00136 
00137         if (tb[RTA_PROTOINFO]) {
00138                 rule->r_mark = nla_get_u32(tb[RTA_PROTOINFO]);
00139                 rule->ce_mask |= RULE_ATTR_MARK;
00140         }
00141 
00142         if (tb[RTA_IIF]) {
00143                 nla_strlcpy(rule->r_iif, tb[RTA_IIF], IFNAMSIZ);
00144                 rule->ce_mask |= RULE_ATTR_IIF;
00145         }
00146 
00147         if (tb[RTA_FLOW]) {
00148                 rule->r_realms = nla_get_u32(tb[RTA_FLOW]);
00149                 rule->ce_mask |= RULE_ATTR_REALMS;
00150         }
00151 
00152         if (tb[RTA_GATEWAY]) {
00153                 rule->r_srcmap = nla_get_addr(tb[RTA_GATEWAY], r->rtm_family);
00154                 if (!rule->r_srcmap) {
00155                         err = nl_errno(ENOMEM);
00156                         goto errout;
00157                 }
00158                 rule->ce_mask |= RULE_ATTR_SRCMAP;
00159         }
00160 
00161         err = pp->pp_cb((struct nl_object *) rule, pp);
00162         if (err < 0)
00163                 goto errout;
00164 
00165         err = P_ACCEPT;
00166 
00167 errout:
00168         rtnl_rule_put(rule);
00169         return err;
00170 }
00171 
00172 static int rule_request_update(struct nl_cache *c, struct nl_handle *h)
00173 {
00174         return nl_rtgen_request(h, RTM_GETRULE, AF_UNSPEC, NLM_F_DUMP);
00175 }
00176 
00177 static int rule_dump_brief(struct nl_object *o, struct nl_dump_params *p)
00178 {
00179         struct rtnl_rule *r = (struct rtnl_rule *) o;
00180         char buf[128];
00181 
00182         if (r->ce_mask & RULE_ATTR_PRIO)
00183                 dp_dump(p, "%d:\t", r->r_prio);
00184         else
00185                 dp_dump(p, "0:\t");
00186 
00187         if (r->ce_mask & RULE_ATTR_SRC)
00188                 dp_dump(p, "from %s ",
00189                         nl_addr2str(r->r_src, buf, sizeof(buf)));
00190         else if (r->ce_mask & RULE_ATTR_SRC_LEN && r->r_src_len)
00191                 dp_dump(p, "from 0/%d ", r->r_src_len);
00192 
00193         if (r->ce_mask & RULE_ATTR_DST)
00194                 dp_dump(p, "to %s ",
00195                         nl_addr2str(r->r_dst, buf, sizeof(buf)));
00196         else if (r->ce_mask & RULE_ATTR_DST_LEN && r->r_dst_len)
00197                 dp_dump(p, "to 0/%d ", r->r_dst_len);
00198 
00199         if (r->ce_mask & RULE_ATTR_DSFIELD && r->r_dsfield)
00200                 dp_dump(p, "tos %d ", r->r_dsfield);
00201 
00202         if (r->ce_mask & RULE_ATTR_MARK)
00203                 dp_dump(p, "mark %" PRIx64 , r->r_mark);
00204 
00205         if (r->ce_mask & RULE_ATTR_IIF)
00206                 dp_dump(p, "iif %s ", r->r_iif);
00207 
00208         if (r->ce_mask & RULE_ATTR_TABLE)
00209                 dp_dump(p, "lookup %s ",
00210                         rtnl_route_table2str(r->r_table, buf, sizeof(buf)));
00211 
00212         if (r->ce_mask & RULE_ATTR_REALMS)
00213                 dp_dump(p, "realms %s ",
00214                         rtnl_realms2str(r->r_realms, buf, sizeof(buf)));
00215 
00216         dp_dump(p, "action %s\n",
00217                 nl_rtntype2str(r->r_type, buf, sizeof(buf)));
00218 
00219         return 1;
00220 }
00221 
00222 static int rule_dump_full(struct nl_object *obj, struct nl_dump_params *p)
00223 {
00224         struct rtnl_rule *rule = (struct rtnl_rule *) obj;
00225         char buf[128];
00226         int line;
00227 
00228         line = rule_dump_brief(obj, p);
00229 
00230         dp_dump_line(p, line++, "  family %s",
00231                      nl_af2str(rule->r_family, buf, sizeof(buf)));
00232 
00233         if (rule->ce_mask & RULE_ATTR_SRCMAP)
00234                 dp_dump(p, " srcmap %s",
00235                         nl_addr2str(rule->r_srcmap, buf, sizeof(buf)));
00236 
00237         dp_dump(p, "\n");
00238 
00239         return line;
00240 }
00241 
00242 static int rule_dump_stats(struct nl_object *obj, struct nl_dump_params *p)
00243 {
00244         return rule_dump_full(obj, p);
00245 }
00246 
00247 static int rule_dump_xml(struct nl_object *obj, struct nl_dump_params *p)
00248 {
00249         struct rtnl_rule *rule = (struct rtnl_rule *) obj;
00250         char buf[128];
00251         int line = 0;
00252         
00253         dp_dump_line(p, line++, "<rule>\n");
00254 
00255         dp_dump_line(p, line++, "  <priority>%u</priority>\n",
00256                      rule->r_prio);
00257         dp_dump_line(p, line++, "  <family>%s</family>\n",
00258                      nl_af2str(rule->r_family, buf, sizeof(buf)));
00259 
00260         if (rule->ce_mask & RULE_ATTR_DST)
00261                 dp_dump_line(p, line++, "  <dst>%s</dst>\n",
00262                              nl_addr2str(rule->r_dst, buf, sizeof(buf)));
00263 
00264         if (rule->ce_mask & RULE_ATTR_DST_LEN)
00265                 dp_dump_line(p, line++, "  <dstlen>%u</dstlen>\n",
00266                              rule->r_dst_len);
00267 
00268         if (rule->ce_mask & RULE_ATTR_SRC)
00269                 dp_dump_line(p, line++, "  <src>%s</src>\n",
00270                              nl_addr2str(rule->r_src, buf, sizeof(buf)));
00271 
00272         if (rule->ce_mask & RULE_ATTR_SRC_LEN)
00273                 dp_dump_line(p, line++, "  <srclen>%u</srclen>\n",
00274                              rule->r_src_len);
00275 
00276         if (rule->ce_mask & RULE_ATTR_IIF)
00277                 dp_dump_line(p, line++, "  <iif>%s</iif>\n", rule->r_iif);
00278 
00279         if (rule->ce_mask & RULE_ATTR_TABLE)
00280                 dp_dump_line(p, line++, "  <table>%u</table>\n",
00281                              rule->r_table);
00282 
00283         if (rule->ce_mask & RULE_ATTR_REALMS)
00284                 dp_dump_line(p, line++, "  <realms>%u</realms>\n",
00285                              rule->r_realms);
00286 
00287         if (rule->ce_mask & RULE_ATTR_MARK)
00288                 dp_dump_line(p, line++, "  <mark>%" PRIx64 "</mark>\n",
00289                              rule->r_mark);
00290 
00291         if (rule->ce_mask & RULE_ATTR_DSFIELD)
00292                 dp_dump_line(p, line++, "  <dsfield>%u</dsfield>\n",
00293                              rule->r_dsfield);
00294 
00295         if (rule->ce_mask & RULE_ATTR_TYPE)
00296                 dp_dump_line(p, line++, "<type>%s</type>\n",
00297                              nl_rtntype2str(rule->r_type, buf, sizeof(buf)));
00298 
00299         if (rule->ce_mask & RULE_ATTR_SRCMAP)
00300                 dp_dump_line(p, line++, "<srcmap>%s</srcmap>\n",
00301                              nl_addr2str(rule->r_srcmap, buf, sizeof(buf)));
00302 
00303         dp_dump_line(p, line++, "</rule>\n");
00304 
00305         return line;
00306 }
00307 
00308 static int rule_dump_env(struct nl_object *obj, struct nl_dump_params *p)
00309 {
00310         struct rtnl_rule *rule = (struct rtnl_rule *) obj;
00311         char buf[128];
00312         int line = 0;
00313 
00314         dp_dump_line(p, line++, "RULE_PRIORITY=%u\n",
00315                      rule->r_prio);
00316         dp_dump_line(p, line++, "RULE_FAMILY=%s\n",
00317                      nl_af2str(rule->r_family, buf, sizeof(buf)));
00318 
00319         if (rule->ce_mask & RULE_ATTR_DST)
00320                 dp_dump_line(p, line++, "RULE_DST=%s\n",
00321                              nl_addr2str(rule->r_dst, buf, sizeof(buf)));
00322 
00323         if (rule->ce_mask & RULE_ATTR_DST_LEN)
00324                 dp_dump_line(p, line++, "RULE_DSTLEN=%u\n",
00325                              rule->r_dst_len);
00326 
00327         if (rule->ce_mask & RULE_ATTR_SRC)
00328                 dp_dump_line(p, line++, "RULE_SRC=%s\n",
00329                              nl_addr2str(rule->r_src, buf, sizeof(buf)));
00330 
00331         if (rule->ce_mask & RULE_ATTR_SRC_LEN)
00332                 dp_dump_line(p, line++, "RULE_SRCLEN=%u\n",
00333                              rule->r_src_len);
00334 
00335         if (rule->ce_mask & RULE_ATTR_IIF)
00336                 dp_dump_line(p, line++, "RULE_IIF=%s\n", rule->r_iif);
00337 
00338         if (rule->ce_mask & RULE_ATTR_TABLE)
00339                 dp_dump_line(p, line++, "RULE_TABLE=%u\n",
00340                              rule->r_table);
00341 
00342         if (rule->ce_mask & RULE_ATTR_REALMS)
00343                 dp_dump_line(p, line++, "RULE_REALM=%u\n",
00344                              rule->r_realms);
00345 
00346         if (rule->ce_mask & RULE_ATTR_MARK)
00347                 dp_dump_line(p, line++, "RULE_MARK=0x%" PRIx64 "\n",
00348                              rule->r_mark);
00349 
00350         if (rule->ce_mask & RULE_ATTR_DSFIELD)
00351                 dp_dump_line(p, line++, "RULE_DSFIELD=%u\n",
00352                              rule->r_dsfield);
00353 
00354         if (rule->ce_mask & RULE_ATTR_TYPE)
00355                 dp_dump_line(p, line++, "RULE_TYPE=%s\n",
00356                              nl_rtntype2str(rule->r_type, buf, sizeof(buf)));
00357 
00358         if (rule->ce_mask & RULE_ATTR_SRCMAP)
00359                 dp_dump_line(p, line++, "RULE_SRCMAP=%s\n",
00360                              nl_addr2str(rule->r_srcmap, buf, sizeof(buf)));
00361 
00362         return line;
00363 }
00364 
00365 static int rule_compare(struct nl_object *_a, struct nl_object *_b,
00366                         uint32_t attrs, int flags)
00367 {
00368         struct rtnl_rule *a = (struct rtnl_rule *) _a;
00369         struct rtnl_rule *b = (struct rtnl_rule *) _b;
00370         int diff = 0;
00371 
00372 #define RULE_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, RULE_ATTR_##ATTR, a, b, EXPR)
00373 
00374         diff |= RULE_DIFF(FAMILY,       a->r_family != b->r_family);
00375         diff |= RULE_DIFF(TABLE,        a->r_table != b->r_table);
00376         diff |= RULE_DIFF(REALMS,       a->r_realms != b->r_realms);
00377         diff |= RULE_DIFF(DSFIELD,      a->r_dsfield != b->r_dsfield);
00378         diff |= RULE_DIFF(TYPE,         a->r_type != b->r_type);
00379         diff |= RULE_DIFF(PRIO,         a->r_prio != b->r_prio);
00380         diff |= RULE_DIFF(MARK,         a->r_mark != b->r_mark);
00381         diff |= RULE_DIFF(SRC_LEN,      a->r_src_len != b->r_src_len);
00382         diff |= RULE_DIFF(DST_LEN,      a->r_dst_len != b->r_dst_len);
00383         diff |= RULE_DIFF(SRC,          nl_addr_cmp(a->r_src, b->r_src));
00384         diff |= RULE_DIFF(DST,          nl_addr_cmp(a->r_dst, b->r_dst));
00385         diff |= RULE_DIFF(IIF,          strcmp(a->r_iif, b->r_iif));
00386         
00387 #undef RULE_DIFF
00388 
00389         return diff;
00390 }
00391 
00392 static struct trans_tbl rule_attrs[] = {
00393         __ADD(RULE_ATTR_FAMILY, family)
00394         __ADD(RULE_ATTR_PRIO, prio)
00395         __ADD(RULE_ATTR_MARK, mark)
00396         __ADD(RULE_ATTR_IIF, iif)
00397         __ADD(RULE_ATTR_REALMS, realms)
00398         __ADD(RULE_ATTR_SRC, src)
00399         __ADD(RULE_ATTR_DST, dst)
00400         __ADD(RULE_ATTR_DSFIELD, dsfield)
00401         __ADD(RULE_ATTR_TABLE, table)
00402         __ADD(RULE_ATTR_TYPE, type)
00403         __ADD(RULE_ATTR_SRC_LEN, src_len)
00404         __ADD(RULE_ATTR_DST_LEN, dst_len)
00405         __ADD(RULE_ATTR_SRCMAP, srcmap)
00406 };
00407 
00408 static char *rule_attrs2str(int attrs, char *buf, size_t len)
00409 {
00410         return __flags2str(attrs, buf, len, rule_attrs,
00411                            ARRAY_SIZE(rule_attrs));
00412 }
00413 
00414 /**
00415  * @name Allocation/Freeing
00416  * @{
00417  */
00418 
00419 struct rtnl_rule *rtnl_rule_alloc(void)
00420 {
00421         return (struct rtnl_rule *) nl_object_alloc(&rule_obj_ops);
00422 }
00423 
00424 void rtnl_rule_put(struct rtnl_rule *rule)
00425 {
00426         nl_object_put((struct nl_object *) rule);
00427 }
00428 
00429 /** @} */
00430 
00431 /**
00432  * @name Cache Management
00433  * @{
00434  */
00435 
00436 /**
00437  * Build a rule cache including all rules of the specified family currently configured in the kernel.
00438  * @arg handle          netlink handle
00439  * @arg family          address family
00440  *
00441  * Allocates a new rule cache, initializes it properly and updates it
00442  * to include all rules of the specified address family currently
00443  * configured in the kernel.
00444  *
00445  * @note The caller is responsible for destroying and freeing the
00446  *       cache after using it. (nl_cache_destroy_and_free())
00447  * @return The new cache or NULL if an error occured.
00448  */
00449 struct nl_cache * rtnl_rule_alloc_cache_by_family(struct nl_handle *handle,
00450                                                   int family)
00451 {
00452         struct nl_cache * cache;
00453 
00454         cache = nl_cache_alloc(&rtnl_rule_ops);
00455         if (cache == NULL)
00456                 return NULL;
00457 
00458         /* XXX RULE_CACHE_FAMILY(cache) = family; */
00459 
00460         if (handle && nl_cache_refill(handle, cache) < 0) {
00461                 free(cache);
00462                 return NULL;
00463         }
00464 
00465         return cache;
00466 }
00467 
00468 /**
00469  * Build a rule cache including all rules currently configured in the kernel.
00470  * @arg handle          netlink handle
00471  *
00472  * Allocates a new rule cache, initializes it properly and updates it
00473  * to include all rules currently configured in the kernel.
00474  *
00475  * @note The caller is responsible for destroying and freeing the
00476  *       cache after using it. (nl_cache_destroy_and_free())
00477  * @return The new cache or NULL if an error occured.
00478  */
00479 struct nl_cache * rtnl_rule_alloc_cache(struct nl_handle *handle)
00480 {
00481         return rtnl_rule_alloc_cache_by_family(handle, AF_UNSPEC);
00482 }
00483 
00484 /** @} */
00485 
00486 /**
00487  * @name Rule Addition
00488  * @{
00489  */
00490 
00491 static struct nl_msg *build_rule_msg(struct rtnl_rule *tmpl, int cmd, int flags)
00492 {
00493         struct nl_msg *msg;
00494         struct rtmsg rtm = {
00495                 .rtm_type = RTN_UNSPEC
00496         };
00497 
00498         if (cmd == RTM_NEWRULE)
00499                 rtm.rtm_type = RTN_UNICAST;
00500                 
00501         if (tmpl->ce_mask & RULE_ATTR_FAMILY)
00502                 rtm.rtm_family = tmpl->r_family;
00503 
00504         if (tmpl->ce_mask & RULE_ATTR_TABLE)
00505                 rtm.rtm_table = tmpl->r_table;
00506 
00507         if (tmpl->ce_mask & RULE_ATTR_DSFIELD)
00508                 rtm.rtm_tos = tmpl->r_dsfield;
00509 
00510         if (tmpl->ce_mask & RULE_ATTR_TYPE)
00511                 rtm.rtm_type = tmpl->r_type;
00512 
00513         if (tmpl->ce_mask & RULE_ATTR_SRC_LEN)
00514                 rtm.rtm_src_len = tmpl->r_src_len;
00515 
00516         if (tmpl->ce_mask & RULE_ATTR_DST_LEN)
00517                 rtm.rtm_dst_len = tmpl->r_dst_len;
00518 
00519         msg = nlmsg_alloc_simple(cmd, flags);
00520         if (!msg)
00521                 goto nla_put_failure;
00522 
00523         if (nlmsg_append(msg, &rtm, sizeof(rtm), NLMSG_ALIGNTO) < 0)
00524                 goto nla_put_failure;
00525 
00526         if (tmpl->ce_mask & RULE_ATTR_SRC)
00527                 NLA_PUT_ADDR(msg, RTA_SRC, tmpl->r_src);
00528 
00529         if (tmpl->ce_mask & RULE_ATTR_DST)
00530                 NLA_PUT_ADDR(msg, RTA_DST, tmpl->r_dst);
00531 
00532         if (tmpl->ce_mask & RULE_ATTR_PRIO)
00533                 NLA_PUT_U32(msg, RTA_PRIORITY, tmpl->r_prio);
00534 
00535         if (tmpl->ce_mask & RULE_ATTR_MARK)
00536                 NLA_PUT_U32(msg, RTA_PROTOINFO, tmpl->r_mark);
00537 
00538         if (tmpl->ce_mask & RULE_ATTR_REALMS)
00539                 NLA_PUT_U32(msg, RTA_FLOW, tmpl->r_realms);
00540 
00541         if (tmpl->ce_mask & RULE_ATTR_IIF)
00542                 NLA_PUT_STRING(msg, RTA_IIF, tmpl->r_iif);
00543 
00544         return msg;
00545 
00546 nla_put_failure:
00547         nlmsg_free(msg);
00548         return NULL;
00549 }
00550 
00551 /**
00552  * Build netlink request message to add a new rule
00553  * @arg tmpl            template with data of new rule
00554  * @arg flags           additional netlink message flags
00555  *
00556  * Builds a new netlink message requesting a addition of a new
00557  * rule. The netlink message header isn't fully equipped with
00558  * all relevant fields and must thus be sent out via nl_send_auto_complete()
00559  * or supplemented as needed. \a tmpl must contain the attributes of the new
00560  * address set via \c rtnl_rule_set_* functions.
00561  * 
00562  * @return The netlink message
00563  */
00564 struct nl_msg *rtnl_rule_build_add_request(struct rtnl_rule *tmpl, int flags)
00565 {
00566         return build_rule_msg(tmpl, RTM_NEWRULE, NLM_F_CREATE | flags);
00567 }
00568 
00569 /**
00570  * Add a new rule
00571  * @arg handle          netlink handle
00572  * @arg tmpl            template with requested changes
00573  * @arg flags           additional netlink message flags
00574  *
00575  * Builds a netlink message by calling rtnl_rule_build_add_request(),
00576  * sends the request to the kernel and waits for the next ACK to be
00577  * received and thus blocks until the request has been fullfilled.
00578  *
00579  * @return 0 on sucess or a negative error if an error occured.
00580  */
00581 int rtnl_rule_add(struct nl_handle *handle, struct rtnl_rule *tmpl, int flags)
00582 {
00583         int err;
00584         struct nl_msg *msg;
00585         
00586         msg = rtnl_rule_build_add_request(tmpl, flags);
00587         if (!msg)
00588                 return nl_errno(ENOMEM);
00589 
00590         err = nl_send_auto_complete(handle, msg);
00591         if (err < 0)
00592                 return err;
00593 
00594         nlmsg_free(msg);
00595         return nl_wait_for_ack(handle);
00596 }
00597 
00598 /** @} */
00599 
00600 /**
00601  * @name Rule Deletion
00602  * @{
00603  */
00604 
00605 /**
00606  * Build a netlink request message to delete a rule
00607  * @arg rule            rule to delete
00608  * @arg flags           additional netlink message flags
00609  *
00610  * Builds a new netlink message requesting a deletion of a rule.
00611  * The netlink message header isn't fully equipped with all relevant
00612  * fields and must thus be sent out via nl_send_auto_complete()
00613  * or supplemented as needed. \a rule must point to an existing
00614  * address.
00615  *
00616  * @return The netlink message
00617  */
00618 struct nl_msg *rtnl_rule_build_delete_request(struct rtnl_rule *rule, int flags)
00619 {
00620         return build_rule_msg(rule, RTM_DELRULE, flags);
00621 }
00622 
00623 /**
00624  * Delete a rule
00625  * @arg handle          netlink handle
00626  * @arg rule            rule to delete
00627  * @arg flags           additional netlink message flags
00628  *
00629  * Builds a netlink message by calling rtnl_rule_build_delete_request(),
00630  * sends the request to the kernel and waits for the next ACK to be
00631  * received and thus blocks until the request has been fullfilled.
00632  *
00633  * @return 0 on sucess or a negative error if an error occured.
00634  */
00635 int rtnl_rule_delete(struct nl_handle *handle, struct rtnl_rule *rule,
00636                      int flags)
00637 {
00638         int err;
00639         struct nl_msg *msg;
00640         
00641         msg = rtnl_rule_build_delete_request(rule, flags);
00642         if (!msg)
00643                 return nl_errno(ENOMEM);
00644 
00645         err = nl_send_auto_complete(handle, msg);
00646         if (err < 0)
00647                 return err;
00648 
00649         nlmsg_free(msg);
00650         return nl_wait_for_ack(handle);
00651 }
00652 
00653 /** @} */
00654 
00655 /**
00656  * @name Attribute Modification
00657  * @{
00658  */
00659 
00660 void rtnl_rule_set_family(struct rtnl_rule *rule, int family)
00661 {
00662         rule->r_family = family;
00663         rule->ce_mask |= RULE_ATTR_FAMILY;
00664 }
00665 
00666 int rtnl_rule_get_family(struct rtnl_rule *rule)
00667 {
00668         if (rule->ce_mask & RULE_ATTR_FAMILY)
00669                 return rule->r_family;
00670         else
00671                 return AF_UNSPEC;
00672 }
00673 
00674 void rtnl_rule_set_prio(struct rtnl_rule *rule, int prio)
00675 {
00676         rule->r_prio = prio;
00677         rule->ce_mask |= RULE_ATTR_PRIO;
00678 }
00679 
00680 int rtnl_rule_get_prio(struct rtnl_rule *rule)
00681 {
00682         if (rule->ce_mask & RULE_ATTR_PRIO)
00683                 return rule->r_prio;
00684         else
00685                 return -1;
00686 }
00687 
00688 void rtnl_rule_set_mark(struct rtnl_rule *rule, uint64_t mark)
00689 {
00690         rule->r_mark = mark;
00691         rule->ce_mask |= RULE_ATTR_MARK;
00692 }
00693 
00694 uint64_t rtnl_rule_get_mark(struct rtnl_rule *rule)
00695 {
00696         if (rule->ce_mask & RULE_ATTR_MARK)
00697                 return rule->r_mark;
00698         else
00699                 return UINT_LEAST64_MAX;
00700 }
00701 
00702 void rtnl_rule_set_table(struct rtnl_rule *rule, int table)
00703 {
00704         rule->r_table = table;
00705         rule->ce_mask |= RULE_ATTR_TABLE;
00706 }
00707 
00708 int rtnl_rule_get_table(struct rtnl_rule *rule)
00709 {
00710         if (rule->ce_mask & RULE_ATTR_TABLE)
00711                 return rule->r_table;
00712         else
00713                 return -1;
00714 }
00715 
00716 void rtnl_rule_set_dsfield(struct rtnl_rule *rule, int dsfield)
00717 {
00718         rule->r_dsfield = dsfield;
00719         rule->ce_mask |= RULE_ATTR_DSFIELD;
00720 }
00721 
00722 int rtnl_rule_get_dsfield(struct rtnl_rule *rule)
00723 {
00724         if (rule->ce_mask & RULE_ATTR_DSFIELD)
00725                 return rule->r_dsfield;
00726         else
00727                 return -1;
00728 }
00729 
00730 void rtnl_rule_set_src_len(struct rtnl_rule *rule, int len)
00731 {
00732         rule->r_src_len = len;
00733         if (rule->ce_mask & RULE_ATTR_SRC)
00734                 nl_addr_set_prefixlen(rule->r_src, len);
00735         rule->ce_mask |= RULE_ATTR_SRC_LEN;
00736 }
00737 
00738 int rtnl_rule_get_src_len(struct rtnl_rule *rule)
00739 {
00740         if (rule->ce_mask & RULE_ATTR_SRC_LEN)
00741                 return rule->r_src_len;
00742         else
00743                 return -1;
00744 }
00745 
00746 void rtnl_rule_set_dst_len(struct rtnl_rule *rule, int len)
00747 {
00748         rule->r_dst_len = len;
00749         if (rule->ce_mask & RULE_ATTR_DST)
00750                 nl_addr_set_prefixlen(rule->r_dst, len);
00751         rule->ce_mask |= RULE_ATTR_DST_LEN;
00752 }
00753 
00754 int rtnl_rule_get_dst_len(struct rtnl_rule *rule)
00755 {
00756         if (rule->ce_mask & RULE_ATTR_DST_LEN)
00757                 return rule->r_dst_len;
00758         else
00759                 return -1;
00760 }
00761 
00762 static inline int __assign_addr(struct rtnl_rule *rule, struct nl_addr **pos,
00763                                 struct nl_addr *new, uint8_t *len, int flag)
00764 {
00765         if (rule->ce_mask & RULE_ATTR_FAMILY) {
00766                 if (new->a_family != rule->r_family)
00767                         return nl_error(EINVAL, "Address family mismatch");
00768         } else
00769                 rule->r_family = new->a_family;
00770 
00771         if (*pos)
00772                 nl_addr_put(*pos);
00773 
00774         nl_addr_get(new);
00775         *pos = new;
00776         *len = nl_addr_get_prefixlen(new);
00777 
00778         rule->ce_mask |= (flag | RULE_ATTR_FAMILY);
00779 
00780         return 0;
00781 }
00782 
00783 int rtnl_rule_set_src(struct rtnl_rule *rule, struct nl_addr *src)
00784 {
00785         return __assign_addr(rule, &rule->r_src, src, &rule->r_src_len,
00786                              RULE_ATTR_SRC | RULE_ATTR_SRC_LEN);
00787 }
00788 
00789 struct nl_addr *rtnl_rule_get_src(struct rtnl_rule *rule)
00790 {
00791         if (rule->ce_mask & RULE_ATTR_SRC)
00792                 return rule->r_src;
00793         else
00794                 return NULL;
00795 }
00796 
00797 int rtnl_rule_set_dst(struct rtnl_rule *rule, struct nl_addr *dst)
00798 {
00799         return __assign_addr(rule, &rule->r_dst, dst, &rule->r_dst_len,
00800                              RULE_ATTR_DST | RULE_ATTR_DST_LEN);
00801 }
00802 
00803 struct nl_addr *rtnl_rule_get_dst(struct rtnl_rule *rule)
00804 {
00805         if (rule->ce_mask & RULE_ATTR_DST)
00806                 return rule->r_dst;
00807         else
00808                 return NULL;
00809 }
00810 
00811 int rtnl_rule_set_iif(struct rtnl_rule *rule, const char *dev)
00812 {
00813         if (strlen(dev) > IFNAMSIZ-1)
00814                 return nl_errno(ERANGE);
00815 
00816         strcpy(rule->r_iif, dev);
00817         rule->ce_mask |= RULE_ATTR_IIF;
00818         return 0;
00819 }
00820 
00821 char *rtnl_rule_get_iif(struct rtnl_rule *rule)
00822 {
00823         if (rule->ce_mask & RULE_ATTR_IIF)
00824                 return rule->r_iif;
00825         else
00826                 return NULL;
00827 }
00828 
00829 void rtnl_rule_set_action(struct rtnl_rule *rule, int type)
00830 {
00831         rule->r_type = type;
00832         rule->ce_mask |= RULE_ATTR_TYPE;
00833 }
00834 
00835 int rtnl_rule_get_action(struct rtnl_rule *rule)
00836 {
00837         if (rule->ce_mask & RULE_ATTR_TYPE)
00838                 return rule->r_type;
00839         else
00840                 return nl_errno(ENOENT);
00841 }
00842 
00843 void rtnl_rule_set_realms(struct rtnl_rule *rule, realm_t realms)
00844 {
00845         rule->r_realms = realms;
00846         rule->ce_mask |= RULE_ATTR_REALMS;
00847 }
00848 
00849 realm_t rtnl_rule_get_realms(struct rtnl_rule *rule)
00850 {
00851         if (rule->ce_mask & RULE_ATTR_REALMS)
00852                 return rule->r_realms;
00853         else
00854                 return 0;
00855 }
00856 
00857 /** @} */
00858 
00859 static struct nl_object_ops rule_obj_ops = {
00860         .oo_name                = "route/rule",
00861         .oo_size                = sizeof(struct rtnl_rule),
00862         .oo_free_data           = rule_free_data,
00863         .oo_clone               = rule_clone,
00864         .oo_dump[NL_DUMP_BRIEF] = rule_dump_brief,
00865         .oo_dump[NL_DUMP_FULL]  = rule_dump_full,
00866         .oo_dump[NL_DUMP_STATS] = rule_dump_stats,
00867         .oo_dump[NL_DUMP_XML]   = rule_dump_xml,
00868         .oo_dump[NL_DUMP_ENV]   = rule_dump_env,
00869         .oo_compare             = rule_compare,
00870         .oo_attrs2str           = rule_attrs2str,
00871         .oo_id_attrs            = ~0,
00872 };
00873 
00874 static struct nl_cache_ops rtnl_rule_ops = {
00875         .co_name                = "route/rule",
00876         .co_hdrsize             = sizeof(struct rtmsg),
00877         .co_msgtypes            = {
00878                                         { RTM_NEWRULE, NL_ACT_NEW, "new" },
00879                                         { RTM_DELRULE, NL_ACT_DEL, "del" },
00880                                         { RTM_GETRULE, NL_ACT_GET, "get" },
00881                                         END_OF_MSGTYPES_LIST,
00882                                   },
00883         .co_protocol            = NETLINK_ROUTE,
00884         .co_request_update      = rule_request_update,
00885         .co_msg_parser          = rule_msg_parser,
00886         .co_obj_ops             = &rule_obj_ops,
00887 };
00888 
00889 static void __init rule_init(void)
00890 {
00891         nl_cache_mngt_register(&rtnl_rule_ops);
00892 }
00893 
00894 static void __exit rule_exit(void)
00895 {
00896         nl_cache_mngt_unregister(&rtnl_rule_ops);
00897 }
00898 
00899 /** @} */