rule.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899
  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-2006 Thomas Graf <tgraf@suug.ch>
  10. */
  11. /**
  12. * @ingroup rtnl
  13. * @defgroup rule Routing Rules
  14. * @brief
  15. * @{
  16. */
  17. #include <netlink-local.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_PRIO 0x0002
  26. #define RULE_ATTR_MARK 0x0004
  27. #define RULE_ATTR_IIF 0x0008
  28. #define RULE_ATTR_REALMS 0x0010
  29. #define RULE_ATTR_SRC 0x0020
  30. #define RULE_ATTR_DST 0x0040
  31. #define RULE_ATTR_DSFIELD 0x0080
  32. #define RULE_ATTR_TABLE 0x0100
  33. #define RULE_ATTR_TYPE 0x0200
  34. #define RULE_ATTR_SRC_LEN 0x0400
  35. #define RULE_ATTR_DST_LEN 0x0800
  36. #define RULE_ATTR_SRCMAP 0x1000
  37. static struct nl_cache_ops rtnl_rule_ops;
  38. static struct nl_object_ops rule_obj_ops;
  39. /** @endcond */
  40. static void rule_free_data(struct nl_object *c)
  41. {
  42. struct rtnl_rule *rule = nl_object_priv(c);
  43. if (!rule)
  44. return;
  45. nl_addr_put(rule->r_src);
  46. nl_addr_put(rule->r_dst);
  47. }
  48. static int rule_clone(struct nl_object *_dst, struct nl_object *_src)
  49. {
  50. struct rtnl_rule *dst = nl_object_priv(_dst);
  51. struct rtnl_rule *src = nl_object_priv(_src);
  52. if (src->r_src)
  53. if (!(dst->r_src = nl_addr_clone(src->r_src)))
  54. goto errout;
  55. if (src->r_dst)
  56. if (!(dst->r_dst = nl_addr_clone(src->r_dst)))
  57. goto errout;
  58. return 0;
  59. errout:
  60. return nl_get_errno();
  61. }
  62. static struct nla_policy rule_policy[RTA_MAX+1] = {
  63. [RTA_PRIORITY] = { .type = NLA_U32 },
  64. [RTA_FLOW] = { .type = NLA_U32 },
  65. [RTA_PROTOINFO] = { .type = NLA_U32 },
  66. [RTA_IIF] = { .type = NLA_STRING,
  67. .maxlen = IFNAMSIZ, },
  68. };
  69. static int rule_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
  70. struct nlmsghdr *n, struct nl_parser_param *pp)
  71. {
  72. struct rtnl_rule *rule;
  73. struct rtmsg *r;
  74. struct nlattr *tb[RTA_MAX+1];
  75. int err = 1;
  76. rule = rtnl_rule_alloc();
  77. if (!rule) {
  78. err = nl_errno(ENOMEM);
  79. goto errout;
  80. }
  81. rule->ce_msgtype = n->nlmsg_type;
  82. r = nlmsg_data(n);
  83. err = nlmsg_parse(n, sizeof(*r), tb, RTA_MAX, rule_policy);
  84. if (err < 0)
  85. goto errout;
  86. rule->r_family = r->rtm_family;
  87. rule->r_type = r->rtm_type;
  88. rule->r_dsfield = r->rtm_tos;
  89. rule->r_src_len = r->rtm_src_len;
  90. rule->r_dst_len = r->rtm_dst_len;
  91. rule->r_table = r->rtm_table;
  92. rule->ce_mask = (RULE_ATTR_FAMILY | RULE_ATTR_TYPE | RULE_ATTR_DSFIELD |
  93. RULE_ATTR_SRC_LEN | RULE_ATTR_DST_LEN |RULE_ATTR_TYPE);
  94. if (tb[RTA_PRIORITY]) {
  95. rule->r_prio = nla_get_u32(tb[RTA_PRIORITY]);
  96. rule->ce_mask |= RULE_ATTR_PRIO;
  97. }
  98. if (tb[RTA_SRC]) {
  99. rule->r_src = nla_get_addr(tb[RTA_SRC], r->rtm_family);
  100. if (!rule->r_src) {
  101. err = nl_errno(ENOMEM);
  102. goto errout;
  103. }
  104. nl_addr_set_prefixlen(rule->r_src, r->rtm_src_len);
  105. rule->ce_mask |= RULE_ATTR_SRC;
  106. }
  107. if (tb[RTA_DST]) {
  108. rule->r_dst = nla_get_addr(tb[RTA_DST], r->rtm_family);
  109. if (!rule->r_dst) {
  110. err = nl_errno(ENOMEM);
  111. goto errout;
  112. }
  113. nl_addr_set_prefixlen(rule->r_dst, r->rtm_dst_len);
  114. rule->ce_mask |= RULE_ATTR_DST;
  115. }
  116. if (tb[RTA_PROTOINFO]) {
  117. rule->r_mark = nla_get_u32(tb[RTA_PROTOINFO]);
  118. rule->ce_mask |= RULE_ATTR_MARK;
  119. }
  120. if (tb[RTA_IIF]) {
  121. nla_strlcpy(rule->r_iif, tb[RTA_IIF], IFNAMSIZ);
  122. rule->ce_mask |= RULE_ATTR_IIF;
  123. }
  124. if (tb[RTA_FLOW]) {
  125. rule->r_realms = nla_get_u32(tb[RTA_FLOW]);
  126. rule->ce_mask |= RULE_ATTR_REALMS;
  127. }
  128. if (tb[RTA_GATEWAY]) {
  129. rule->r_srcmap = nla_get_addr(tb[RTA_GATEWAY], r->rtm_family);
  130. if (!rule->r_srcmap) {
  131. err = nl_errno(ENOMEM);
  132. goto errout;
  133. }
  134. rule->ce_mask |= RULE_ATTR_SRCMAP;
  135. }
  136. err = pp->pp_cb((struct nl_object *) rule, pp);
  137. if (err < 0)
  138. goto errout;
  139. err = P_ACCEPT;
  140. errout:
  141. rtnl_rule_put(rule);
  142. return err;
  143. }
  144. static int rule_request_update(struct nl_cache *c, struct nl_handle *h)
  145. {
  146. return nl_rtgen_request(h, RTM_GETRULE, AF_UNSPEC, NLM_F_DUMP);
  147. }
  148. static int rule_dump_brief(struct nl_object *o, struct nl_dump_params *p)
  149. {
  150. struct rtnl_rule *r = (struct rtnl_rule *) o;
  151. char buf[128];
  152. if (r->ce_mask & RULE_ATTR_PRIO)
  153. dp_dump(p, "%d:\t", r->r_prio);
  154. else
  155. dp_dump(p, "0:\t");
  156. if (r->ce_mask & RULE_ATTR_SRC)
  157. dp_dump(p, "from %s ",
  158. nl_addr2str(r->r_src, buf, sizeof(buf)));
  159. else if (r->ce_mask & RULE_ATTR_SRC_LEN && r->r_src_len)
  160. dp_dump(p, "from 0/%d ", r->r_src_len);
  161. if (r->ce_mask & RULE_ATTR_DST)
  162. dp_dump(p, "to %s ",
  163. nl_addr2str(r->r_dst, buf, sizeof(buf)));
  164. else if (r->ce_mask & RULE_ATTR_DST_LEN && r->r_dst_len)
  165. dp_dump(p, "to 0/%d ", r->r_dst_len);
  166. if (r->ce_mask & RULE_ATTR_DSFIELD && r->r_dsfield)
  167. dp_dump(p, "tos %d ", r->r_dsfield);
  168. if (r->ce_mask & RULE_ATTR_MARK)
  169. dp_dump(p, "mark %" PRIx64 , r->r_mark);
  170. if (r->ce_mask & RULE_ATTR_IIF)
  171. dp_dump(p, "iif %s ", r->r_iif);
  172. if (r->ce_mask & RULE_ATTR_TABLE)
  173. dp_dump(p, "lookup %s ",
  174. rtnl_route_table2str(r->r_table, buf, sizeof(buf)));
  175. if (r->ce_mask & RULE_ATTR_REALMS)
  176. dp_dump(p, "realms %s ",
  177. rtnl_realms2str(r->r_realms, buf, sizeof(buf)));
  178. dp_dump(p, "action %s\n",
  179. nl_rtntype2str(r->r_type, buf, sizeof(buf)));
  180. return 1;
  181. }
  182. static int rule_dump_full(struct nl_object *obj, struct nl_dump_params *p)
  183. {
  184. struct rtnl_rule *rule = (struct rtnl_rule *) obj;
  185. char buf[128];
  186. int line;
  187. line = rule_dump_brief(obj, p);
  188. dp_dump_line(p, line++, " family %s",
  189. nl_af2str(rule->r_family, buf, sizeof(buf)));
  190. if (rule->ce_mask & RULE_ATTR_SRCMAP)
  191. dp_dump(p, " srcmap %s",
  192. nl_addr2str(rule->r_srcmap, buf, sizeof(buf)));
  193. dp_dump(p, "\n");
  194. return line;
  195. }
  196. static int rule_dump_stats(struct nl_object *obj, struct nl_dump_params *p)
  197. {
  198. return rule_dump_full(obj, p);
  199. }
  200. static int rule_dump_xml(struct nl_object *obj, struct nl_dump_params *p)
  201. {
  202. struct rtnl_rule *rule = (struct rtnl_rule *) obj;
  203. char buf[128];
  204. int line = 0;
  205. dp_dump_line(p, line++, "<rule>\n");
  206. dp_dump_line(p, line++, " <priority>%u</priority>\n",
  207. rule->r_prio);
  208. dp_dump_line(p, line++, " <family>%s</family>\n",
  209. nl_af2str(rule->r_family, buf, sizeof(buf)));
  210. if (rule->ce_mask & RULE_ATTR_DST)
  211. dp_dump_line(p, line++, " <dst>%s</dst>\n",
  212. nl_addr2str(rule->r_dst, buf, sizeof(buf)));
  213. if (rule->ce_mask & RULE_ATTR_DST_LEN)
  214. dp_dump_line(p, line++, " <dstlen>%u</dstlen>\n",
  215. rule->r_dst_len);
  216. if (rule->ce_mask & RULE_ATTR_SRC)
  217. dp_dump_line(p, line++, " <src>%s</src>\n",
  218. nl_addr2str(rule->r_src, buf, sizeof(buf)));
  219. if (rule->ce_mask & RULE_ATTR_SRC_LEN)
  220. dp_dump_line(p, line++, " <srclen>%u</srclen>\n",
  221. rule->r_src_len);
  222. if (rule->ce_mask & RULE_ATTR_IIF)
  223. dp_dump_line(p, line++, " <iif>%s</iif>\n", rule->r_iif);
  224. if (rule->ce_mask & RULE_ATTR_TABLE)
  225. dp_dump_line(p, line++, " <table>%u</table>\n",
  226. rule->r_table);
  227. if (rule->ce_mask & RULE_ATTR_REALMS)
  228. dp_dump_line(p, line++, " <realms>%u</realms>\n",
  229. rule->r_realms);
  230. if (rule->ce_mask & RULE_ATTR_MARK)
  231. dp_dump_line(p, line++, " <mark>%" PRIx64 "</mark>\n",
  232. rule->r_mark);
  233. if (rule->ce_mask & RULE_ATTR_DSFIELD)
  234. dp_dump_line(p, line++, " <dsfield>%u</dsfield>\n",
  235. rule->r_dsfield);
  236. if (rule->ce_mask & RULE_ATTR_TYPE)
  237. dp_dump_line(p, line++, "<type>%s</type>\n",
  238. nl_rtntype2str(rule->r_type, buf, sizeof(buf)));
  239. if (rule->ce_mask & RULE_ATTR_SRCMAP)
  240. dp_dump_line(p, line++, "<srcmap>%s</srcmap>\n",
  241. nl_addr2str(rule->r_srcmap, buf, sizeof(buf)));
  242. dp_dump_line(p, line++, "</rule>\n");
  243. return line;
  244. }
  245. static int rule_dump_env(struct nl_object *obj, struct nl_dump_params *p)
  246. {
  247. struct rtnl_rule *rule = (struct rtnl_rule *) obj;
  248. char buf[128];
  249. int line = 0;
  250. dp_dump_line(p, line++, "RULE_PRIORITY=%u\n",
  251. rule->r_prio);
  252. dp_dump_line(p, line++, "RULE_FAMILY=%s\n",
  253. nl_af2str(rule->r_family, buf, sizeof(buf)));
  254. if (rule->ce_mask & RULE_ATTR_DST)
  255. dp_dump_line(p, line++, "RULE_DST=%s\n",
  256. nl_addr2str(rule->r_dst, buf, sizeof(buf)));
  257. if (rule->ce_mask & RULE_ATTR_DST_LEN)
  258. dp_dump_line(p, line++, "RULE_DSTLEN=%u\n",
  259. rule->r_dst_len);
  260. if (rule->ce_mask & RULE_ATTR_SRC)
  261. dp_dump_line(p, line++, "RULE_SRC=%s\n",
  262. nl_addr2str(rule->r_src, buf, sizeof(buf)));
  263. if (rule->ce_mask & RULE_ATTR_SRC_LEN)
  264. dp_dump_line(p, line++, "RULE_SRCLEN=%u\n",
  265. rule->r_src_len);
  266. if (rule->ce_mask & RULE_ATTR_IIF)
  267. dp_dump_line(p, line++, "RULE_IIF=%s\n", rule->r_iif);
  268. if (rule->ce_mask & RULE_ATTR_TABLE)
  269. dp_dump_line(p, line++, "RULE_TABLE=%u\n",
  270. rule->r_table);
  271. if (rule->ce_mask & RULE_ATTR_REALMS)
  272. dp_dump_line(p, line++, "RULE_REALM=%u\n",
  273. rule->r_realms);
  274. if (rule->ce_mask & RULE_ATTR_MARK)
  275. dp_dump_line(p, line++, "RULE_MARK=0x%" PRIx64 "\n",
  276. rule->r_mark);
  277. if (rule->ce_mask & RULE_ATTR_DSFIELD)
  278. dp_dump_line(p, line++, "RULE_DSFIELD=%u\n",
  279. rule->r_dsfield);
  280. if (rule->ce_mask & RULE_ATTR_TYPE)
  281. dp_dump_line(p, line++, "RULE_TYPE=%s\n",
  282. nl_rtntype2str(rule->r_type, buf, sizeof(buf)));
  283. if (rule->ce_mask & RULE_ATTR_SRCMAP)
  284. dp_dump_line(p, line++, "RULE_SRCMAP=%s\n",
  285. nl_addr2str(rule->r_srcmap, buf, sizeof(buf)));
  286. return line;
  287. }
  288. static int rule_compare(struct nl_object *_a, struct nl_object *_b,
  289. uint32_t attrs, int flags)
  290. {
  291. struct rtnl_rule *a = (struct rtnl_rule *) _a;
  292. struct rtnl_rule *b = (struct rtnl_rule *) _b;
  293. int diff = 0;
  294. #define RULE_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, RULE_ATTR_##ATTR, a, b, EXPR)
  295. diff |= RULE_DIFF(FAMILY, a->r_family != b->r_family);
  296. diff |= RULE_DIFF(TABLE, a->r_table != b->r_table);
  297. diff |= RULE_DIFF(REALMS, a->r_realms != b->r_realms);
  298. diff |= RULE_DIFF(DSFIELD, a->r_dsfield != b->r_dsfield);
  299. diff |= RULE_DIFF(TYPE, a->r_type != b->r_type);
  300. diff |= RULE_DIFF(PRIO, a->r_prio != b->r_prio);
  301. diff |= RULE_DIFF(MARK, a->r_mark != b->r_mark);
  302. diff |= RULE_DIFF(SRC_LEN, a->r_src_len != b->r_src_len);
  303. diff |= RULE_DIFF(DST_LEN, a->r_dst_len != b->r_dst_len);
  304. diff |= RULE_DIFF(SRC, nl_addr_cmp(a->r_src, b->r_src));
  305. diff |= RULE_DIFF(DST, nl_addr_cmp(a->r_dst, b->r_dst));
  306. diff |= RULE_DIFF(IIF, strcmp(a->r_iif, b->r_iif));
  307. #undef RULE_DIFF
  308. return diff;
  309. }
  310. static struct trans_tbl rule_attrs[] = {
  311. __ADD(RULE_ATTR_FAMILY, family)
  312. __ADD(RULE_ATTR_PRIO, prio)
  313. __ADD(RULE_ATTR_MARK, mark)
  314. __ADD(RULE_ATTR_IIF, iif)
  315. __ADD(RULE_ATTR_REALMS, realms)
  316. __ADD(RULE_ATTR_SRC, src)
  317. __ADD(RULE_ATTR_DST, dst)
  318. __ADD(RULE_ATTR_DSFIELD, dsfield)
  319. __ADD(RULE_ATTR_TABLE, table)
  320. __ADD(RULE_ATTR_TYPE, type)
  321. __ADD(RULE_ATTR_SRC_LEN, src_len)
  322. __ADD(RULE_ATTR_DST_LEN, dst_len)
  323. __ADD(RULE_ATTR_SRCMAP, srcmap)
  324. };
  325. static char *rule_attrs2str(int attrs, char *buf, size_t len)
  326. {
  327. return __flags2str(attrs, buf, len, rule_attrs,
  328. ARRAY_SIZE(rule_attrs));
  329. }
  330. /**
  331. * @name Allocation/Freeing
  332. * @{
  333. */
  334. struct rtnl_rule *rtnl_rule_alloc(void)
  335. {
  336. return (struct rtnl_rule *) nl_object_alloc(&rule_obj_ops);
  337. }
  338. void rtnl_rule_put(struct rtnl_rule *rule)
  339. {
  340. nl_object_put((struct nl_object *) rule);
  341. }
  342. /** @} */
  343. /**
  344. * @name Cache Management
  345. * @{
  346. */
  347. /**
  348. * Build a rule cache including all rules of the specified family currently configured in the kernel.
  349. * @arg handle netlink handle
  350. * @arg family address family
  351. *
  352. * Allocates a new rule cache, initializes it properly and updates it
  353. * to include all rules of the specified address family currently
  354. * configured in the kernel.
  355. *
  356. * @note The caller is responsible for destroying and freeing the
  357. * cache after using it. (nl_cache_destroy_and_free())
  358. * @return The new cache or NULL if an error occured.
  359. */
  360. struct nl_cache * rtnl_rule_alloc_cache_by_family(struct nl_handle *handle,
  361. int family)
  362. {
  363. struct nl_cache * cache;
  364. cache = nl_cache_alloc(&rtnl_rule_ops);
  365. if (cache == NULL)
  366. return NULL;
  367. /* XXX RULE_CACHE_FAMILY(cache) = family; */
  368. if (handle && nl_cache_refill(handle, cache) < 0) {
  369. free(cache);
  370. return NULL;
  371. }
  372. return cache;
  373. }
  374. /**
  375. * Build a rule cache including all rules currently configured in the kernel.
  376. * @arg handle netlink handle
  377. *
  378. * Allocates a new rule cache, initializes it properly and updates it
  379. * to include all rules currently configured in the kernel.
  380. *
  381. * @note The caller is responsible for destroying and freeing the
  382. * cache after using it. (nl_cache_destroy_and_free())
  383. * @return The new cache or NULL if an error occured.
  384. */
  385. struct nl_cache * rtnl_rule_alloc_cache(struct nl_handle *handle)
  386. {
  387. return rtnl_rule_alloc_cache_by_family(handle, AF_UNSPEC);
  388. }
  389. /** @} */
  390. /**
  391. * @name Rule Addition
  392. * @{
  393. */
  394. static struct nl_msg *build_rule_msg(struct rtnl_rule *tmpl, int cmd, int flags)
  395. {
  396. struct nl_msg *msg;
  397. struct rtmsg rtm = {
  398. .rtm_type = RTN_UNSPEC
  399. };
  400. if (cmd == RTM_NEWRULE)
  401. rtm.rtm_type = RTN_UNICAST;
  402. if (tmpl->ce_mask & RULE_ATTR_FAMILY)
  403. rtm.rtm_family = tmpl->r_family;
  404. if (tmpl->ce_mask & RULE_ATTR_TABLE)
  405. rtm.rtm_table = tmpl->r_table;
  406. if (tmpl->ce_mask & RULE_ATTR_DSFIELD)
  407. rtm.rtm_tos = tmpl->r_dsfield;
  408. if (tmpl->ce_mask & RULE_ATTR_TYPE)
  409. rtm.rtm_type = tmpl->r_type;
  410. if (tmpl->ce_mask & RULE_ATTR_SRC_LEN)
  411. rtm.rtm_src_len = tmpl->r_src_len;
  412. if (tmpl->ce_mask & RULE_ATTR_DST_LEN)
  413. rtm.rtm_dst_len = tmpl->r_dst_len;
  414. msg = nlmsg_alloc_simple(cmd, flags);
  415. if (!msg)
  416. goto nla_put_failure;
  417. if (nlmsg_append(msg, &rtm, sizeof(rtm), NLMSG_ALIGNTO) < 0)
  418. goto nla_put_failure;
  419. if (tmpl->ce_mask & RULE_ATTR_SRC)
  420. NLA_PUT_ADDR(msg, RTA_SRC, tmpl->r_src);
  421. if (tmpl->ce_mask & RULE_ATTR_DST)
  422. NLA_PUT_ADDR(msg, RTA_DST, tmpl->r_dst);
  423. if (tmpl->ce_mask & RULE_ATTR_PRIO)
  424. NLA_PUT_U32(msg, RTA_PRIORITY, tmpl->r_prio);
  425. if (tmpl->ce_mask & RULE_ATTR_MARK)
  426. NLA_PUT_U32(msg, RTA_PROTOINFO, tmpl->r_mark);
  427. if (tmpl->ce_mask & RULE_ATTR_REALMS)
  428. NLA_PUT_U32(msg, RTA_FLOW, tmpl->r_realms);
  429. if (tmpl->ce_mask & RULE_ATTR_IIF)
  430. NLA_PUT_STRING(msg, RTA_IIF, tmpl->r_iif);
  431. return msg;
  432. nla_put_failure:
  433. nlmsg_free(msg);
  434. return NULL;
  435. }
  436. /**
  437. * Build netlink request message to add a new rule
  438. * @arg tmpl template with data of new rule
  439. * @arg flags additional netlink message flags
  440. *
  441. * Builds a new netlink message requesting a addition of a new
  442. * rule. The netlink message header isn't fully equipped with
  443. * all relevant fields and must thus be sent out via nl_send_auto_complete()
  444. * or supplemented as needed. \a tmpl must contain the attributes of the new
  445. * address set via \c rtnl_rule_set_* functions.
  446. *
  447. * @return The netlink message
  448. */
  449. struct nl_msg *rtnl_rule_build_add_request(struct rtnl_rule *tmpl, int flags)
  450. {
  451. return build_rule_msg(tmpl, RTM_NEWRULE, NLM_F_CREATE | flags);
  452. }
  453. /**
  454. * Add a new rule
  455. * @arg handle netlink handle
  456. * @arg tmpl template with requested changes
  457. * @arg flags additional netlink message flags
  458. *
  459. * Builds a netlink message by calling rtnl_rule_build_add_request(),
  460. * sends the request to the kernel and waits for the next ACK to be
  461. * received and thus blocks until the request has been fullfilled.
  462. *
  463. * @return 0 on sucess or a negative error if an error occured.
  464. */
  465. int rtnl_rule_add(struct nl_handle *handle, struct rtnl_rule *tmpl, int flags)
  466. {
  467. int err;
  468. struct nl_msg *msg;
  469. msg = rtnl_rule_build_add_request(tmpl, flags);
  470. if (!msg)
  471. return nl_errno(ENOMEM);
  472. err = nl_send_auto_complete(handle, msg);
  473. nlmsg_free(msg);
  474. if (err < 0)
  475. return err;
  476. return nl_wait_for_ack(handle);
  477. }
  478. /** @} */
  479. /**
  480. * @name Rule Deletion
  481. * @{
  482. */
  483. /**
  484. * Build a netlink request message to delete a rule
  485. * @arg rule rule to delete
  486. * @arg flags additional netlink message flags
  487. *
  488. * Builds a new netlink message requesting a deletion of a rule.
  489. * The netlink message header isn't fully equipped with all relevant
  490. * fields and must thus be sent out via nl_send_auto_complete()
  491. * or supplemented as needed. \a rule must point to an existing
  492. * address.
  493. *
  494. * @return The netlink message
  495. */
  496. struct nl_msg *rtnl_rule_build_delete_request(struct rtnl_rule *rule, int flags)
  497. {
  498. return build_rule_msg(rule, RTM_DELRULE, flags);
  499. }
  500. /**
  501. * Delete a rule
  502. * @arg handle netlink handle
  503. * @arg rule rule to delete
  504. * @arg flags additional netlink message flags
  505. *
  506. * Builds a netlink message by calling rtnl_rule_build_delete_request(),
  507. * sends the request to the kernel and waits for the next ACK to be
  508. * received and thus blocks until the request has been fullfilled.
  509. *
  510. * @return 0 on sucess or a negative error if an error occured.
  511. */
  512. int rtnl_rule_delete(struct nl_handle *handle, struct rtnl_rule *rule,
  513. int flags)
  514. {
  515. int err;
  516. struct nl_msg *msg;
  517. msg = rtnl_rule_build_delete_request(rule, flags);
  518. if (!msg)
  519. return nl_errno(ENOMEM);
  520. err = nl_send_auto_complete(handle, msg);
  521. nlmsg_free(msg);
  522. if (err < 0)
  523. return err;
  524. return nl_wait_for_ack(handle);
  525. }
  526. /** @} */
  527. /**
  528. * @name Attribute Modification
  529. * @{
  530. */
  531. void rtnl_rule_set_family(struct rtnl_rule *rule, int family)
  532. {
  533. rule->r_family = family;
  534. rule->ce_mask |= RULE_ATTR_FAMILY;
  535. }
  536. int rtnl_rule_get_family(struct rtnl_rule *rule)
  537. {
  538. if (rule->ce_mask & RULE_ATTR_FAMILY)
  539. return rule->r_family;
  540. else
  541. return AF_UNSPEC;
  542. }
  543. void rtnl_rule_set_prio(struct rtnl_rule *rule, int prio)
  544. {
  545. rule->r_prio = prio;
  546. rule->ce_mask |= RULE_ATTR_PRIO;
  547. }
  548. int rtnl_rule_get_prio(struct rtnl_rule *rule)
  549. {
  550. if (rule->ce_mask & RULE_ATTR_PRIO)
  551. return rule->r_prio;
  552. else
  553. return -1;
  554. }
  555. void rtnl_rule_set_mark(struct rtnl_rule *rule, uint64_t mark)
  556. {
  557. rule->r_mark = mark;
  558. rule->ce_mask |= RULE_ATTR_MARK;
  559. }
  560. uint64_t rtnl_rule_get_mark(struct rtnl_rule *rule)
  561. {
  562. if (rule->ce_mask & RULE_ATTR_MARK)
  563. return rule->r_mark;
  564. else
  565. return UINT_LEAST64_MAX;
  566. }
  567. void rtnl_rule_set_table(struct rtnl_rule *rule, int table)
  568. {
  569. rule->r_table = table;
  570. rule->ce_mask |= RULE_ATTR_TABLE;
  571. }
  572. int rtnl_rule_get_table(struct rtnl_rule *rule)
  573. {
  574. if (rule->ce_mask & RULE_ATTR_TABLE)
  575. return rule->r_table;
  576. else
  577. return -1;
  578. }
  579. void rtnl_rule_set_dsfield(struct rtnl_rule *rule, int dsfield)
  580. {
  581. rule->r_dsfield = dsfield;
  582. rule->ce_mask |= RULE_ATTR_DSFIELD;
  583. }
  584. int rtnl_rule_get_dsfield(struct rtnl_rule *rule)
  585. {
  586. if (rule->ce_mask & RULE_ATTR_DSFIELD)
  587. return rule->r_dsfield;
  588. else
  589. return -1;
  590. }
  591. void rtnl_rule_set_src_len(struct rtnl_rule *rule, int len)
  592. {
  593. rule->r_src_len = len;
  594. if (rule->ce_mask & RULE_ATTR_SRC)
  595. nl_addr_set_prefixlen(rule->r_src, len);
  596. rule->ce_mask |= RULE_ATTR_SRC_LEN;
  597. }
  598. int rtnl_rule_get_src_len(struct rtnl_rule *rule)
  599. {
  600. if (rule->ce_mask & RULE_ATTR_SRC_LEN)
  601. return rule->r_src_len;
  602. else
  603. return -1;
  604. }
  605. void rtnl_rule_set_dst_len(struct rtnl_rule *rule, int len)
  606. {
  607. rule->r_dst_len = len;
  608. if (rule->ce_mask & RULE_ATTR_DST)
  609. nl_addr_set_prefixlen(rule->r_dst, len);
  610. rule->ce_mask |= RULE_ATTR_DST_LEN;
  611. }
  612. int rtnl_rule_get_dst_len(struct rtnl_rule *rule)
  613. {
  614. if (rule->ce_mask & RULE_ATTR_DST_LEN)
  615. return rule->r_dst_len;
  616. else
  617. return -1;
  618. }
  619. static inline int __assign_addr(struct rtnl_rule *rule, struct nl_addr **pos,
  620. struct nl_addr *new, uint8_t *len, int flag)
  621. {
  622. if (rule->ce_mask & RULE_ATTR_FAMILY) {
  623. if (new->a_family != rule->r_family)
  624. return nl_error(EINVAL, "Address family mismatch");
  625. } else
  626. rule->r_family = new->a_family;
  627. if (*pos)
  628. nl_addr_put(*pos);
  629. nl_addr_get(new);
  630. *pos = new;
  631. *len = nl_addr_get_prefixlen(new);
  632. rule->ce_mask |= (flag | RULE_ATTR_FAMILY);
  633. return 0;
  634. }
  635. int rtnl_rule_set_src(struct rtnl_rule *rule, struct nl_addr *src)
  636. {
  637. return __assign_addr(rule, &rule->r_src, src, &rule->r_src_len,
  638. RULE_ATTR_SRC | RULE_ATTR_SRC_LEN);
  639. }
  640. struct nl_addr *rtnl_rule_get_src(struct rtnl_rule *rule)
  641. {
  642. if (rule->ce_mask & RULE_ATTR_SRC)
  643. return rule->r_src;
  644. else
  645. return NULL;
  646. }
  647. int rtnl_rule_set_dst(struct rtnl_rule *rule, struct nl_addr *dst)
  648. {
  649. return __assign_addr(rule, &rule->r_dst, dst, &rule->r_dst_len,
  650. RULE_ATTR_DST | RULE_ATTR_DST_LEN);
  651. }
  652. struct nl_addr *rtnl_rule_get_dst(struct rtnl_rule *rule)
  653. {
  654. if (rule->ce_mask & RULE_ATTR_DST)
  655. return rule->r_dst;
  656. else
  657. return NULL;
  658. }
  659. int rtnl_rule_set_iif(struct rtnl_rule *rule, const char *dev)
  660. {
  661. if (strlen(dev) > IFNAMSIZ-1)
  662. return nl_errno(ERANGE);
  663. strcpy(rule->r_iif, dev);
  664. rule->ce_mask |= RULE_ATTR_IIF;
  665. return 0;
  666. }
  667. char *rtnl_rule_get_iif(struct rtnl_rule *rule)
  668. {
  669. if (rule->ce_mask & RULE_ATTR_IIF)
  670. return rule->r_iif;
  671. else
  672. return NULL;
  673. }
  674. void rtnl_rule_set_action(struct rtnl_rule *rule, int type)
  675. {
  676. rule->r_type = type;
  677. rule->ce_mask |= RULE_ATTR_TYPE;
  678. }
  679. int rtnl_rule_get_action(struct rtnl_rule *rule)
  680. {
  681. if (rule->ce_mask & RULE_ATTR_TYPE)
  682. return rule->r_type;
  683. else
  684. return nl_errno(ENOENT);
  685. }
  686. void rtnl_rule_set_realms(struct rtnl_rule *rule, realm_t realms)
  687. {
  688. rule->r_realms = realms;
  689. rule->ce_mask |= RULE_ATTR_REALMS;
  690. }
  691. realm_t rtnl_rule_get_realms(struct rtnl_rule *rule)
  692. {
  693. if (rule->ce_mask & RULE_ATTR_REALMS)
  694. return rule->r_realms;
  695. else
  696. return 0;
  697. }
  698. /** @} */
  699. static struct nl_object_ops rule_obj_ops = {
  700. .oo_name = "route/rule",
  701. .oo_size = sizeof(struct rtnl_rule),
  702. .oo_free_data = rule_free_data,
  703. .oo_clone = rule_clone,
  704. .oo_dump[NL_DUMP_BRIEF] = rule_dump_brief,
  705. .oo_dump[NL_DUMP_FULL] = rule_dump_full,
  706. .oo_dump[NL_DUMP_STATS] = rule_dump_stats,
  707. .oo_dump[NL_DUMP_XML] = rule_dump_xml,
  708. .oo_dump[NL_DUMP_ENV] = rule_dump_env,
  709. .oo_compare = rule_compare,
  710. .oo_attrs2str = rule_attrs2str,
  711. .oo_id_attrs = ~0,
  712. };
  713. static struct nl_cache_ops rtnl_rule_ops = {
  714. .co_name = "route/rule",
  715. .co_hdrsize = sizeof(struct rtmsg),
  716. .co_msgtypes = {
  717. { RTM_NEWRULE, NL_ACT_NEW, "new" },
  718. { RTM_DELRULE, NL_ACT_DEL, "del" },
  719. { RTM_GETRULE, NL_ACT_GET, "get" },
  720. END_OF_MSGTYPES_LIST,
  721. },
  722. .co_protocol = NETLINK_ROUTE,
  723. .co_request_update = rule_request_update,
  724. .co_msg_parser = rule_msg_parser,
  725. .co_obj_ops = &rule_obj_ops,
  726. };
  727. static void __init rule_init(void)
  728. {
  729. nl_cache_mngt_register(&rtnl_rule_ops);
  730. }
  731. static void __exit rule_exit(void)
  732. {
  733. nl_cache_mngt_unregister(&rtnl_rule_ops);
  734. }
  735. /** @} */