ebt_ip.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * ebt_ip
  4. *
  5. * Authors:
  6. * Bart De Schuymer <bdschuym@pandora.be>
  7. *
  8. * April, 2002
  9. *
  10. * Changes:
  11. * added ip-sport and ip-dport
  12. * Innominate Security Technologies AG <mhopf@innominate.com>
  13. * September, 2002
  14. */
  15. #include <linux/ip.h>
  16. #include <net/ip.h>
  17. #include <linux/in.h>
  18. #include <linux/module.h>
  19. #include <linux/netfilter/x_tables.h>
  20. #include <linux/netfilter_bridge/ebtables.h>
  21. #include <linux/netfilter_bridge/ebt_ip.h>
  22. union pkthdr {
  23. struct {
  24. __be16 src;
  25. __be16 dst;
  26. } tcpudphdr;
  27. struct {
  28. u8 type;
  29. u8 code;
  30. } icmphdr;
  31. struct {
  32. u8 type;
  33. } igmphdr;
  34. };
  35. static bool
  36. ebt_ip_mt(const struct sk_buff *skb, struct xt_action_param *par)
  37. {
  38. const struct ebt_ip_info *info = par->matchinfo;
  39. const struct iphdr *ih;
  40. struct iphdr _iph;
  41. const union pkthdr *pptr;
  42. union pkthdr _pkthdr;
  43. ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph);
  44. if (ih == NULL)
  45. return false;
  46. if ((info->bitmask & EBT_IP_TOS) &&
  47. NF_INVF(info, EBT_IP_TOS, info->tos != ih->tos))
  48. return false;
  49. if ((info->bitmask & EBT_IP_SOURCE) &&
  50. NF_INVF(info, EBT_IP_SOURCE,
  51. (ih->saddr & info->smsk) != info->saddr))
  52. return false;
  53. if ((info->bitmask & EBT_IP_DEST) &&
  54. NF_INVF(info, EBT_IP_DEST,
  55. (ih->daddr & info->dmsk) != info->daddr))
  56. return false;
  57. if (info->bitmask & EBT_IP_PROTO) {
  58. if (NF_INVF(info, EBT_IP_PROTO, info->protocol != ih->protocol))
  59. return false;
  60. if (!(info->bitmask & (EBT_IP_DPORT | EBT_IP_SPORT |
  61. EBT_IP_ICMP | EBT_IP_IGMP)))
  62. return true;
  63. if (ntohs(ih->frag_off) & IP_OFFSET)
  64. return false;
  65. /* min icmp/igmp headersize is 4, so sizeof(_pkthdr) is ok. */
  66. pptr = skb_header_pointer(skb, ih->ihl*4,
  67. sizeof(_pkthdr), &_pkthdr);
  68. if (pptr == NULL)
  69. return false;
  70. if (info->bitmask & EBT_IP_DPORT) {
  71. u32 dst = ntohs(pptr->tcpudphdr.dst);
  72. if (NF_INVF(info, EBT_IP_DPORT,
  73. dst < info->dport[0] ||
  74. dst > info->dport[1]))
  75. return false;
  76. }
  77. if (info->bitmask & EBT_IP_SPORT) {
  78. u32 src = ntohs(pptr->tcpudphdr.src);
  79. if (NF_INVF(info, EBT_IP_SPORT,
  80. src < info->sport[0] ||
  81. src > info->sport[1]))
  82. return false;
  83. }
  84. if ((info->bitmask & EBT_IP_ICMP) &&
  85. NF_INVF(info, EBT_IP_ICMP,
  86. pptr->icmphdr.type < info->icmp_type[0] ||
  87. pptr->icmphdr.type > info->icmp_type[1] ||
  88. pptr->icmphdr.code < info->icmp_code[0] ||
  89. pptr->icmphdr.code > info->icmp_code[1]))
  90. return false;
  91. if ((info->bitmask & EBT_IP_IGMP) &&
  92. NF_INVF(info, EBT_IP_IGMP,
  93. pptr->igmphdr.type < info->igmp_type[0] ||
  94. pptr->igmphdr.type > info->igmp_type[1]))
  95. return false;
  96. }
  97. return true;
  98. }
  99. static int ebt_ip_mt_check(const struct xt_mtchk_param *par)
  100. {
  101. const struct ebt_ip_info *info = par->matchinfo;
  102. const struct ebt_entry *e = par->entryinfo;
  103. if (e->ethproto != htons(ETH_P_IP) ||
  104. e->invflags & EBT_IPROTO)
  105. return -EINVAL;
  106. if (info->bitmask & ~EBT_IP_MASK || info->invflags & ~EBT_IP_MASK)
  107. return -EINVAL;
  108. if (info->bitmask & (EBT_IP_DPORT | EBT_IP_SPORT)) {
  109. if (info->invflags & EBT_IP_PROTO)
  110. return -EINVAL;
  111. if (info->protocol != IPPROTO_TCP &&
  112. info->protocol != IPPROTO_UDP &&
  113. info->protocol != IPPROTO_UDPLITE &&
  114. info->protocol != IPPROTO_SCTP &&
  115. info->protocol != IPPROTO_DCCP)
  116. return -EINVAL;
  117. }
  118. if (info->bitmask & EBT_IP_DPORT && info->dport[0] > info->dport[1])
  119. return -EINVAL;
  120. if (info->bitmask & EBT_IP_SPORT && info->sport[0] > info->sport[1])
  121. return -EINVAL;
  122. if (info->bitmask & EBT_IP_ICMP) {
  123. if ((info->invflags & EBT_IP_PROTO) ||
  124. info->protocol != IPPROTO_ICMP)
  125. return -EINVAL;
  126. if (info->icmp_type[0] > info->icmp_type[1] ||
  127. info->icmp_code[0] > info->icmp_code[1])
  128. return -EINVAL;
  129. }
  130. if (info->bitmask & EBT_IP_IGMP) {
  131. if ((info->invflags & EBT_IP_PROTO) ||
  132. info->protocol != IPPROTO_IGMP)
  133. return -EINVAL;
  134. if (info->igmp_type[0] > info->igmp_type[1])
  135. return -EINVAL;
  136. }
  137. return 0;
  138. }
  139. static struct xt_match ebt_ip_mt_reg __read_mostly = {
  140. .name = "ip",
  141. .revision = 0,
  142. .family = NFPROTO_BRIDGE,
  143. .match = ebt_ip_mt,
  144. .checkentry = ebt_ip_mt_check,
  145. .matchsize = sizeof(struct ebt_ip_info),
  146. .me = THIS_MODULE,
  147. };
  148. static int __init ebt_ip_init(void)
  149. {
  150. return xt_register_match(&ebt_ip_mt_reg);
  151. }
  152. static void __exit ebt_ip_fini(void)
  153. {
  154. xt_unregister_match(&ebt_ip_mt_reg);
  155. }
  156. module_init(ebt_ip_init);
  157. module_exit(ebt_ip_fini);
  158. MODULE_DESCRIPTION("Ebtables: IPv4 protocol packet match");
  159. MODULE_LICENSE("GPL");