rule.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757
  1. /*
  2. * lib/route/rule.c Routing Rules
  3. *
  4. * This library is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU Lesser General Public
  6. * License as published by the Free Software Foundation version 2.1
  7. * of the License.
  8. *
  9. * Copyright (c) 2003-2010 Thomas Graf <tgraf@suug.ch>
  10. */
  11. /**
  12. * @ingroup rtnl
  13. * @defgroup rule Routing Rules
  14. * @brief
  15. * @{
  16. */
  17. #include <netlink-private/netlink.h>
  18. #include <netlink/netlink.h>
  19. #include <netlink/utils.h>
  20. #include <netlink/route/rtnl.h>
  21. #include <netlink/route/rule.h>
  22. #include <inttypes.h>
  23. /** @cond SKIP */
  24. #define RULE_ATTR_FAMILY 0x0001
  25. #define RULE_ATTR_TABLE 0x0002
  26. #define RULE_ATTR_ACTION 0x0004
  27. #define RULE_ATTR_FLAGS 0x0008
  28. #define RULE_ATTR_IIFNAME 0x0010
  29. #define RULE_ATTR_OIFNAME 0x0020
  30. #define RULE_ATTR_PRIO 0x0040
  31. #define RULE_ATTR_MARK 0x0080
  32. #define RULE_ATTR_MASK 0x0100
  33. #define RULE_ATTR_GOTO 0x0200
  34. #define RULE_ATTR_SRC 0x0400
  35. #define RULE_ATTR_DST 0x0800
  36. #define RULE_ATTR_DSFIELD 0x1000
  37. #define RULE_ATTR_FLOW 0x2000
  38. static struct nl_cache_ops rtnl_rule_ops;
  39. static struct nl_object_ops rule_obj_ops;
  40. /** @endcond */
  41. static void rule_free_data(struct nl_object *c)
  42. {
  43. struct rtnl_rule *rule = nl_object_priv(c);
  44. if (!rule)
  45. return;
  46. nl_addr_put(rule->r_src);
  47. nl_addr_put(rule->r_dst);
  48. }
  49. static int rule_clone(struct nl_object *_dst, struct nl_object *_src)
  50. {
  51. struct rtnl_rule *dst = nl_object_priv(_dst);
  52. struct rtnl_rule *src = nl_object_priv(_src);
  53. if (src->r_src)
  54. if (!(dst->r_src = nl_addr_clone(src->r_src)))
  55. return -NLE_NOMEM;
  56. if (src->r_dst)
  57. if (!(dst->r_dst = nl_addr_clone(src->r_dst)))
  58. return -NLE_NOMEM;
  59. return 0;
  60. }
  61. static struct nla_policy rule_policy[FRA_MAX+1] = {
  62. [FRA_TABLE] = { .type = NLA_U32 },
  63. [FRA_IIFNAME] = { .type = NLA_STRING, .maxlen = IFNAMSIZ },
  64. [FRA_OIFNAME] = { .type = NLA_STRING, .maxlen = IFNAMSIZ },
  65. [FRA_PRIORITY] = { .type = NLA_U32 },
  66. [FRA_FWMARK] = { .type = NLA_U32 },
  67. [FRA_FWMASK] = { .type = NLA_U32 },
  68. [FRA_GOTO] = { .type = NLA_U32 },
  69. [FRA_FLOW] = { .type = NLA_U32 },
  70. };
  71. static int rule_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
  72. struct nlmsghdr *n, struct nl_parser_param *pp)
  73. {
  74. struct rtnl_rule *rule;
  75. struct fib_rule_hdr *frh;
  76. struct nlattr *tb[FRA_MAX+1];
  77. int err = 1, family;
  78. rule = rtnl_rule_alloc();
  79. if (!rule) {
  80. err = -NLE_NOMEM;
  81. goto errout;
  82. }
  83. rule->ce_msgtype = n->nlmsg_type;
  84. frh = nlmsg_data(n);
  85. err = nlmsg_parse(n, sizeof(*frh), tb, FRA_MAX, rule_policy);
  86. if (err < 0)
  87. goto errout;
  88. rule->r_family = family = frh->family;
  89. rule->r_table = frh->table;
  90. rule->r_action = frh->action;
  91. rule->r_flags = frh->flags;
  92. rule->ce_mask = (RULE_ATTR_FAMILY | RULE_ATTR_TABLE | RULE_ATTR_ACTION |
  93. RULE_ATTR_FLAGS);
  94. /* ipv4 only */
  95. if (frh->tos) {
  96. rule->r_dsfield = frh->tos;
  97. rule->ce_mask |= RULE_ATTR_DSFIELD;
  98. }
  99. if (tb[FRA_TABLE]) {
  100. rule->r_table = nla_get_u32(tb[FRA_TABLE]);
  101. rule->ce_mask |= RULE_ATTR_TABLE;
  102. }
  103. if (tb[FRA_IIFNAME]) {
  104. nla_strlcpy(rule->r_iifname, tb[FRA_IIFNAME], IFNAMSIZ);
  105. rule->ce_mask |= RULE_ATTR_IIFNAME;
  106. }
  107. if (tb[FRA_OIFNAME]) {
  108. nla_strlcpy(rule->r_oifname, tb[FRA_OIFNAME], IFNAMSIZ);
  109. rule->ce_mask |= RULE_ATTR_OIFNAME;
  110. }
  111. if (tb[FRA_PRIORITY]) {
  112. rule->r_prio = nla_get_u32(tb[FRA_PRIORITY]);
  113. rule->ce_mask |= RULE_ATTR_PRIO;
  114. }
  115. if (tb[FRA_FWMARK]) {
  116. rule->r_mark = nla_get_u32(tb[FRA_FWMARK]);
  117. rule->ce_mask |= RULE_ATTR_MARK;
  118. }
  119. if (tb[FRA_FWMASK]) {
  120. rule->r_mask = nla_get_u32(tb[FRA_FWMASK]);
  121. rule->ce_mask |= RULE_ATTR_MASK;
  122. }
  123. if (tb[FRA_GOTO]) {
  124. rule->r_goto = nla_get_u32(tb[FRA_GOTO]);
  125. rule->ce_mask |= RULE_ATTR_GOTO;
  126. }
  127. if (tb[FRA_SRC]) {
  128. if (!(rule->r_src = nl_addr_alloc_attr(tb[FRA_SRC], family)))
  129. goto errout_enomem;
  130. nl_addr_set_prefixlen(rule->r_src, frh->src_len);
  131. rule->ce_mask |= RULE_ATTR_SRC;
  132. }
  133. if (tb[FRA_DST]) {
  134. if (!(rule->r_dst = nl_addr_alloc_attr(tb[FRA_DST], family)))
  135. goto errout_enomem;
  136. nl_addr_set_prefixlen(rule->r_dst, frh->dst_len);
  137. rule->ce_mask |= RULE_ATTR_DST;
  138. }
  139. /* ipv4 only */
  140. if (tb[FRA_FLOW]) {
  141. rule->r_flow = nla_get_u32(tb[FRA_FLOW]);
  142. rule->ce_mask |= RULE_ATTR_FLOW;
  143. }
  144. err = pp->pp_cb((struct nl_object *) rule, pp);
  145. errout:
  146. rtnl_rule_put(rule);
  147. return err;
  148. errout_enomem:
  149. err = -NLE_NOMEM;
  150. goto errout;
  151. }
  152. static int rule_request_update(struct nl_cache *c, struct nl_sock *h)
  153. {
  154. return nl_rtgen_request(h, RTM_GETRULE, AF_UNSPEC, NLM_F_DUMP);
  155. }
  156. static void rule_dump_line(struct nl_object *o, struct nl_dump_params *p)
  157. {
  158. struct rtnl_rule *r = (struct rtnl_rule *) o;
  159. char buf[128];
  160. nl_dump_line(p, "%8d ", (r->ce_mask & RULE_ATTR_PRIO) ? r->r_prio : 0);
  161. nl_dump(p, "%s ", nl_af2str(r->r_family, buf, sizeof(buf)));
  162. if (r->ce_mask & RULE_ATTR_SRC)
  163. nl_dump(p, "from %s ",
  164. nl_addr2str(r->r_src, buf, sizeof(buf)));
  165. if (r->ce_mask & RULE_ATTR_DST)
  166. nl_dump(p, "to %s ",
  167. nl_addr2str(r->r_dst, buf, sizeof(buf)));
  168. if (r->ce_mask & RULE_ATTR_DSFIELD)
  169. nl_dump(p, "tos %u ", r->r_dsfield);
  170. if (r->ce_mask & (RULE_ATTR_MARK | RULE_ATTR_MASK))
  171. nl_dump(p, "mark %#x/%#x", r->r_mark, r->r_mask);
  172. if (r->ce_mask & RULE_ATTR_IIFNAME)
  173. nl_dump(p, "iif %s ", r->r_iifname);
  174. if (r->ce_mask & RULE_ATTR_OIFNAME)
  175. nl_dump(p, "oif %s ", r->r_oifname);
  176. if (r->ce_mask & RULE_ATTR_TABLE)
  177. nl_dump(p, "lookup %s ",
  178. rtnl_route_table2str(r->r_table, buf, sizeof(buf)));
  179. if (r->ce_mask & RULE_ATTR_FLOW)
  180. nl_dump(p, "flow %s ",
  181. rtnl_realms2str(r->r_flow, buf, sizeof(buf)));
  182. if (r->ce_mask & RULE_ATTR_GOTO)
  183. nl_dump(p, "goto %u ", r->r_goto);
  184. if (r->ce_mask & RULE_ATTR_ACTION)
  185. nl_dump(p, "action %s",
  186. nl_rtntype2str(r->r_action, buf, sizeof(buf)));
  187. nl_dump(p, "\n");
  188. }
  189. static void rule_dump_details(struct nl_object *obj, struct nl_dump_params *p)
  190. {
  191. rule_dump_line(obj, p);
  192. }
  193. static void rule_dump_stats(struct nl_object *obj, struct nl_dump_params *p)
  194. {
  195. rule_dump_details(obj, p);
  196. }
  197. #define RULE_ATTR_FLAGS 0x0008
  198. static int rule_compare(struct nl_object *_a, struct nl_object *_b,
  199. uint32_t attrs, int flags)
  200. {
  201. struct rtnl_rule *a = (struct rtnl_rule *) _a;
  202. struct rtnl_rule *b = (struct rtnl_rule *) _b;
  203. int diff = 0;
  204. #define RULE_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, RULE_ATTR_##ATTR, a, b, EXPR)
  205. diff |= RULE_DIFF(FAMILY, a->r_family != b->r_family);
  206. diff |= RULE_DIFF(TABLE, a->r_table != b->r_table);
  207. diff |= RULE_DIFF(ACTION, a->r_action != b->r_action);
  208. diff |= RULE_DIFF(IIFNAME, strcmp(a->r_iifname, b->r_iifname));
  209. diff |= RULE_DIFF(OIFNAME, strcmp(a->r_oifname, b->r_oifname));
  210. diff |= RULE_DIFF(PRIO, a->r_prio != b->r_prio);
  211. diff |= RULE_DIFF(MARK, a->r_mark != b->r_mark);
  212. diff |= RULE_DIFF(MASK, a->r_mask != b->r_mask);
  213. diff |= RULE_DIFF(GOTO, a->r_goto != b->r_goto);
  214. diff |= RULE_DIFF(SRC, nl_addr_cmp(a->r_src, b->r_src));
  215. diff |= RULE_DIFF(DST, nl_addr_cmp(a->r_dst, b->r_dst));
  216. diff |= RULE_DIFF(DSFIELD, a->r_dsfield != b->r_dsfield);
  217. diff |= RULE_DIFF(FLOW, a->r_flow != b->r_flow);
  218. #undef RULE_DIFF
  219. return diff;
  220. }
  221. static const struct trans_tbl rule_attrs[] = {
  222. __ADD(RULE_ATTR_FAMILY, family)
  223. __ADD(RULE_ATTR_TABLE, table)
  224. __ADD(RULE_ATTR_ACTION, action)
  225. __ADD(RULE_ATTR_IIFNAME, iifname)
  226. __ADD(RULE_ATTR_OIFNAME, oifname)
  227. __ADD(RULE_ATTR_PRIO, prio)
  228. __ADD(RULE_ATTR_MARK, mark)
  229. __ADD(RULE_ATTR_MASK, mask)
  230. __ADD(RULE_ATTR_GOTO, goto)
  231. __ADD(RULE_ATTR_SRC, src)
  232. __ADD(RULE_ATTR_DST, dst)
  233. __ADD(RULE_ATTR_DSFIELD, dsfield)
  234. __ADD(RULE_ATTR_FLOW, flow)
  235. };
  236. static char *rule_attrs2str(int attrs, char *buf, size_t len)
  237. {
  238. return __flags2str(attrs, buf, len, rule_attrs,
  239. ARRAY_SIZE(rule_attrs));
  240. }
  241. /**
  242. * @name Allocation/Freeing
  243. * @{
  244. */
  245. struct rtnl_rule *rtnl_rule_alloc(void)
  246. {
  247. return (struct rtnl_rule *) nl_object_alloc(&rule_obj_ops);
  248. }
  249. void rtnl_rule_put(struct rtnl_rule *rule)
  250. {
  251. nl_object_put((struct nl_object *) rule);
  252. }
  253. /** @} */
  254. /**
  255. * @name Cache Management
  256. * @{
  257. */
  258. /**
  259. * Build a rule cache including all rules currently configured in the kernel.
  260. * @arg sock Netlink socket.
  261. * @arg family Address family or AF_UNSPEC.
  262. * @arg result Pointer to store resulting cache.
  263. *
  264. * Allocates a new rule cache, initializes it properly and updates it
  265. * to include all rules currently configured in the kernel.
  266. *
  267. * @return 0 on success or a negative error code.
  268. */
  269. int rtnl_rule_alloc_cache(struct nl_sock *sock, int family,
  270. struct nl_cache **result)
  271. {
  272. struct nl_cache * cache;
  273. int err;
  274. if (!(cache = nl_cache_alloc(&rtnl_rule_ops)))
  275. return -NLE_NOMEM;
  276. cache->c_iarg1 = family;
  277. if (sock && (err = nl_cache_refill(sock, cache)) < 0) {
  278. free(cache);
  279. return err;
  280. }
  281. *result = cache;
  282. return 0;
  283. }
  284. /** @} */
  285. /**
  286. * @name Rule Addition
  287. * @{
  288. */
  289. static int build_rule_msg(struct rtnl_rule *tmpl, int cmd, int flags,
  290. struct nl_msg **result)
  291. {
  292. struct nl_msg *msg;
  293. struct fib_rule_hdr frh = {
  294. .family = tmpl->r_family,
  295. .table = tmpl->r_table,
  296. .action = tmpl->r_action,
  297. .flags = tmpl->r_flags,
  298. .tos = tmpl->r_dsfield,
  299. };
  300. if (!(tmpl->ce_mask & RULE_ATTR_FAMILY))
  301. return -NLE_MISSING_ATTR;
  302. msg = nlmsg_alloc_simple(cmd, flags);
  303. if (!msg)
  304. return -NLE_NOMEM;
  305. if (tmpl->ce_mask & RULE_ATTR_SRC)
  306. frh.src_len = nl_addr_get_prefixlen(tmpl->r_src);
  307. if (tmpl->ce_mask & RULE_ATTR_DST)
  308. frh.dst_len = nl_addr_get_prefixlen(tmpl->r_dst);
  309. if (nlmsg_append(msg, &frh, sizeof(frh), NLMSG_ALIGNTO) < 0)
  310. goto nla_put_failure;
  311. /* Additional table attribute replacing the 8bit in the header, was
  312. * required to allow more than 256 tables. */
  313. NLA_PUT_U32(msg, FRA_TABLE, tmpl->r_table);
  314. if (tmpl->ce_mask & RULE_ATTR_SRC)
  315. NLA_PUT_ADDR(msg, FRA_SRC, tmpl->r_src);
  316. if (tmpl->ce_mask & RULE_ATTR_DST)
  317. NLA_PUT_ADDR(msg, FRA_DST, tmpl->r_dst);
  318. if (tmpl->ce_mask & RULE_ATTR_IIFNAME)
  319. NLA_PUT_STRING(msg, FRA_IIFNAME, tmpl->r_iifname);
  320. if (tmpl->ce_mask & RULE_ATTR_OIFNAME)
  321. NLA_PUT_STRING(msg, FRA_OIFNAME, tmpl->r_oifname);
  322. if (tmpl->ce_mask & RULE_ATTR_PRIO)
  323. NLA_PUT_U32(msg, FRA_PRIORITY, tmpl->r_prio);
  324. if (tmpl->ce_mask & RULE_ATTR_MARK)
  325. NLA_PUT_U32(msg, FRA_FWMARK, tmpl->r_mark);
  326. if (tmpl->ce_mask & RULE_ATTR_MASK)
  327. NLA_PUT_U32(msg, FRA_FWMASK, tmpl->r_mask);
  328. if (tmpl->ce_mask & RULE_ATTR_GOTO)
  329. NLA_PUT_U32(msg, FRA_GOTO, tmpl->r_goto);
  330. if (tmpl->ce_mask & RULE_ATTR_FLOW)
  331. NLA_PUT_U32(msg, FRA_FLOW, tmpl->r_flow);
  332. *result = msg;
  333. return 0;
  334. nla_put_failure:
  335. nlmsg_free(msg);
  336. return -NLE_MSGSIZE;
  337. }
  338. /**
  339. * Build netlink request message to add a new rule
  340. * @arg tmpl template with data of new rule
  341. * @arg flags additional netlink message flags
  342. * @arg result Result pointer
  343. *
  344. * Builds a new netlink message requesting a addition of a new
  345. * rule. The netlink message header isn't fully equipped with
  346. * all relevant fields and must thus be sent out via nl_send_auto_complete()
  347. * or supplemented as needed. \a tmpl must contain the attributes of the new
  348. * address set via \c rtnl_rule_set_* functions.
  349. *
  350. * @return 0 on success or a negative error code.
  351. */
  352. int rtnl_rule_build_add_request(struct rtnl_rule *tmpl, int flags,
  353. struct nl_msg **result)
  354. {
  355. return build_rule_msg(tmpl, RTM_NEWRULE, NLM_F_CREATE | flags,
  356. result);
  357. }
  358. /**
  359. * Add a new rule
  360. * @arg sk Netlink socket.
  361. * @arg tmpl template with requested changes
  362. * @arg flags additional netlink message flags
  363. *
  364. * Builds a netlink message by calling rtnl_rule_build_add_request(),
  365. * sends the request to the kernel and waits for the next ACK to be
  366. * received and thus blocks until the request has been fullfilled.
  367. *
  368. * @return 0 on sucess or a negative error if an error occured.
  369. */
  370. int rtnl_rule_add(struct nl_sock *sk, struct rtnl_rule *tmpl, int flags)
  371. {
  372. struct nl_msg *msg;
  373. int err;
  374. if ((err = rtnl_rule_build_add_request(tmpl, flags, &msg)) < 0)
  375. return err;
  376. err = nl_send_auto_complete(sk, msg);
  377. nlmsg_free(msg);
  378. if (err < 0)
  379. return err;
  380. return wait_for_ack(sk);
  381. }
  382. /** @} */
  383. /**
  384. * @name Rule Deletion
  385. * @{
  386. */
  387. /**
  388. * Build a netlink request message to delete a rule
  389. * @arg rule rule to delete
  390. * @arg flags additional netlink message flags
  391. * @arg result Result pointer
  392. *
  393. * Builds a new netlink message requesting a deletion of a rule.
  394. * The netlink message header isn't fully equipped with all relevant
  395. * fields and must thus be sent out via nl_send_auto_complete()
  396. * or supplemented as needed. \a rule must point to an existing
  397. * address.
  398. *
  399. * @return 0 on success or a negative error code.
  400. */
  401. int rtnl_rule_build_delete_request(struct rtnl_rule *rule, int flags,
  402. struct nl_msg **result)
  403. {
  404. return build_rule_msg(rule, RTM_DELRULE, flags, result);
  405. }
  406. /**
  407. * Delete a rule
  408. * @arg sk Netlink socket.
  409. * @arg rule rule to delete
  410. * @arg flags additional netlink message flags
  411. *
  412. * Builds a netlink message by calling rtnl_rule_build_delete_request(),
  413. * sends the request to the kernel and waits for the next ACK to be
  414. * received and thus blocks until the request has been fullfilled.
  415. *
  416. * @return 0 on sucess or a negative error if an error occured.
  417. */
  418. int rtnl_rule_delete(struct nl_sock *sk, struct rtnl_rule *rule, int flags)
  419. {
  420. struct nl_msg *msg;
  421. int err;
  422. if ((err = rtnl_rule_build_delete_request(rule, flags, &msg)) < 0)
  423. return err;
  424. err = nl_send_auto_complete(sk, msg);
  425. nlmsg_free(msg);
  426. if (err < 0)
  427. return err;
  428. return wait_for_ack(sk);
  429. }
  430. /** @} */
  431. /**
  432. * @name Attribute Modification
  433. * @{
  434. */
  435. void rtnl_rule_set_family(struct rtnl_rule *rule, int family)
  436. {
  437. rule->r_family = family;
  438. rule->ce_mask |= RULE_ATTR_FAMILY;
  439. }
  440. int rtnl_rule_get_family(struct rtnl_rule *rule)
  441. {
  442. if (rule->ce_mask & RULE_ATTR_FAMILY)
  443. return rule->r_family;
  444. else
  445. return AF_UNSPEC;
  446. }
  447. void rtnl_rule_set_prio(struct rtnl_rule *rule, uint32_t prio)
  448. {
  449. rule->r_prio = prio;
  450. rule->ce_mask |= RULE_ATTR_PRIO;
  451. }
  452. uint32_t rtnl_rule_get_prio(struct rtnl_rule *rule)
  453. {
  454. return rule->r_prio;
  455. }
  456. void rtnl_rule_set_mark(struct rtnl_rule *rule, uint32_t mark)
  457. {
  458. rule->r_mark = mark;
  459. rule->ce_mask |= RULE_ATTR_MARK;
  460. }
  461. uint32_t rtnl_rule_get_mark(struct rtnl_rule *rule)
  462. {
  463. return rule->r_mark;
  464. }
  465. void rtnl_rule_set_mask(struct rtnl_rule *rule, uint32_t mask)
  466. {
  467. rule->r_mask = mask;
  468. rule->ce_mask |= RULE_ATTR_MASK;
  469. }
  470. uint32_t rtnl_rule_get_mask(struct rtnl_rule *rule)
  471. {
  472. return rule->r_mask;
  473. }
  474. void rtnl_rule_set_table(struct rtnl_rule *rule, uint32_t table)
  475. {
  476. rule->r_table = table;
  477. rule->ce_mask |= RULE_ATTR_TABLE;
  478. }
  479. uint32_t rtnl_rule_get_table(struct rtnl_rule *rule)
  480. {
  481. return rule->r_table;
  482. }
  483. void rtnl_rule_set_dsfield(struct rtnl_rule *rule, uint8_t dsfield)
  484. {
  485. rule->r_dsfield = dsfield;
  486. rule->ce_mask |= RULE_ATTR_DSFIELD;
  487. }
  488. uint8_t rtnl_rule_get_dsfield(struct rtnl_rule *rule)
  489. {
  490. return rule->r_dsfield;
  491. }
  492. static inline int __assign_addr(struct rtnl_rule *rule, struct nl_addr **pos,
  493. struct nl_addr *new, int flag)
  494. {
  495. if (rule->ce_mask & RULE_ATTR_FAMILY) {
  496. if (new->a_family != rule->r_family)
  497. return -NLE_AF_MISMATCH;
  498. } else
  499. rule->r_family = new->a_family;
  500. if (*pos)
  501. nl_addr_put(*pos);
  502. nl_addr_get(new);
  503. *pos = new;
  504. rule->ce_mask |= (flag | RULE_ATTR_FAMILY);
  505. return 0;
  506. }
  507. int rtnl_rule_set_src(struct rtnl_rule *rule, struct nl_addr *src)
  508. {
  509. return __assign_addr(rule, &rule->r_src, src, RULE_ATTR_SRC);
  510. }
  511. struct nl_addr *rtnl_rule_get_src(struct rtnl_rule *rule)
  512. {
  513. return rule->r_src;
  514. }
  515. int rtnl_rule_set_dst(struct rtnl_rule *rule, struct nl_addr *dst)
  516. {
  517. return __assign_addr(rule, &rule->r_dst, dst, RULE_ATTR_DST);
  518. }
  519. struct nl_addr *rtnl_rule_get_dst(struct rtnl_rule *rule)
  520. {
  521. return rule->r_dst;
  522. }
  523. int rtnl_rule_set_iif(struct rtnl_rule *rule, const char *dev)
  524. {
  525. if (strlen(dev) > IFNAMSIZ-1)
  526. return -NLE_RANGE;
  527. strcpy(rule->r_iifname, dev);
  528. rule->ce_mask |= RULE_ATTR_IIFNAME;
  529. return 0;
  530. }
  531. char *rtnl_rule_get_iif(struct rtnl_rule *rule)
  532. {
  533. if (rule->ce_mask & RULE_ATTR_IIFNAME)
  534. return rule->r_iifname;
  535. else
  536. return NULL;
  537. }
  538. int rtnl_rule_set_oif(struct rtnl_rule *rule, const char *dev)
  539. {
  540. if (strlen(dev) > IFNAMSIZ-1)
  541. return -NLE_RANGE;
  542. strcpy(rule->r_oifname, dev);
  543. rule->ce_mask |= RULE_ATTR_OIFNAME;
  544. return 0;
  545. }
  546. char *rtnl_rule_get_oif(struct rtnl_rule *rule)
  547. {
  548. if (rule->ce_mask & RULE_ATTR_OIFNAME)
  549. return rule->r_oifname;
  550. else
  551. return NULL;
  552. }
  553. void rtnl_rule_set_action(struct rtnl_rule *rule, uint8_t action)
  554. {
  555. rule->r_action = action;
  556. rule->ce_mask |= RULE_ATTR_ACTION;
  557. }
  558. uint8_t rtnl_rule_get_action(struct rtnl_rule *rule)
  559. {
  560. return rule->r_action;
  561. }
  562. void rtnl_rule_set_realms(struct rtnl_rule *rule, uint32_t realms)
  563. {
  564. rule->r_flow = realms;
  565. rule->ce_mask |= RULE_ATTR_FLOW;
  566. }
  567. uint32_t rtnl_rule_get_realms(struct rtnl_rule *rule)
  568. {
  569. return rule->r_flow;
  570. }
  571. void rtnl_rule_set_goto(struct rtnl_rule *rule, uint32_t ref)
  572. {
  573. rule->r_goto = ref;
  574. rule->ce_mask |= RULE_ATTR_GOTO;
  575. }
  576. uint32_t rtnl_rule_get_goto(struct rtnl_rule *rule)
  577. {
  578. return rule->r_goto;
  579. }
  580. /** @} */
  581. static struct nl_object_ops rule_obj_ops = {
  582. .oo_name = "route/rule",
  583. .oo_size = sizeof(struct rtnl_rule),
  584. .oo_free_data = rule_free_data,
  585. .oo_clone = rule_clone,
  586. .oo_dump = {
  587. [NL_DUMP_LINE] = rule_dump_line,
  588. [NL_DUMP_DETAILS] = rule_dump_details,
  589. [NL_DUMP_STATS] = rule_dump_stats,
  590. },
  591. .oo_compare = rule_compare,
  592. .oo_attrs2str = rule_attrs2str,
  593. .oo_id_attrs = ~0,
  594. };
  595. static struct nl_cache_ops rtnl_rule_ops = {
  596. .co_name = "route/rule",
  597. .co_hdrsize = sizeof(struct fib_rule_hdr),
  598. .co_msgtypes = {
  599. { RTM_NEWRULE, NL_ACT_NEW, "new" },
  600. { RTM_DELRULE, NL_ACT_DEL, "del" },
  601. { RTM_GETRULE, NL_ACT_GET, "get" },
  602. END_OF_MSGTYPES_LIST,
  603. },
  604. .co_protocol = NETLINK_ROUTE,
  605. .co_request_update = rule_request_update,
  606. .co_msg_parser = rule_msg_parser,
  607. .co_obj_ops = &rule_obj_ops,
  608. };
  609. static void __init rule_init(void)
  610. {
  611. nl_cache_mngt_register(&rtnl_rule_ops);
  612. }
  613. static void __exit rule_exit(void)
  614. {
  615. nl_cache_mngt_unregister(&rtnl_rule_ops);
  616. }
  617. /** @} */