/net/ipv4/netfilter/nf_defrag_ipv4.c

https://bitbucket.org/abioy/linux · C · 121 lines · 93 code · 17 blank · 11 comment · 13 complexity · 65ffe94947dc1c3173c99ebbe275609d MD5 · raw file

  1. /* (C) 1999-2001 Paul `Rusty' Russell
  2. * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License version 2 as
  6. * published by the Free Software Foundation.
  7. */
  8. #include <linux/types.h>
  9. #include <linux/ip.h>
  10. #include <linux/netfilter.h>
  11. #include <linux/module.h>
  12. #include <linux/skbuff.h>
  13. #include <net/route.h>
  14. #include <net/ip.h>
  15. #include <linux/netfilter_bridge.h>
  16. #include <linux/netfilter_ipv4.h>
  17. #include <net/netfilter/ipv4/nf_defrag_ipv4.h>
  18. #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
  19. #include <net/netfilter/nf_conntrack.h>
  20. #endif
  21. #include <net/netfilter/nf_conntrack_zones.h>
  22. /* Returns new sk_buff, or NULL */
  23. static int nf_ct_ipv4_gather_frags(struct sk_buff *skb, u_int32_t user)
  24. {
  25. int err;
  26. skb_orphan(skb);
  27. local_bh_disable();
  28. err = ip_defrag(skb, user);
  29. local_bh_enable();
  30. if (!err)
  31. ip_send_check(ip_hdr(skb));
  32. return err;
  33. }
  34. static enum ip_defrag_users nf_ct_defrag_user(unsigned int hooknum,
  35. struct sk_buff *skb)
  36. {
  37. u16 zone = NF_CT_DEFAULT_ZONE;
  38. #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
  39. if (skb->nfct)
  40. zone = nf_ct_zone((struct nf_conn *)skb->nfct);
  41. #endif
  42. #ifdef CONFIG_BRIDGE_NETFILTER
  43. if (skb->nf_bridge &&
  44. skb->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING)
  45. return IP_DEFRAG_CONNTRACK_BRIDGE_IN + zone;
  46. #endif
  47. if (hooknum == NF_INET_PRE_ROUTING)
  48. return IP_DEFRAG_CONNTRACK_IN + zone;
  49. else
  50. return IP_DEFRAG_CONNTRACK_OUT + zone;
  51. }
  52. static unsigned int ipv4_conntrack_defrag(unsigned int hooknum,
  53. struct sk_buff *skb,
  54. const struct net_device *in,
  55. const struct net_device *out,
  56. int (*okfn)(struct sk_buff *))
  57. {
  58. #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
  59. #if !defined(CONFIG_NF_NAT) && !defined(CONFIG_NF_NAT_MODULE)
  60. /* Previously seen (loopback)? Ignore. Do this before
  61. fragment check. */
  62. if (skb->nfct && !nf_ct_is_template((struct nf_conn *)skb->nfct))
  63. return NF_ACCEPT;
  64. #endif
  65. #endif
  66. /* Gather fragments. */
  67. if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) {
  68. enum ip_defrag_users user = nf_ct_defrag_user(hooknum, skb);
  69. if (nf_ct_ipv4_gather_frags(skb, user))
  70. return NF_STOLEN;
  71. }
  72. return NF_ACCEPT;
  73. }
  74. static struct nf_hook_ops ipv4_defrag_ops[] = {
  75. {
  76. .hook = ipv4_conntrack_defrag,
  77. .owner = THIS_MODULE,
  78. .pf = PF_INET,
  79. .hooknum = NF_INET_PRE_ROUTING,
  80. .priority = NF_IP_PRI_CONNTRACK_DEFRAG,
  81. },
  82. {
  83. .hook = ipv4_conntrack_defrag,
  84. .owner = THIS_MODULE,
  85. .pf = PF_INET,
  86. .hooknum = NF_INET_LOCAL_OUT,
  87. .priority = NF_IP_PRI_CONNTRACK_DEFRAG,
  88. },
  89. };
  90. static int __init nf_defrag_init(void)
  91. {
  92. return nf_register_hooks(ipv4_defrag_ops, ARRAY_SIZE(ipv4_defrag_ops));
  93. }
  94. static void __exit nf_defrag_fini(void)
  95. {
  96. nf_unregister_hooks(ipv4_defrag_ops, ARRAY_SIZE(ipv4_defrag_ops));
  97. }
  98. void nf_defrag_ipv4_enable(void)
  99. {
  100. }
  101. EXPORT_SYMBOL_GPL(nf_defrag_ipv4_enable);
  102. module_init(nf_defrag_init);
  103. module_exit(nf_defrag_fini);
  104. MODULE_LICENSE("GPL");