xt_addrtype.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. /*
  2. * iptables module to match inet_addr_type() of an ip.
  3. *
  4. * Copyright (c) 2004 Patrick McHardy <kaber@trash.net>
  5. * (C) 2007 Laszlo Attila Toth <panther@balabit.hu>
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License version 2 as
  9. * published by the Free Software Foundation.
  10. */
  11. #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  12. #include <linux/kernel.h>
  13. #include <linux/module.h>
  14. #include <linux/skbuff.h>
  15. #include <linux/netdevice.h>
  16. #include <linux/ip.h>
  17. #include <net/route.h>
  18. #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
  19. #include <net/ipv6.h>
  20. #include <net/ip6_route.h>
  21. #include <net/ip6_fib.h>
  22. #endif
  23. #include <linux/netfilter_ipv6.h>
  24. #include <linux/netfilter/xt_addrtype.h>
  25. #include <linux/netfilter/x_tables.h>
  26. MODULE_LICENSE("GPL");
  27. MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
  28. MODULE_DESCRIPTION("Xtables: address type match");
  29. MODULE_ALIAS("ipt_addrtype");
  30. MODULE_ALIAS("ip6t_addrtype");
  31. #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
  32. static u32 match_lookup_rt6(struct net *net, const struct net_device *dev,
  33. const struct in6_addr *addr, u16 mask)
  34. {
  35. const struct nf_afinfo *afinfo;
  36. struct flowi6 flow;
  37. struct rt6_info *rt;
  38. u32 ret = 0;
  39. int route_err;
  40. memset(&flow, 0, sizeof(flow));
  41. flow.daddr = *addr;
  42. if (dev)
  43. flow.flowi6_oif = dev->ifindex;
  44. rcu_read_lock();
  45. afinfo = nf_get_afinfo(NFPROTO_IPV6);
  46. if (afinfo != NULL) {
  47. const struct nf_ipv6_ops *v6ops;
  48. if (dev && (mask & XT_ADDRTYPE_LOCAL)) {
  49. v6ops = nf_get_ipv6_ops();
  50. if (v6ops && v6ops->chk_addr(net, addr, dev, true))
  51. ret = XT_ADDRTYPE_LOCAL;
  52. }
  53. route_err = afinfo->route(net, (struct dst_entry **)&rt,
  54. flowi6_to_flowi(&flow), false);
  55. } else {
  56. route_err = 1;
  57. }
  58. rcu_read_unlock();
  59. if (route_err)
  60. return XT_ADDRTYPE_UNREACHABLE;
  61. if (rt->rt6i_flags & RTF_REJECT)
  62. ret = XT_ADDRTYPE_UNREACHABLE;
  63. if (dev == NULL && rt->rt6i_flags & RTF_LOCAL)
  64. ret |= XT_ADDRTYPE_LOCAL;
  65. if (ipv6_anycast_destination((struct dst_entry *)rt, addr))
  66. ret |= XT_ADDRTYPE_ANYCAST;
  67. dst_release(&rt->dst);
  68. return ret;
  69. }
  70. static bool match_type6(struct net *net, const struct net_device *dev,
  71. const struct in6_addr *addr, u16 mask)
  72. {
  73. int addr_type = ipv6_addr_type(addr);
  74. if ((mask & XT_ADDRTYPE_MULTICAST) &&
  75. !(addr_type & IPV6_ADDR_MULTICAST))
  76. return false;
  77. if ((mask & XT_ADDRTYPE_UNICAST) && !(addr_type & IPV6_ADDR_UNICAST))
  78. return false;
  79. if ((mask & XT_ADDRTYPE_UNSPEC) && addr_type != IPV6_ADDR_ANY)
  80. return false;
  81. if ((XT_ADDRTYPE_LOCAL | XT_ADDRTYPE_ANYCAST |
  82. XT_ADDRTYPE_UNREACHABLE) & mask)
  83. return !!(mask & match_lookup_rt6(net, dev, addr, mask));
  84. return true;
  85. }
  86. static bool
  87. addrtype_mt6(struct net *net, const struct net_device *dev,
  88. const struct sk_buff *skb, const struct xt_addrtype_info_v1 *info)
  89. {
  90. const struct ipv6hdr *iph = ipv6_hdr(skb);
  91. bool ret = true;
  92. if (info->source)
  93. ret &= match_type6(net, dev, &iph->saddr, info->source) ^
  94. (info->flags & XT_ADDRTYPE_INVERT_SOURCE);
  95. if (ret && info->dest)
  96. ret &= match_type6(net, dev, &iph->daddr, info->dest) ^
  97. !!(info->flags & XT_ADDRTYPE_INVERT_DEST);
  98. return ret;
  99. }
  100. #endif
  101. static inline bool match_type(struct net *net, const struct net_device *dev,
  102. __be32 addr, u_int16_t mask)
  103. {
  104. return !!(mask & (1 << inet_dev_addr_type(net, dev, addr)));
  105. }
  106. static bool
  107. addrtype_mt_v0(const struct sk_buff *skb, struct xt_action_param *par)
  108. {
  109. struct net *net = par->net;
  110. const struct xt_addrtype_info *info = par->matchinfo;
  111. const struct iphdr *iph = ip_hdr(skb);
  112. bool ret = true;
  113. if (info->source)
  114. ret &= match_type(net, NULL, iph->saddr, info->source) ^
  115. info->invert_source;
  116. if (info->dest)
  117. ret &= match_type(net, NULL, iph->daddr, info->dest) ^
  118. info->invert_dest;
  119. return ret;
  120. }
  121. static bool
  122. addrtype_mt_v1(const struct sk_buff *skb, struct xt_action_param *par)
  123. {
  124. struct net *net = par->net;
  125. const struct xt_addrtype_info_v1 *info = par->matchinfo;
  126. const struct iphdr *iph;
  127. const struct net_device *dev = NULL;
  128. bool ret = true;
  129. if (info->flags & XT_ADDRTYPE_LIMIT_IFACE_IN)
  130. dev = par->in;
  131. else if (info->flags & XT_ADDRTYPE_LIMIT_IFACE_OUT)
  132. dev = par->out;
  133. #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
  134. if (par->family == NFPROTO_IPV6)
  135. return addrtype_mt6(net, dev, skb, info);
  136. #endif
  137. iph = ip_hdr(skb);
  138. if (info->source)
  139. ret &= match_type(net, dev, iph->saddr, info->source) ^
  140. (info->flags & XT_ADDRTYPE_INVERT_SOURCE);
  141. if (ret && info->dest)
  142. ret &= match_type(net, dev, iph->daddr, info->dest) ^
  143. !!(info->flags & XT_ADDRTYPE_INVERT_DEST);
  144. return ret;
  145. }
  146. static int addrtype_mt_checkentry_v1(const struct xt_mtchk_param *par)
  147. {
  148. struct xt_addrtype_info_v1 *info = par->matchinfo;
  149. if (info->flags & XT_ADDRTYPE_LIMIT_IFACE_IN &&
  150. info->flags & XT_ADDRTYPE_LIMIT_IFACE_OUT) {
  151. pr_info("both incoming and outgoing "
  152. "interface limitation cannot be selected\n");
  153. return -EINVAL;
  154. }
  155. if (par->hook_mask & ((1 << NF_INET_PRE_ROUTING) |
  156. (1 << NF_INET_LOCAL_IN)) &&
  157. info->flags & XT_ADDRTYPE_LIMIT_IFACE_OUT) {
  158. pr_info("output interface limitation "
  159. "not valid in PREROUTING and INPUT\n");
  160. return -EINVAL;
  161. }
  162. if (par->hook_mask & ((1 << NF_INET_POST_ROUTING) |
  163. (1 << NF_INET_LOCAL_OUT)) &&
  164. info->flags & XT_ADDRTYPE_LIMIT_IFACE_IN) {
  165. pr_info("input interface limitation "
  166. "not valid in POSTROUTING and OUTPUT\n");
  167. return -EINVAL;
  168. }
  169. #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
  170. if (par->family == NFPROTO_IPV6) {
  171. if ((info->source | info->dest) & XT_ADDRTYPE_BLACKHOLE) {
  172. pr_err("ipv6 BLACKHOLE matching not supported\n");
  173. return -EINVAL;
  174. }
  175. if ((info->source | info->dest) >= XT_ADDRTYPE_PROHIBIT) {
  176. pr_err("ipv6 PROHIBIT (THROW, NAT ..) matching not supported\n");
  177. return -EINVAL;
  178. }
  179. if ((info->source | info->dest) & XT_ADDRTYPE_BROADCAST) {
  180. pr_err("ipv6 does not support BROADCAST matching\n");
  181. return -EINVAL;
  182. }
  183. }
  184. #endif
  185. return 0;
  186. }
  187. static struct xt_match addrtype_mt_reg[] __read_mostly = {
  188. {
  189. .name = "addrtype",
  190. .family = NFPROTO_IPV4,
  191. .match = addrtype_mt_v0,
  192. .matchsize = sizeof(struct xt_addrtype_info),
  193. .me = THIS_MODULE
  194. },
  195. {
  196. .name = "addrtype",
  197. .family = NFPROTO_UNSPEC,
  198. .revision = 1,
  199. .match = addrtype_mt_v1,
  200. .checkentry = addrtype_mt_checkentry_v1,
  201. .matchsize = sizeof(struct xt_addrtype_info_v1),
  202. .me = THIS_MODULE
  203. }
  204. };
  205. static int __init addrtype_mt_init(void)
  206. {
  207. return xt_register_matches(addrtype_mt_reg,
  208. ARRAY_SIZE(addrtype_mt_reg));
  209. }
  210. static void __exit addrtype_mt_exit(void)
  211. {
  212. xt_unregister_matches(addrtype_mt_reg, ARRAY_SIZE(addrtype_mt_reg));
  213. }
  214. module_init(addrtype_mt_init);
  215. module_exit(addrtype_mt_exit);