libnl 1.1
|
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 /** @} */