ip_set_hash_mac.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /* Copyright (C) 2014 Jozsef Kadlecsik <kadlec@netfilter.org> */
  3. /* Kernel module implementing an IP set type: the hash:mac type */
  4. #include <linux/jhash.h>
  5. #include <linux/module.h>
  6. #include <linux/etherdevice.h>
  7. #include <linux/skbuff.h>
  8. #include <linux/errno.h>
  9. #include <linux/if_ether.h>
  10. #include <net/netlink.h>
  11. #include <linux/netfilter.h>
  12. #include <linux/netfilter/ipset/ip_set.h>
  13. #include <linux/netfilter/ipset/ip_set_hash.h>
  14. #define IPSET_TYPE_REV_MIN 0
  15. #define IPSET_TYPE_REV_MAX 0
  16. MODULE_LICENSE("GPL");
  17. MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@netfilter.org>");
  18. IP_SET_MODULE_DESC("hash:mac", IPSET_TYPE_REV_MIN, IPSET_TYPE_REV_MAX);
  19. MODULE_ALIAS("ip_set_hash:mac");
  20. /* Type specific function prefix */
  21. #define HTYPE hash_mac
  22. /* Member elements */
  23. struct hash_mac4_elem {
  24. /* Zero valued IP addresses cannot be stored */
  25. union {
  26. unsigned char ether[ETH_ALEN];
  27. __be32 foo[2];
  28. };
  29. };
  30. /* Common functions */
  31. static bool
  32. hash_mac4_data_equal(const struct hash_mac4_elem *e1,
  33. const struct hash_mac4_elem *e2,
  34. u32 *multi)
  35. {
  36. return ether_addr_equal(e1->ether, e2->ether);
  37. }
  38. static bool
  39. hash_mac4_data_list(struct sk_buff *skb, const struct hash_mac4_elem *e)
  40. {
  41. if (nla_put(skb, IPSET_ATTR_ETHER, ETH_ALEN, e->ether))
  42. goto nla_put_failure;
  43. return false;
  44. nla_put_failure:
  45. return true;
  46. }
  47. static void
  48. hash_mac4_data_next(struct hash_mac4_elem *next,
  49. const struct hash_mac4_elem *e)
  50. {
  51. }
  52. #define MTYPE hash_mac4
  53. #define HOST_MASK 32
  54. #define IP_SET_EMIT_CREATE
  55. #define IP_SET_PROTO_UNDEF
  56. #include "ip_set_hash_gen.h"
  57. static int
  58. hash_mac4_kadt(struct ip_set *set, const struct sk_buff *skb,
  59. const struct xt_action_param *par,
  60. enum ipset_adt adt, struct ip_set_adt_opt *opt)
  61. {
  62. ipset_adtfn adtfn = set->variant->adt[adt];
  63. struct hash_mac4_elem e = { { .foo[0] = 0, .foo[1] = 0 } };
  64. struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
  65. if (skb_mac_header(skb) < skb->head ||
  66. (skb_mac_header(skb) + ETH_HLEN) > skb->data)
  67. return -EINVAL;
  68. if (opt->flags & IPSET_DIM_ONE_SRC)
  69. ether_addr_copy(e.ether, eth_hdr(skb)->h_source);
  70. else
  71. ether_addr_copy(e.ether, eth_hdr(skb)->h_dest);
  72. if (is_zero_ether_addr(e.ether))
  73. return -EINVAL;
  74. return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
  75. }
  76. static int
  77. hash_mac4_uadt(struct ip_set *set, struct nlattr *tb[],
  78. enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
  79. {
  80. ipset_adtfn adtfn = set->variant->adt[adt];
  81. struct hash_mac4_elem e = { { .foo[0] = 0, .foo[1] = 0 } };
  82. struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
  83. int ret;
  84. if (tb[IPSET_ATTR_LINENO])
  85. *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
  86. if (unlikely(!tb[IPSET_ATTR_ETHER] ||
  87. nla_len(tb[IPSET_ATTR_ETHER]) != ETH_ALEN))
  88. return -IPSET_ERR_PROTOCOL;
  89. ret = ip_set_get_extensions(set, tb, &ext);
  90. if (ret)
  91. return ret;
  92. ether_addr_copy(e.ether, nla_data(tb[IPSET_ATTR_ETHER]));
  93. if (is_zero_ether_addr(e.ether))
  94. return -IPSET_ERR_HASH_ELEM;
  95. return adtfn(set, &e, &ext, &ext, flags);
  96. }
  97. static struct ip_set_type hash_mac_type __read_mostly = {
  98. .name = "hash:mac",
  99. .protocol = IPSET_PROTOCOL,
  100. .features = IPSET_TYPE_MAC,
  101. .dimension = IPSET_DIM_ONE,
  102. .family = NFPROTO_UNSPEC,
  103. .revision_min = IPSET_TYPE_REV_MIN,
  104. .revision_max = IPSET_TYPE_REV_MAX,
  105. .create = hash_mac_create,
  106. .create_policy = {
  107. [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
  108. [IPSET_ATTR_MAXELEM] = { .type = NLA_U32 },
  109. [IPSET_ATTR_PROBES] = { .type = NLA_U8 },
  110. [IPSET_ATTR_RESIZE] = { .type = NLA_U8 },
  111. [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
  112. [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
  113. },
  114. .adt_policy = {
  115. [IPSET_ATTR_ETHER] = { .type = NLA_BINARY,
  116. .len = ETH_ALEN },
  117. [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
  118. [IPSET_ATTR_LINENO] = { .type = NLA_U32 },
  119. [IPSET_ATTR_BYTES] = { .type = NLA_U64 },
  120. [IPSET_ATTR_PACKETS] = { .type = NLA_U64 },
  121. [IPSET_ATTR_COMMENT] = { .type = NLA_NUL_STRING,
  122. .len = IPSET_MAX_COMMENT_SIZE },
  123. [IPSET_ATTR_SKBMARK] = { .type = NLA_U64 },
  124. [IPSET_ATTR_SKBPRIO] = { .type = NLA_U32 },
  125. [IPSET_ATTR_SKBQUEUE] = { .type = NLA_U16 },
  126. },
  127. .me = THIS_MODULE,
  128. };
  129. static int __init
  130. hash_mac_init(void)
  131. {
  132. return ip_set_type_register(&hash_mac_type);
  133. }
  134. static void __exit
  135. hash_mac_fini(void)
  136. {
  137. rcu_barrier();
  138. ip_set_type_unregister(&hash_mac_type);
  139. }
  140. module_init(hash_mac_init);
  141. module_exit(hash_mac_fini);