ip6_fw.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:7k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * IPv6 Firewall
  3.  * Linux INET6 implementation
  4.  *
  5.  * Authors:
  6.  * Pedro Roque <roque@di.fc.ul.pt>
  7.  *
  8.  * $Id: ip6_fw.c,v 1.16 2001/10/31 08:17:58 davem Exp $
  9.  *
  10.  * This program is free software; you can redistribute it and/or
  11.  *      modify it under the terms of the GNU General Public License
  12.  *      as published by the Free Software Foundation; either version
  13.  *      2 of the License, or (at your option) any later version.
  14.  */
  15. #include <linux/config.h>
  16. #include <linux/errno.h>
  17. #include <linux/types.h>
  18. #include <linux/string.h>
  19. #include <linux/socket.h>
  20. #include <linux/sockios.h>
  21. #include <linux/net.h>
  22. #include <linux/route.h>
  23. #include <linux/netdevice.h>
  24. #include <linux/in6.h>
  25. #include <linux/udp.h>
  26. #include <linux/init.h>
  27. #include <net/ipv6.h>
  28. #include <net/ip6_route.h>
  29. #include <net/ip6_fw.h>
  30. #include <net/netlink.h>
  31. static unsigned long ip6_fw_rule_cnt;
  32. static struct ip6_fw_rule ip6_fw_rule_list = {
  33. {0},
  34. NULL, NULL,
  35. {0},
  36. IP6_FW_REJECT
  37. };
  38. static int ip6_fw_accept(struct dst_entry *dst, struct fl_acc_args *args);
  39. struct flow_rule_ops ip6_fw_ops = {
  40. ip6_fw_accept
  41. };
  42. static struct rt6_info ip6_fw_null_entry = {
  43. {{NULL, 0, 0, NULL,
  44.   0, 0, 0, 0, 0, 0, 0, 0, -ENETUNREACH, NULL, NULL,
  45.   ip6_pkt_discard, ip6_pkt_discard, NULL}},
  46. NULL, {{{0}}}, 256, RTF_REJECT|RTF_NONEXTHOP, ~0UL,
  47. 0, &ip6_fw_rule_list, {{{{0}}}, 128}, {{{{0}}}, 128}
  48. };
  49. static struct fib6_node ip6_fw_fib = {
  50. NULL, NULL, NULL, NULL,
  51. &ip6_fw_null_entry,
  52. 0, RTN_ROOT|RTN_TL_ROOT, 0
  53. };
  54. rwlock_t ip6_fw_lock = RW_LOCK_UNLOCKED;
  55. static void ip6_rule_add(struct ip6_fw_rule *rl)
  56. {
  57. struct ip6_fw_rule *next;
  58. write_lock_bh(&ip6_fw_lock);
  59. ip6_fw_rule_cnt++;
  60. next = &ip6_fw_rule_list;
  61. rl->next = next;
  62. rl->prev = next->prev;
  63. rl->prev->next = rl;
  64. next->prev = rl;
  65. write_unlock_bh(&ip6_fw_lock);
  66. }
  67. static void ip6_rule_del(struct ip6_fw_rule *rl)
  68. {
  69. struct ip6_fw_rule *next, *prev;
  70. write_lock_bh(&ip6_fw_lock);
  71. ip6_fw_rule_cnt--;
  72. next = rl->next;
  73. prev = rl->prev;
  74. next->prev = prev;
  75. prev->next = next;
  76. write_unlock_bh(&ip6_fw_lock);
  77. }
  78. static __inline__ struct ip6_fw_rule * ip6_fwrule_alloc(void)
  79. {
  80. struct ip6_fw_rule *rl;
  81. rl = kmalloc(sizeof(struct ip6_fw_rule), GFP_ATOMIC);
  82. if (rl)
  83. {
  84. memset(rl, 0, sizeof(struct ip6_fw_rule));
  85. rl->flowr.ops = &ip6_fw_ops;
  86. }
  87. return rl;
  88. }
  89. static __inline__ void ip6_fwrule_free(struct ip6_fw_rule * rl)
  90. {
  91. kfree(rl);
  92. }
  93. static __inline__ int port_match(int rl_port, int fl_port)
  94. {
  95. int res = 0;
  96. if (rl_port == 0 || (rl_port == fl_port))
  97. res = 1;
  98. return res;
  99. }
  100. static int ip6_fw_accept_trans(struct ip6_fw_rule *rl,
  101.        struct fl_acc_args *args)
  102. {
  103. int res = FLOWR_NODECISION;
  104. int proto = 0;
  105. int sport = 0;
  106. int dport = 0;
  107. switch (args->type) {
  108. case FL_ARG_FORWARD:
  109. {
  110. struct sk_buff *skb = args->fl_u.skb;
  111. struct ipv6hdr *hdr = skb->nh.ipv6h;
  112. int len;
  113. len = skb->len - sizeof(struct ipv6hdr);
  114. proto = hdr->nexthdr;
  115. switch (proto) {
  116. case IPPROTO_TCP:
  117. {
  118. struct tcphdr *th;
  119. if (len < sizeof(struct tcphdr)) {
  120. res = FLOWR_ERROR;
  121. goto out;
  122. }
  123. th = (struct tcphdr *)(hdr + 1);
  124. sport = th->source;
  125. dport = th->dest;
  126. break;
  127. }
  128. case IPPROTO_UDP:
  129. {
  130. struct udphdr *uh;
  131. if (len < sizeof(struct udphdr)) {
  132. res = FLOWR_ERROR;
  133. goto out;
  134. }
  135. uh = (struct udphdr *)(hdr + 1);
  136. sport = uh->source;
  137. dport = uh->dest;
  138. break;
  139. }
  140. default:
  141. goto out;
  142. };
  143. break;
  144. }
  145. case FL_ARG_ORIGIN:
  146. {
  147. proto = args->fl_u.fl_o.flow->proto;
  148. if (proto == IPPROTO_ICMPV6) {
  149. goto out;
  150. } else {
  151. sport = args->fl_u.fl_o.flow->uli_u.ports.sport;
  152. dport = args->fl_u.fl_o.flow->uli_u.ports.dport;
  153. }
  154. break;
  155. }
  156. if (proto == rl->info.proto &&
  157.     port_match(args->fl_u.fl_o.flow->uli_u.ports.sport, sport) &&
  158.     port_match(args->fl_u.fl_o.flow->uli_u.ports.dport, dport)) {
  159. if (rl->policy & IP6_FW_REJECT)
  160. res = FLOWR_SELECT;
  161. else
  162. res = FLOWR_CLEAR;
  163. }
  164. default:
  165. #if IP6_FW_DEBUG >= 1
  166. printk(KERN_DEBUG "ip6_fw_accept: unknown arg typen");
  167. #endif
  168. goto out;
  169. };
  170. out:
  171. return res;
  172. }
  173. static int ip6_fw_accept(struct dst_entry *dst, struct fl_acc_args *args)
  174. {
  175. struct rt6_info *rt;
  176. struct ip6_fw_rule *rl;
  177. int proto;
  178. int res = FLOWR_NODECISION;
  179. rt = (struct rt6_info *) dst;
  180. rl = (struct ip6_fw_rule *) rt->rt6i_flowr;
  181. proto = rl->info.proto;
  182. switch (proto) {
  183. case 0:
  184. if (rl->policy & IP6_FW_REJECT)
  185. res = FLOWR_SELECT;
  186. else
  187. res = FLOWR_CLEAR;
  188. break;
  189. case IPPROTO_TCP:
  190. case IPPROTO_UDP:
  191. res = ip6_fw_accept_trans(rl, args);
  192. break;
  193. case IPPROTO_ICMPV6:
  194. };
  195. return res;
  196. }
  197. static struct dst_entry * ip6_fw_dup(struct dst_entry *frule,
  198.      struct dst_entry *rt,
  199.      struct fl_acc_args *args)
  200. {
  201. struct ip6_fw_rule *rl;
  202. struct rt6_info *nrt;
  203. struct rt6_info *frt;
  204. frt = (struct rt6_info *) frule;
  205. rl = (struct ip6_fw_rule *) frt->rt6i_flowr;
  206. nrt = ip6_rt_copy((struct rt6_info *) rt);
  207. if (nrt) {
  208. nrt->u.dst.input = frule->input;
  209. nrt->u.dst.output = frule->output;
  210. nrt->rt6i_flowr = flow_clone(frt->rt6i_flowr);
  211. nrt->rt6i_flags |= RTF_CACHE;
  212. nrt->rt6i_tstamp = jiffies;
  213. }
  214. return (struct dst_entry *) nrt;
  215. }
  216. int ip6_fw_reject(struct sk_buff *skb)
  217. {
  218. #if IP6_FW_DEBUG >= 1
  219. printk(KERN_DEBUG "packet rejected: n");
  220. #endif
  221. icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_ADM_PROHIBITED, 0,
  222.     skb->dev);
  223. /*
  224.  * send it via netlink, as (rule, skb)
  225.  */
  226. kfree_skb(skb);
  227. return 0;
  228. }
  229. int ip6_fw_discard(struct sk_buff *skb)
  230. {
  231. printk(KERN_DEBUG "ip6_fw: BUG fw_reject calledn");
  232. kfree_skb(skb);
  233. return 0;
  234. }
  235. int ip6_fw_msg_add(struct ip6_fw_msg *msg)
  236. {
  237. struct in6_rtmsg rtmsg;
  238. struct ip6_fw_rule *rl;
  239. struct rt6_info *rt;
  240. int err;
  241. ipv6_addr_copy(&rtmsg.rtmsg_dst, &msg->dst);
  242. ipv6_addr_copy(&rtmsg.rtmsg_src, &msg->src);
  243. rtmsg.rtmsg_dst_len = msg->dst_len;
  244. rtmsg.rtmsg_src_len = msg->src_len;
  245. rtmsg.rtmsg_metric = IP6_RT_PRIO_FW;
  246. rl = ip6_fwrule_alloc();
  247. if (rl == NULL)
  248. return -ENOMEM;
  249. rl->policy = msg->policy;
  250. rl->info.proto = msg->proto;
  251. rl->info.uli_u.data = msg->u.data;
  252. rtmsg.rtmsg_flags = RTF_NONEXTHOP|RTF_POLICY;
  253. err = ip6_route_add(&rtmsg);
  254. if (err) {
  255. ip6_fwrule_free(rl);
  256. return err;
  257. }
  258. /* The rest will not work for now. --ABK (989725) */
  259. #ifndef notdef
  260. ip6_fwrule_free(rl);
  261. return -EPERM;
  262. #else
  263. rt->u.dst.error = -EPERM;
  264. if (msg->policy == IP6_FW_ACCEPT) {
  265. /*
  266.  * Accept rules are never selected
  267.  * (i.e. packets use normal forwarding)
  268.  */
  269. rt->u.dst.input = ip6_fw_discard;
  270. rt->u.dst.output = ip6_fw_discard;
  271. } else {
  272. rt->u.dst.input = ip6_fw_reject;
  273. rt->u.dst.output = ip6_fw_reject;
  274. }
  275. ip6_rule_add(rl);
  276. rt->rt6i_flowr = flow_clone((struct flow_rule *)rl);
  277. return 0;
  278. #endif
  279. }
  280. static int ip6_fw_msgrcv(int unit, struct sk_buff *skb)
  281. {
  282. int count = 0;
  283. while (skb->len) {
  284. struct ip6_fw_msg *msg;
  285. if (skb->len < sizeof(struct ip6_fw_msg)) {
  286. count = -EINVAL;
  287. break;
  288. }
  289. msg = (struct ip6_fw_msg *) skb->data;
  290. skb_pull(skb, sizeof(struct ip6_fw_msg));
  291. count += sizeof(struct ip6_fw_msg);
  292. switch (msg->action) {
  293. case IP6_FW_MSG_ADD:
  294. ip6_fw_msg_add(msg);
  295. break;
  296. case IP6_FW_MSG_DEL:
  297. break;
  298. default:
  299. return -EINVAL;
  300. };
  301. }
  302. return count;
  303. }
  304. static void ip6_fw_destroy(struct flow_rule *rl)
  305. {
  306. ip6_fwrule_free((struct ip6_fw_rule *)rl);
  307. }
  308. #ifdef MODULE
  309. #define ip6_fw_init module_init
  310. #endif
  311. void __init ip6_fw_init(void)
  312. {
  313. netlink_attach(NETLINK_IP6_FW, ip6_fw_msgrcv);
  314. }
  315. #ifdef MODULE
  316. void cleanup_module(void)
  317. {
  318. netlink_detach(NETLINK_IP6_FW);
  319. }
  320. #endif