ebt_ip.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. /*
  2. * ebt_ip
  3. *
  4. * Authors:
  5. * Bart De Schuymer <bdschuym@pandora.be>
  6. *
  7. * April, 2002
  8. *
  9. * Changes:
  10. * added ip-sport and ip-dport
  11. * Innominate Security Technologies AG <mhopf@innominate.com>
  12. * September, 2002
  13. */
  14. #include <linux/ip.h>
  15. #include <net/ip.h>
  16. #include <linux/in.h>
  17. #include <linux/module.h>
  18. #include <linux/netfilter/x_tables.h>
  19. #include <linux/netfilter_bridge/ebtables.h>
  20. #include <linux/netfilter_bridge/ebt_ip.h>
  21. struct tcpudphdr {
  22. __be16 src;
  23. __be16 dst;
  24. };
  25. static bool
  26. ebt_ip_mt(const struct sk_buff *skb, struct xt_action_param *par)
  27. {
  28. const struct ebt_ip_info *info = par->matchinfo;
  29. const struct iphdr *ih;
  30. struct iphdr _iph;
  31. const struct tcpudphdr *pptr;
  32. struct tcpudphdr _ports;
  33. ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph);
  34. if (ih == NULL)
  35. return false;
  36. if (info->bitmask & EBT_IP_TOS &&
  37. FWINV(info->tos != ih->tos, EBT_IP_TOS))
  38. return false;
  39. if (info->bitmask & EBT_IP_SOURCE &&
  40. FWINV((ih->saddr & info->smsk) !=
  41. info->saddr, EBT_IP_SOURCE))
  42. return false;
  43. if ((info->bitmask & EBT_IP_DEST) &&
  44. FWINV((ih->daddr & info->dmsk) !=
  45. info->daddr, EBT_IP_DEST))
  46. return false;
  47. if (info->bitmask & EBT_IP_PROTO) {
  48. if (FWINV(info->protocol != ih->protocol, EBT_IP_PROTO))
  49. return false;
  50. if (!(info->bitmask & EBT_IP_DPORT) &&
  51. !(info->bitmask & EBT_IP_SPORT))
  52. return true;
  53. if (ntohs(ih->frag_off) & IP_OFFSET)
  54. return false;
  55. pptr = skb_header_pointer(skb, ih->ihl*4,
  56. sizeof(_ports), &_ports);
  57. if (pptr == NULL)
  58. return false;
  59. if (info->bitmask & EBT_IP_DPORT) {
  60. u32 dst = ntohs(pptr->dst);
  61. if (FWINV(dst < info->dport[0] ||
  62. dst > info->dport[1],
  63. EBT_IP_DPORT))
  64. return false;
  65. }
  66. if (info->bitmask & EBT_IP_SPORT) {
  67. u32 src = ntohs(pptr->src);
  68. if (FWINV(src < info->sport[0] ||
  69. src > info->sport[1],
  70. EBT_IP_SPORT))
  71. return false;
  72. }
  73. }
  74. return true;
  75. }
  76. static int ebt_ip_mt_check(const struct xt_mtchk_param *par)
  77. {
  78. const struct ebt_ip_info *info = par->matchinfo;
  79. const struct ebt_entry *e = par->entryinfo;
  80. if (e->ethproto != htons(ETH_P_IP) ||
  81. e->invflags & EBT_IPROTO)
  82. return -EINVAL;
  83. if (info->bitmask & ~EBT_IP_MASK || info->invflags & ~EBT_IP_MASK)
  84. return -EINVAL;
  85. if (info->bitmask & (EBT_IP_DPORT | EBT_IP_SPORT)) {
  86. if (info->invflags & EBT_IP_PROTO)
  87. return -EINVAL;
  88. if (info->protocol != IPPROTO_TCP &&
  89. info->protocol != IPPROTO_UDP &&
  90. info->protocol != IPPROTO_UDPLITE &&
  91. info->protocol != IPPROTO_SCTP &&
  92. info->protocol != IPPROTO_DCCP)
  93. return -EINVAL;
  94. }
  95. if (info->bitmask & EBT_IP_DPORT && info->dport[0] > info->dport[1])
  96. return -EINVAL;
  97. if (info->bitmask & EBT_IP_SPORT && info->sport[0] > info->sport[1])
  98. return -EINVAL;
  99. return 0;
  100. }
  101. static struct xt_match ebt_ip_mt_reg __read_mostly = {
  102. .name = "ip",
  103. .revision = 0,
  104. .family = NFPROTO_BRIDGE,
  105. .match = ebt_ip_mt,
  106. .checkentry = ebt_ip_mt_check,
  107. .matchsize = sizeof(struct ebt_ip_info),
  108. .me = THIS_MODULE,
  109. };
  110. static int __init ebt_ip_init(void)
  111. {
  112. return xt_register_match(&ebt_ip_mt_reg);
  113. }
  114. static void __exit ebt_ip_fini(void)
  115. {
  116. xt_unregister_match(&ebt_ip_mt_reg);
  117. }
  118. module_init(ebt_ip_init);
  119. module_exit(ebt_ip_fini);
  120. MODULE_DESCRIPTION("Ebtables: IPv4 protocol packet match");
  121. MODULE_LICENSE("GPL");