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

嵌入式Linux

开发平台:

Unix_Linux

  1. /* Compatibility framework for ipchains and ipfwadm support; designed
  2.    to look as much like the 2.2 infrastructure as possible. */
  3. struct notifier_block;
  4. #include <linux/netfilter_ipv4.h>
  5. #include <linux/ip.h>
  6. #include <net/icmp.h>
  7. #include <linux/if.h>
  8. #include <linux/inetdevice.h>
  9. #include <linux/netdevice.h>
  10. #include <linux/module.h>
  11. #include <asm/uaccess.h>
  12. #include <net/ip.h>
  13. #include <net/route.h>
  14. #include <linux/netfilter_ipv4/compat_firewall.h>
  15. #include <linux/netfilter_ipv4/ip_conntrack.h>
  16. #include <linux/netfilter_ipv4/ip_conntrack_core.h>
  17. /* Theoretically, we could one day use 2.4 helpers, but for now it
  18.    just confuses depmod --RR */
  19. EXPORT_NO_SYMBOLS;
  20. static struct firewall_ops *fwops;
  21. /* From ip_fw_compat_redir.c */
  22. extern unsigned int
  23. do_redirect(struct sk_buff *skb,
  24.     const struct net_device *dev,
  25.     u_int16_t redirpt);
  26. extern void
  27. check_for_redirect(struct sk_buff *skb);
  28. extern void
  29. check_for_unredirect(struct sk_buff *skb);
  30. /* From ip_fw_compat_masq.c */
  31. extern unsigned int
  32. do_masquerade(struct sk_buff **pskb, const struct net_device *dev);
  33. extern unsigned int
  34. check_for_masq_error(struct sk_buff *pskb);
  35. extern unsigned int
  36. check_for_demasq(struct sk_buff **pskb);
  37. extern int __init masq_init(void);
  38. extern void masq_cleanup(void);
  39. /* They call these; we do what they want. */
  40. int register_firewall(int pf, struct firewall_ops *fw)
  41. {
  42. if (pf != PF_INET) {
  43. printk("Attempt to register non-IP firewall module.n");
  44. return -EINVAL;
  45. }
  46. if (fwops) {
  47. printk("Attempt to register multiple firewall modules.n");
  48. return -EBUSY;
  49. }
  50. fwops = fw;
  51. return 0;
  52. }
  53. int unregister_firewall(int pf, struct firewall_ops *fw)
  54. {
  55. fwops = NULL;
  56. return 0;
  57. }
  58. static unsigned int
  59. fw_in(unsigned int hooknum,
  60.       struct sk_buff **pskb,
  61.       const struct net_device *in,
  62.       const struct net_device *out,
  63.       int (*okfn)(struct sk_buff *))
  64. {
  65. int ret = FW_BLOCK;
  66. u_int16_t redirpt;
  67. /* Assume worse case: any hook could change packet */
  68. (*pskb)->nfcache |= NFC_UNKNOWN | NFC_ALTERED;
  69. if ((*pskb)->ip_summed == CHECKSUM_HW)
  70. (*pskb)->ip_summed = CHECKSUM_NONE;
  71. /* Firewall rules can alter TOS: raw socket (tcpdump) may have
  72.            clone of incoming skb: don't disturb it --RR */
  73. if (skb_cloned(*pskb) && !(*pskb)->sk) {
  74. struct sk_buff *nskb = skb_copy(*pskb, GFP_ATOMIC);
  75. if (!nskb)
  76. return NF_DROP;
  77. kfree_skb(*pskb);
  78. *pskb = nskb;
  79. }
  80. switch (hooknum) {
  81. case NF_IP_PRE_ROUTING:
  82. if (fwops->fw_acct_in)
  83. fwops->fw_acct_in(fwops, PF_INET,
  84.   (struct net_device *)in,
  85.   (*pskb)->nh.raw, &redirpt, pskb);
  86. if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
  87. *pskb = ip_ct_gather_frags(*pskb);
  88. if (!*pskb)
  89. return NF_STOLEN;
  90. }
  91. ret = fwops->fw_input(fwops, PF_INET, (struct net_device *)in,
  92.       (*pskb)->nh.raw, &redirpt, pskb);
  93. break;
  94. case NF_IP_FORWARD:
  95. /* Connection will only be set if it was
  96.                    demasqueraded: if so, skip forward chain. */
  97. if ((*pskb)->nfct)
  98. ret = FW_ACCEPT;
  99. else ret = fwops->fw_forward(fwops, PF_INET,
  100.      (struct net_device *)out,
  101.      (*pskb)->nh.raw, &redirpt, pskb);
  102. break;
  103. case NF_IP_POST_ROUTING:
  104. ret = fwops->fw_output(fwops, PF_INET,
  105.        (struct net_device *)out,
  106.        (*pskb)->nh.raw, &redirpt, pskb);
  107. if (ret == FW_ACCEPT || ret == FW_SKIP) {
  108. if (fwops->fw_acct_out)
  109. fwops->fw_acct_out(fwops, PF_INET,
  110.    (struct net_device *)out,
  111.    (*pskb)->nh.raw, &redirpt,
  112.    pskb);
  113. /* ip_conntrack_confirm return NF_DROP or NF_ACCEPT */
  114. if (ip_conntrack_confirm(*pskb) == NF_DROP)
  115. ret = FW_BLOCK;
  116. }
  117. break;
  118. }
  119. switch (ret) {
  120. case FW_REJECT: {
  121. /* Alexey says:
  122.  *
  123.  * Generally, routing is THE FIRST thing to make, when
  124.  * packet enters IP stack. Before packet is routed you
  125.  * cannot call any service routines from IP stack.  */
  126. struct iphdr *iph = (*pskb)->nh.iph;
  127. if ((*pskb)->dst != NULL
  128.     || ip_route_input(*pskb, iph->daddr, iph->saddr, iph->tos,
  129.       (struct net_device *)in) == 0)
  130. icmp_send(*pskb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH,
  131.   0);
  132. return NF_DROP;
  133. }
  134. case FW_ACCEPT:
  135. case FW_SKIP:
  136. if (hooknum == NF_IP_PRE_ROUTING) {
  137. check_for_demasq(pskb);
  138. check_for_redirect(*pskb);
  139. } else if (hooknum == NF_IP_POST_ROUTING) {
  140. check_for_unredirect(*pskb);
  141. /* Handle ICMP errors from client here */
  142. if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP
  143.     && (*pskb)->nfct)
  144. check_for_masq_error(*pskb);
  145. }
  146. return NF_ACCEPT;
  147. case FW_MASQUERADE:
  148. if (hooknum == NF_IP_FORWARD)
  149. return do_masquerade(pskb, out);
  150. else return NF_ACCEPT;
  151. case FW_REDIRECT:
  152. if (hooknum == NF_IP_PRE_ROUTING)
  153. return do_redirect(*pskb, in, redirpt);
  154. else return NF_ACCEPT;
  155. default:
  156. /* FW_BLOCK */
  157. return NF_DROP;
  158. }
  159. }
  160. static unsigned int fw_confirm(unsigned int hooknum,
  161.        struct sk_buff **pskb,
  162.        const struct net_device *in,
  163.        const struct net_device *out,
  164.        int (*okfn)(struct sk_buff *))
  165. {
  166. return ip_conntrack_confirm(*pskb);
  167. }
  168. extern int ip_fw_ctl(int optval, void *m, unsigned int len);
  169. static int sock_fn(struct sock *sk, int optval, void *user, unsigned int len)
  170. {
  171. /* MAX of:
  172.    2.2: sizeof(struct ip_fwtest) (~14x4 + 3x4 = 17x4)
  173.    2.2: sizeof(struct ip_fwnew) (~1x4 + 15x4 + 3x4 + 3x4 = 22x4)
  174.    2.0: sizeof(struct ip_fw) (~25x4)
  175.    We can't include both 2.0 and 2.2 headers, they conflict.
  176.    Hence, 200 is a good number. --RR */
  177. char tmp_fw[200];
  178. if (!capable(CAP_NET_ADMIN))
  179. return -EPERM;
  180. if (len > sizeof(tmp_fw) || len < 1)
  181. return -EINVAL;
  182. if (copy_from_user(&tmp_fw, user, len))
  183. return -EFAULT;
  184. return -ip_fw_ctl(optval, &tmp_fw, len);
  185. }
  186. static struct nf_hook_ops preroute_ops
  187. = { { NULL, NULL }, fw_in, PF_INET, NF_IP_PRE_ROUTING, NF_IP_PRI_FILTER };
  188. static struct nf_hook_ops postroute_ops
  189. = { { NULL, NULL }, fw_in, PF_INET, NF_IP_POST_ROUTING, NF_IP_PRI_FILTER };
  190. static struct nf_hook_ops forward_ops
  191. = { { NULL, NULL }, fw_in, PF_INET, NF_IP_FORWARD, NF_IP_PRI_FILTER };
  192. static struct nf_hook_ops local_in_ops
  193. = { { NULL, NULL }, fw_confirm, PF_INET, NF_IP_LOCAL_IN, NF_IP_PRI_LAST - 1 };
  194. static struct nf_sockopt_ops sock_ops
  195. = { { NULL, NULL }, PF_INET, 64, 64 + 1024 + 1, &sock_fn, 0, 0, NULL,
  196.     0, NULL };
  197. extern int ipfw_init_or_cleanup(int init);
  198. static int init_or_cleanup(int init)
  199. {
  200. int ret = 0;
  201. if (!init) goto cleanup;
  202. ret = nf_register_sockopt(&sock_ops);
  203. if (ret < 0)
  204. goto cleanup_nothing;
  205. ret = ipfw_init_or_cleanup(1);
  206. if (ret < 0)
  207. goto cleanup_sockopt;
  208. ret = masq_init();
  209. if (ret < 0)
  210. goto cleanup_ipfw;
  211. nf_register_hook(&preroute_ops);
  212. nf_register_hook(&postroute_ops);
  213. nf_register_hook(&forward_ops);
  214. nf_register_hook(&local_in_ops);
  215. return ret;
  216.  cleanup:
  217. nf_unregister_hook(&preroute_ops);
  218. nf_unregister_hook(&postroute_ops);
  219. nf_unregister_hook(&forward_ops);
  220. nf_unregister_hook(&local_in_ops);
  221. masq_cleanup();
  222.  cleanup_ipfw:
  223. ipfw_init_or_cleanup(0);
  224.  cleanup_sockopt:
  225. nf_unregister_sockopt(&sock_ops);
  226.  cleanup_nothing:
  227. return ret;
  228. }
  229. static int __init init(void)
  230. {
  231. return init_or_cleanup(1);
  232. }
  233. static void __exit fini(void)
  234. {
  235. init_or_cleanup(0);
  236. }
  237. module_init(init);
  238. module_exit(fini);