00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
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
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
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 return -NLE_NOMEM;
00064
00065 if (src->r_dst)
00066 if (!(dst->r_dst = nl_addr_clone(src->r_dst)))
00067 return -NLE_NOMEM;
00068
00069 return 0;
00070 }
00071
00072 static struct nla_policy rule_policy[RTA_MAX+1] = {
00073 [RTA_PRIORITY] = { .type = NLA_U32 },
00074 [RTA_FLOW] = { .type = NLA_U32 },
00075 [RTA_PROTOINFO] = { .type = NLA_U32 },
00076 [RTA_IIF] = { .type = NLA_STRING,
00077 .maxlen = IFNAMSIZ, },
00078 };
00079
00080 static int rule_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
00081 struct nlmsghdr *n, struct nl_parser_param *pp)
00082 {
00083 struct rtnl_rule *rule;
00084 struct rtmsg *r;
00085 struct nlattr *tb[RTA_MAX+1];
00086 int err = 1, family;
00087
00088 rule = rtnl_rule_alloc();
00089 if (!rule) {
00090 err = -NLE_NOMEM;
00091 goto errout;
00092 }
00093
00094 rule->ce_msgtype = n->nlmsg_type;
00095 r = nlmsg_data(n);
00096
00097 err = nlmsg_parse(n, sizeof(*r), tb, RTA_MAX, rule_policy);
00098 if (err < 0)
00099 goto errout;
00100
00101 rule->r_family = family = r->rtm_family;
00102 rule->r_type = r->rtm_type;
00103 rule->r_dsfield = r->rtm_tos;
00104 rule->r_src_len = r->rtm_src_len;
00105 rule->r_dst_len = r->rtm_dst_len;
00106 rule->r_table = r->rtm_table;
00107 rule->ce_mask = (RULE_ATTR_FAMILY | RULE_ATTR_TYPE | RULE_ATTR_DSFIELD |
00108 RULE_ATTR_SRC_LEN | RULE_ATTR_DST_LEN |RULE_ATTR_TYPE |
00109 RULE_ATTR_TABLE);
00110
00111 if (tb[RTA_PRIORITY]) {
00112 rule->r_prio = nla_get_u32(tb[RTA_PRIORITY]);
00113 rule->ce_mask |= RULE_ATTR_PRIO;
00114 }
00115
00116 if (tb[RTA_SRC]) {
00117 if (!(rule->r_src = nl_addr_alloc_attr(tb[RTA_SRC], family)))
00118 goto errout_enomem;
00119 nl_addr_set_prefixlen(rule->r_src, r->rtm_src_len);
00120 rule->ce_mask |= RULE_ATTR_SRC;
00121 }
00122
00123 if (tb[RTA_DST]) {
00124 if (!(rule->r_dst = nl_addr_alloc_attr(tb[RTA_DST], family)))
00125 goto errout_enomem;
00126 nl_addr_set_prefixlen(rule->r_dst, r->rtm_dst_len);
00127 rule->ce_mask |= RULE_ATTR_DST;
00128 }
00129
00130 if (tb[RTA_PROTOINFO]) {
00131 rule->r_mark = nla_get_u32(tb[RTA_PROTOINFO]);
00132 rule->ce_mask |= RULE_ATTR_MARK;
00133 }
00134
00135 if (tb[RTA_IIF]) {
00136 nla_strlcpy(rule->r_iif, tb[RTA_IIF], IFNAMSIZ);
00137 rule->ce_mask |= RULE_ATTR_IIF;
00138 }
00139
00140 if (tb[RTA_FLOW]) {
00141 rule->r_realms = nla_get_u32(tb[RTA_FLOW]);
00142 rule->ce_mask |= RULE_ATTR_REALMS;
00143 }
00144
00145 if (tb[RTA_GATEWAY]) {
00146 rule->r_srcmap = nl_addr_alloc_attr(tb[RTA_GATEWAY], family);
00147 if (!rule->r_srcmap)
00148 goto errout_enomem;
00149 rule->ce_mask |= RULE_ATTR_SRCMAP;
00150 }
00151
00152 if (tb[RTA_TABLE]) {
00153 rule->r_table = nla_get_u32(tb[RTA_TABLE]);
00154 rule->ce_mask |= RULE_ATTR_TABLE;
00155 }
00156
00157 err = pp->pp_cb((struct nl_object *) rule, pp);
00158 errout:
00159 rtnl_rule_put(rule);
00160 return err;
00161
00162 errout_enomem:
00163 err = -NLE_NOMEM;
00164 goto errout;
00165 }
00166
00167 static int rule_request_update(struct nl_cache *c, struct nl_sock *h)
00168 {
00169 return nl_rtgen_request(h, RTM_GETRULE, AF_UNSPEC, NLM_F_DUMP);
00170 }
00171
00172 static void rule_dump_line(struct nl_object *o, struct nl_dump_params *p)
00173 {
00174 struct rtnl_rule *r = (struct rtnl_rule *) o;
00175 char buf[128];
00176
00177 nl_dump_line(p, "%8d ", (r->ce_mask & RULE_ATTR_PRIO) ? r->r_prio : 0);
00178 nl_dump(p, "%s ", nl_af2str(r->r_family, buf, sizeof(buf)));
00179
00180 if (r->ce_mask & RULE_ATTR_SRC)
00181 nl_dump(p, "from %s ",
00182 nl_addr2str(r->r_src, buf, sizeof(buf)));
00183 else if (r->ce_mask & RULE_ATTR_SRC_LEN && r->r_src_len)
00184 nl_dump(p, "from 0/%d ", r->r_src_len);
00185
00186 if (r->ce_mask & RULE_ATTR_DST)
00187 nl_dump(p, "to %s ",
00188 nl_addr2str(r->r_dst, buf, sizeof(buf)));
00189 else if (r->ce_mask & RULE_ATTR_DST_LEN && r->r_dst_len)
00190 nl_dump(p, "to 0/%d ", r->r_dst_len);
00191
00192 if (r->ce_mask & RULE_ATTR_DSFIELD && r->r_dsfield)
00193 nl_dump(p, "tos %d ", r->r_dsfield);
00194
00195 if (r->ce_mask & RULE_ATTR_MARK)
00196 nl_dump(p, "mark %" PRIx64 , r->r_mark);
00197
00198 if (r->ce_mask & RULE_ATTR_IIF)
00199 nl_dump(p, "iif %s ", r->r_iif);
00200
00201 if (r->ce_mask & RULE_ATTR_TABLE)
00202 nl_dump(p, "lookup %s ",
00203 rtnl_route_table2str(r->r_table, buf, sizeof(buf)));
00204
00205 if (r->ce_mask & RULE_ATTR_REALMS)
00206 nl_dump(p, "realms %s ",
00207 rtnl_realms2str(r->r_realms, buf, sizeof(buf)));
00208
00209 nl_dump(p, "action %s\n",
00210 nl_rtntype2str(r->r_type, buf, sizeof(buf)));
00211 }
00212
00213 static void rule_dump_details(struct nl_object *obj, struct nl_dump_params *p)
00214 {
00215 struct rtnl_rule *rule = (struct rtnl_rule *) obj;
00216 char buf[128];
00217
00218 rule_dump_line(obj, p);
00219
00220 if (rule->ce_mask & RULE_ATTR_SRCMAP)
00221 nl_dump_line(p, " srcmap %s\n",
00222 nl_addr2str(rule->r_srcmap, buf, sizeof(buf)));
00223 }
00224
00225 static void rule_dump_stats(struct nl_object *obj, struct nl_dump_params *p)
00226 {
00227 rule_dump_details(obj, p);
00228 }
00229
00230 static void rule_dump_env(struct nl_object *obj, struct nl_dump_params *p)
00231 {
00232 struct rtnl_rule *rule = (struct rtnl_rule *) obj;
00233 char buf[128];
00234
00235 nl_dump_line(p, "RULE_PRIORITY=%u\n", rule->r_prio);
00236 nl_dump_line(p, "RULE_FAMILY=%s\n",
00237 nl_af2str(rule->r_family, buf, sizeof(buf)));
00238
00239 if (rule->ce_mask & RULE_ATTR_DST)
00240 nl_dump_line(p, "RULE_DST=%s\n",
00241 nl_addr2str(rule->r_dst, buf, sizeof(buf)));
00242
00243 if (rule->ce_mask & RULE_ATTR_DST_LEN)
00244 nl_dump_line(p, "RULE_DSTLEN=%u\n", rule->r_dst_len);
00245
00246 if (rule->ce_mask & RULE_ATTR_SRC)
00247 nl_dump_line(p, "RULE_SRC=%s\n",
00248 nl_addr2str(rule->r_src, buf, sizeof(buf)));
00249
00250 if (rule->ce_mask & RULE_ATTR_SRC_LEN)
00251 nl_dump_line(p, "RULE_SRCLEN=%u\n", rule->r_src_len);
00252
00253 if (rule->ce_mask & RULE_ATTR_IIF)
00254 nl_dump_line(p, "RULE_IIF=%s\n", rule->r_iif);
00255
00256 if (rule->ce_mask & RULE_ATTR_TABLE)
00257 nl_dump_line(p, "RULE_TABLE=%u\n", rule->r_table);
00258
00259 if (rule->ce_mask & RULE_ATTR_REALMS)
00260 nl_dump_line(p, "RULE_REALM=%u\n", rule->r_realms);
00261
00262 if (rule->ce_mask & RULE_ATTR_MARK)
00263 nl_dump_line(p, "RULE_MARK=0x%" PRIx64 "\n", rule->r_mark);
00264
00265 if (rule->ce_mask & RULE_ATTR_DSFIELD)
00266 nl_dump_line(p, "RULE_DSFIELD=%u\n", rule->r_dsfield);
00267
00268 if (rule->ce_mask & RULE_ATTR_TYPE)
00269 nl_dump_line(p, "RULE_TYPE=%s\n",
00270 nl_rtntype2str(rule->r_type, buf, sizeof(buf)));
00271
00272 if (rule->ce_mask & RULE_ATTR_SRCMAP)
00273 nl_dump_line(p, "RULE_SRCMAP=%s\n",
00274 nl_addr2str(rule->r_srcmap, buf, sizeof(buf)));
00275 }
00276
00277 static int rule_compare(struct nl_object *_a, struct nl_object *_b,
00278 uint32_t attrs, int flags)
00279 {
00280 struct rtnl_rule *a = (struct rtnl_rule *) _a;
00281 struct rtnl_rule *b = (struct rtnl_rule *) _b;
00282 int diff = 0;
00283
00284 #define RULE_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, RULE_ATTR_##ATTR, a, b, EXPR)
00285
00286 diff |= RULE_DIFF(FAMILY, a->r_family != b->r_family);
00287 diff |= RULE_DIFF(TABLE, a->r_table != b->r_table);
00288 diff |= RULE_DIFF(REALMS, a->r_realms != b->r_realms);
00289 diff |= RULE_DIFF(DSFIELD, a->r_dsfield != b->r_dsfield);
00290 diff |= RULE_DIFF(TYPE, a->r_type != b->r_type);
00291 diff |= RULE_DIFF(PRIO, a->r_prio != b->r_prio);
00292 diff |= RULE_DIFF(MARK, a->r_mark != b->r_mark);
00293 diff |= RULE_DIFF(SRC_LEN, a->r_src_len != b->r_src_len);
00294 diff |= RULE_DIFF(DST_LEN, a->r_dst_len != b->r_dst_len);
00295 diff |= RULE_DIFF(SRC, nl_addr_cmp(a->r_src, b->r_src));
00296 diff |= RULE_DIFF(DST, nl_addr_cmp(a->r_dst, b->r_dst));
00297 diff |= RULE_DIFF(IIF, strcmp(a->r_iif, b->r_iif));
00298
00299 #undef RULE_DIFF
00300
00301 return diff;
00302 }
00303
00304 static struct trans_tbl rule_attrs[] = {
00305 __ADD(RULE_ATTR_FAMILY, family)
00306 __ADD(RULE_ATTR_PRIO, prio)
00307 __ADD(RULE_ATTR_MARK, mark)
00308 __ADD(RULE_ATTR_IIF, iif)
00309 __ADD(RULE_ATTR_REALMS, realms)
00310 __ADD(RULE_ATTR_SRC, src)
00311 __ADD(RULE_ATTR_DST, dst)
00312 __ADD(RULE_ATTR_DSFIELD, dsfield)
00313 __ADD(RULE_ATTR_TABLE, table)
00314 __ADD(RULE_ATTR_TYPE, type)
00315 __ADD(RULE_ATTR_SRC_LEN, src_len)
00316 __ADD(RULE_ATTR_DST_LEN, dst_len)
00317 __ADD(RULE_ATTR_SRCMAP, srcmap)
00318 };
00319
00320 static char *rule_attrs2str(int attrs, char *buf, size_t len)
00321 {
00322 return __flags2str(attrs, buf, len, rule_attrs,
00323 ARRAY_SIZE(rule_attrs));
00324 }
00325
00326
00327
00328
00329
00330
00331 struct rtnl_rule *rtnl_rule_alloc(void)
00332 {
00333 return (struct rtnl_rule *) nl_object_alloc(&rule_obj_ops);
00334 }
00335
00336 void rtnl_rule_put(struct rtnl_rule *rule)
00337 {
00338 nl_object_put((struct nl_object *) rule);
00339 }
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359 int rtnl_rule_alloc_cache(struct nl_sock *sock, int family,
00360 struct nl_cache **result)
00361 {
00362 struct nl_cache * cache;
00363 int err;
00364
00365 if (!(cache = nl_cache_alloc(&rtnl_rule_ops)))
00366 return -NLE_NOMEM;
00367
00368 cache->c_iarg1 = family;
00369
00370 if (sock && (err = nl_cache_refill(sock, cache)) < 0) {
00371 free(cache);
00372 return err;
00373 }
00374
00375 *result = cache;
00376 return 0;
00377 }
00378
00379
00380
00381
00382
00383
00384
00385
00386 static int build_rule_msg(struct rtnl_rule *tmpl, int cmd, int flags,
00387 struct nl_msg **result)
00388 {
00389 struct nl_msg *msg;
00390 struct rtmsg rtm = {
00391 .rtm_type = RTN_UNSPEC
00392 };
00393
00394 if (cmd == RTM_NEWRULE)
00395 rtm.rtm_type = RTN_UNICAST;
00396
00397 if (tmpl->ce_mask & RULE_ATTR_FAMILY)
00398 rtm.rtm_family = tmpl->r_family;
00399
00400 if (tmpl->ce_mask & RULE_ATTR_TABLE)
00401 rtm.rtm_table = tmpl->r_table;
00402
00403 if (tmpl->ce_mask & RULE_ATTR_DSFIELD)
00404 rtm.rtm_tos = tmpl->r_dsfield;
00405
00406 if (tmpl->ce_mask & RULE_ATTR_TYPE)
00407 rtm.rtm_type = tmpl->r_type;
00408
00409 if (tmpl->ce_mask & RULE_ATTR_SRC_LEN)
00410 rtm.rtm_src_len = tmpl->r_src_len;
00411
00412 if (tmpl->ce_mask & RULE_ATTR_DST_LEN)
00413 rtm.rtm_dst_len = tmpl->r_dst_len;
00414
00415 msg = nlmsg_alloc_simple(cmd, flags);
00416 if (!msg)
00417 return -NLE_NOMEM;
00418
00419 if (nlmsg_append(msg, &rtm, sizeof(rtm), NLMSG_ALIGNTO) < 0)
00420 goto nla_put_failure;
00421
00422 if (tmpl->ce_mask & RULE_ATTR_SRC)
00423 NLA_PUT_ADDR(msg, RTA_SRC, tmpl->r_src);
00424
00425 if (tmpl->ce_mask & RULE_ATTR_DST)
00426 NLA_PUT_ADDR(msg, RTA_DST, tmpl->r_dst);
00427
00428 if (tmpl->ce_mask & RULE_ATTR_PRIO)
00429 NLA_PUT_U32(msg, RTA_PRIORITY, tmpl->r_prio);
00430
00431 if (tmpl->ce_mask & RULE_ATTR_MARK)
00432 NLA_PUT_U32(msg, RTA_PROTOINFO, tmpl->r_mark);
00433
00434 if (tmpl->ce_mask & RULE_ATTR_REALMS)
00435 NLA_PUT_U32(msg, RTA_FLOW, tmpl->r_realms);
00436
00437 if (tmpl->ce_mask & RULE_ATTR_IIF)
00438 NLA_PUT_STRING(msg, RTA_IIF, tmpl->r_iif);
00439
00440 *result = msg;
00441 return 0;
00442
00443 nla_put_failure:
00444 nlmsg_free(msg);
00445 return -NLE_MSGSIZE;
00446 }
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461 int rtnl_rule_build_add_request(struct rtnl_rule *tmpl, int flags,
00462 struct nl_msg **result)
00463 {
00464 return build_rule_msg(tmpl, RTM_NEWRULE, NLM_F_CREATE | flags,
00465 result);
00466 }
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480 int rtnl_rule_add(struct nl_sock *sk, struct rtnl_rule *tmpl, int flags)
00481 {
00482 struct nl_msg *msg;
00483 int err;
00484
00485 if ((err = rtnl_rule_build_add_request(tmpl, flags, &msg)) < 0)
00486 return err;
00487
00488 err = nl_send_auto_complete(sk, msg);
00489 nlmsg_free(msg);
00490 if (err < 0)
00491 return err;
00492
00493 return wait_for_ack(sk);
00494 }
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516 int rtnl_rule_build_delete_request(struct rtnl_rule *rule, int flags,
00517 struct nl_msg **result)
00518 {
00519 return build_rule_msg(rule, RTM_DELRULE, flags, result);
00520 }
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534 int rtnl_rule_delete(struct nl_sock *sk, struct rtnl_rule *rule, int flags)
00535 {
00536 struct nl_msg *msg;
00537 int err;
00538
00539 if ((err = rtnl_rule_build_delete_request(rule, flags, &msg)) < 0)
00540 return err;
00541
00542 err = nl_send_auto_complete(sk, msg);
00543 nlmsg_free(msg);
00544 if (err < 0)
00545 return err;
00546
00547 return wait_for_ack(sk);
00548 }
00549
00550
00551
00552
00553
00554
00555
00556
00557 void rtnl_rule_set_family(struct rtnl_rule *rule, int family)
00558 {
00559 rule->r_family = family;
00560 rule->ce_mask |= RULE_ATTR_FAMILY;
00561 }
00562
00563 int rtnl_rule_get_family(struct rtnl_rule *rule)
00564 {
00565 if (rule->ce_mask & RULE_ATTR_FAMILY)
00566 return rule->r_family;
00567 else
00568 return AF_UNSPEC;
00569 }
00570
00571 void rtnl_rule_set_prio(struct rtnl_rule *rule, int prio)
00572 {
00573 rule->r_prio = prio;
00574 rule->ce_mask |= RULE_ATTR_PRIO;
00575 }
00576
00577 int rtnl_rule_get_prio(struct rtnl_rule *rule)
00578 {
00579 if (rule->ce_mask & RULE_ATTR_PRIO)
00580 return rule->r_prio;
00581 else
00582 return -1;
00583 }
00584
00585 void rtnl_rule_set_mark(struct rtnl_rule *rule, uint64_t mark)
00586 {
00587 rule->r_mark = mark;
00588 rule->ce_mask |= RULE_ATTR_MARK;
00589 }
00590
00591 uint64_t rtnl_rule_get_mark(struct rtnl_rule *rule)
00592 {
00593 if (rule->ce_mask & RULE_ATTR_MARK)
00594 return rule->r_mark;
00595 else
00596 return UINT_LEAST64_MAX;
00597 }
00598
00599 void rtnl_rule_set_table(struct rtnl_rule *rule, int table)
00600 {
00601 rule->r_table = table;
00602 rule->ce_mask |= RULE_ATTR_TABLE;
00603 }
00604
00605 int rtnl_rule_get_table(struct rtnl_rule *rule)
00606 {
00607 if (rule->ce_mask & RULE_ATTR_TABLE)
00608 return rule->r_table;
00609 else
00610 return -1;
00611 }
00612
00613 void rtnl_rule_set_dsfield(struct rtnl_rule *rule, int dsfield)
00614 {
00615 rule->r_dsfield = dsfield;
00616 rule->ce_mask |= RULE_ATTR_DSFIELD;
00617 }
00618
00619 int rtnl_rule_get_dsfield(struct rtnl_rule *rule)
00620 {
00621 if (rule->ce_mask & RULE_ATTR_DSFIELD)
00622 return rule->r_dsfield;
00623 else
00624 return -1;
00625 }
00626
00627 void rtnl_rule_set_src_len(struct rtnl_rule *rule, int len)
00628 {
00629 rule->r_src_len = len;
00630 if (rule->ce_mask & RULE_ATTR_SRC)
00631 nl_addr_set_prefixlen(rule->r_src, len);
00632 rule->ce_mask |= RULE_ATTR_SRC_LEN;
00633 }
00634
00635 int rtnl_rule_get_src_len(struct rtnl_rule *rule)
00636 {
00637 if (rule->ce_mask & RULE_ATTR_SRC_LEN)
00638 return rule->r_src_len;
00639 else
00640 return -1;
00641 }
00642
00643 void rtnl_rule_set_dst_len(struct rtnl_rule *rule, int len)
00644 {
00645 rule->r_dst_len = len;
00646 if (rule->ce_mask & RULE_ATTR_DST)
00647 nl_addr_set_prefixlen(rule->r_dst, len);
00648 rule->ce_mask |= RULE_ATTR_DST_LEN;
00649 }
00650
00651 int rtnl_rule_get_dst_len(struct rtnl_rule *rule)
00652 {
00653 if (rule->ce_mask & RULE_ATTR_DST_LEN)
00654 return rule->r_dst_len;
00655 else
00656 return -1;
00657 }
00658
00659 static inline int __assign_addr(struct rtnl_rule *rule, struct nl_addr **pos,
00660 struct nl_addr *new, uint8_t *len, int flag)
00661 {
00662 if (rule->ce_mask & RULE_ATTR_FAMILY) {
00663 if (new->a_family != rule->r_family)
00664 return -NLE_AF_MISMATCH;
00665 } else
00666 rule->r_family = new->a_family;
00667
00668 if (*pos)
00669 nl_addr_put(*pos);
00670
00671 nl_addr_get(new);
00672 *pos = new;
00673 *len = nl_addr_get_prefixlen(new);
00674
00675 rule->ce_mask |= (flag | RULE_ATTR_FAMILY);
00676
00677 return 0;
00678 }
00679
00680 int rtnl_rule_set_src(struct rtnl_rule *rule, struct nl_addr *src)
00681 {
00682 return __assign_addr(rule, &rule->r_src, src, &rule->r_src_len,
00683 RULE_ATTR_SRC | RULE_ATTR_SRC_LEN);
00684 }
00685
00686 struct nl_addr *rtnl_rule_get_src(struct rtnl_rule *rule)
00687 {
00688 if (rule->ce_mask & RULE_ATTR_SRC)
00689 return rule->r_src;
00690 else
00691 return NULL;
00692 }
00693
00694 int rtnl_rule_set_dst(struct rtnl_rule *rule, struct nl_addr *dst)
00695 {
00696 return __assign_addr(rule, &rule->r_dst, dst, &rule->r_dst_len,
00697 RULE_ATTR_DST | RULE_ATTR_DST_LEN);
00698 }
00699
00700 struct nl_addr *rtnl_rule_get_dst(struct rtnl_rule *rule)
00701 {
00702 if (rule->ce_mask & RULE_ATTR_DST)
00703 return rule->r_dst;
00704 else
00705 return NULL;
00706 }
00707
00708 int rtnl_rule_set_iif(struct rtnl_rule *rule, const char *dev)
00709 {
00710 if (strlen(dev) > IFNAMSIZ-1)
00711 return -NLE_RANGE;
00712
00713 strcpy(rule->r_iif, dev);
00714 rule->ce_mask |= RULE_ATTR_IIF;
00715 return 0;
00716 }
00717
00718 char *rtnl_rule_get_iif(struct rtnl_rule *rule)
00719 {
00720 if (rule->ce_mask & RULE_ATTR_IIF)
00721 return rule->r_iif;
00722 else
00723 return NULL;
00724 }
00725
00726 void rtnl_rule_set_action(struct rtnl_rule *rule, int type)
00727 {
00728 rule->r_type = type;
00729 rule->ce_mask |= RULE_ATTR_TYPE;
00730 }
00731
00732 int rtnl_rule_get_action(struct rtnl_rule *rule)
00733 {
00734 if (rule->ce_mask & RULE_ATTR_TYPE)
00735 return rule->r_type;
00736 else
00737 return -NLE_NOATTR;
00738 }
00739
00740 void rtnl_rule_set_realms(struct rtnl_rule *rule, uint32_t realms)
00741 {
00742 rule->r_realms = realms;
00743 rule->ce_mask |= RULE_ATTR_REALMS;
00744 }
00745
00746 uint32_t rtnl_rule_get_realms(struct rtnl_rule *rule)
00747 {
00748 if (rule->ce_mask & RULE_ATTR_REALMS)
00749 return rule->r_realms;
00750 else
00751 return 0;
00752 }
00753
00754
00755
00756 static struct nl_object_ops rule_obj_ops = {
00757 .oo_name = "route/rule",
00758 .oo_size = sizeof(struct rtnl_rule),
00759 .oo_free_data = rule_free_data,
00760 .oo_clone = rule_clone,
00761 .oo_dump = {
00762 [NL_DUMP_LINE] = rule_dump_line,
00763 [NL_DUMP_DETAILS] = rule_dump_details,
00764 [NL_DUMP_STATS] = rule_dump_stats,
00765 [NL_DUMP_ENV] = rule_dump_env,
00766 },
00767 .oo_compare = rule_compare,
00768 .oo_attrs2str = rule_attrs2str,
00769 .oo_id_attrs = ~0,
00770 };
00771
00772 static struct nl_cache_ops rtnl_rule_ops = {
00773 .co_name = "route/rule",
00774 .co_hdrsize = sizeof(struct rtmsg),
00775 .co_msgtypes = {
00776 { RTM_NEWRULE, NL_ACT_NEW, "new" },
00777 { RTM_DELRULE, NL_ACT_DEL, "del" },
00778 { RTM_GETRULE, NL_ACT_GET, "get" },
00779 END_OF_MSGTYPES_LIST,
00780 },
00781 .co_protocol = NETLINK_ROUTE,
00782 .co_request_update = rule_request_update,
00783 .co_msg_parser = rule_msg_parser,
00784 .co_obj_ops = &rule_obj_ops,
00785 };
00786
00787 static void __init rule_init(void)
00788 {
00789 nl_cache_mngt_register(&rtnl_rule_ops);
00790 }
00791
00792 static void __exit rule_exit(void)
00793 {
00794 nl_cache_mngt_unregister(&rtnl_rule_ops);
00795 }
00796
00797