You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

krnl_rule.c 4.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. /* This file is part of Netsukuku
  2. * (c) Copyright 2005 Andrea Lo Pumo aka AlpT <alpt@freaknet.org>
  3. *
  4. * This source code is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License as published
  6. * by the Free Software Foundation; either version 2 of the License,
  7. * or (at your option) any later version.
  8. *
  9. * This source code is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  12. * Please refer to the GNU Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Public License along with
  15. * this source code; if not, write to:
  16. * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. *
  18. * --
  19. * This code derives from iproute2/iprule.c
  20. * written by Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>.
  21. */
  22. #include "includes.h"
  23. #include "libnetlink.h"
  24. #include "inet.h"
  25. #include "krnl_route.h"
  26. #include "krnl_rule.h"
  27. #include "common.h"
  28. int rule_exec(int rtm_cmd, inet_prefix * from, inet_prefix * to, char *dev,
  29. int prio, u_int fwmark, u_char table);
  30. int
  31. rule_add(inet_prefix * from, inet_prefix * to, char *dev,
  32. int prio, u_int fwmark, u_char table)
  33. {
  34. return rule_exec(RTM_NEWRULE, from, to, dev, prio, fwmark, table);
  35. }
  36. int
  37. rule_del(inet_prefix * from, inet_prefix * to, char *dev,
  38. int prio, u_int fwmark, u_char table)
  39. {
  40. return rule_exec(RTM_DELRULE, from, to, dev, prio, fwmark, table);
  41. }
  42. int
  43. rule_replace(inet_prefix * from, inet_prefix * to, char *dev,
  44. int prio, u_int fwmark, u_char table)
  45. {
  46. rule_del(from, to, dev, prio, fwmark, table);
  47. return rule_add(from, to, dev, prio, fwmark, table);
  48. }
  49. /*
  50. * rule_exec:
  51. * `from' and `to' have to be in network order
  52. */
  53. int
  54. rule_exec(int rtm_cmd, inet_prefix * from, inet_prefix * to, char *dev,
  55. int prio, u_int fwmark, u_char table)
  56. {
  57. struct {
  58. struct nlmsghdr nh;
  59. struct rtmsg rt;
  60. char buf[1024];
  61. } req;
  62. struct rtnl_handle rth;
  63. setzero(&req, sizeof(req));
  64. table = !table ? RT_TABLE_MAIN : table;
  65. req.nh.nlmsg_type = rtm_cmd;
  66. req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
  67. req.nh.nlmsg_flags = NLM_F_REQUEST;
  68. req.rt.rtm_scope = RT_SCOPE_UNIVERSE;
  69. req.rt.rtm_type = RTN_UNSPEC;
  70. req.rt.rtm_family = AF_UNSPEC;
  71. req.rt.rtm_protocol = RTPROT_NETSUKUKU;
  72. req.rt.rtm_table = table;
  73. if (rtm_cmd == RTM_NEWRULE) {
  74. req.nh.nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
  75. req.rt.rtm_type = RTN_UNICAST;
  76. }
  77. if (from) {
  78. req.rt.rtm_src_len = from->bits;
  79. addattr_l(&req.nh, sizeof(req), RTA_SRC, &from->data, from->len);
  80. req.rt.rtm_family = from->family;
  81. }
  82. if (to) {
  83. req.rt.rtm_dst_len = to->bits;
  84. addattr_l(&req.nh, sizeof(req), RTA_DST, &to->data, to->len);
  85. req.rt.rtm_family = to->family;
  86. }
  87. if (prio)
  88. addattr32(&req.nh, sizeof(req), RTA_PRIORITY, prio);
  89. if (fwmark)
  90. addattr32(&req.nh, sizeof(req), RTA_PROTOINFO, fwmark);
  91. if (dev) {
  92. addattr_l(&req.nh, sizeof(req), RTA_IIF, dev, strlen(dev) + 1);
  93. }
  94. if (req.rt.rtm_family == AF_UNSPEC)
  95. req.rt.rtm_family = AF_INET;
  96. if (rtnl_open(&rth, 0) < 0)
  97. return 1;
  98. if (rtnl_talk(&rth, &req.nh, 0, 0, NULL, NULL, NULL) < 0)
  99. return 2;
  100. rtnl_close(&rth);
  101. return 0;
  102. }
  103. /*
  104. * rule_flush_table_range_filter: rtnl_dump filter for
  105. * rule_flush_table_range() (see below)
  106. */
  107. int
  108. rule_flush_table_range_filter(const struct sockaddr_nl *who,
  109. struct nlmsghdr *n, void *arg)
  110. {
  111. struct rtnl_handle rth2;
  112. struct rtmsg *r = NLMSG_DATA(n);
  113. int len = n->nlmsg_len;
  114. struct rtattr *tb[RTA_MAX + 1];
  115. u_int a = *(u_int *) arg;
  116. u_int b = *((u_int *) arg + 1);
  117. len -= NLMSG_LENGTH(sizeof(*r));
  118. if (len < 0)
  119. return -1;
  120. parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len);
  121. if (tb[RTA_PRIORITY] && (r->rtm_table >= a && r->rtm_table <= b)) {
  122. n->nlmsg_type = RTM_DELRULE;
  123. n->nlmsg_flags = NLM_F_REQUEST;
  124. if (rtnl_open(&rth2, 0) < 0)
  125. return -1;
  126. if (rtnl_talk(&rth2, n, 0, 0, NULL, NULL, NULL) < 0)
  127. return -2;
  128. rtnl_close(&rth2);
  129. }
  130. return 0;
  131. }
  132. /*
  133. * rule_flush_table_range: deletes all the rules which lookup the table X.
  134. * The table X is any table in the range of `a' <= X <= `b'.
  135. */
  136. int
  137. rule_flush_table_range(int family, int a, int b)
  138. {
  139. struct rtnl_handle rth;
  140. int arg[2];
  141. if (rtnl_open(&rth, 0) < 0)
  142. return 1;
  143. if (rtnl_wilddump_request(&rth, family, RTM_GETRULE) < 0) {
  144. error("Cannot dump the routing rule table");
  145. return -1;
  146. }
  147. arg[0] = a;
  148. arg[1] = b;
  149. if (rtnl_dump_filter
  150. (&rth, rule_flush_table_range_filter, arg, NULL, NULL) < 0) {
  151. error("Flush terminated");
  152. return -1;
  153. }
  154. rtnl_close(&rth);
  155. return 0;
  156. }