ip_set_bitmap_ipmac.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424
  1. /* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
  2. * Patrick Schaaf <bof@bof.de>
  3. * Martin Josefsson <gandalf@wlug.westbo.se>
  4. * Copyright (C) 2003-2013 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License version 2 as
  8. * published by the Free Software Foundation.
  9. */
  10. /* Kernel module implementing an IP set type: the bitmap:ip,mac type */
  11. #include <linux/module.h>
  12. #include <linux/ip.h>
  13. #include <linux/etherdevice.h>
  14. #include <linux/skbuff.h>
  15. #include <linux/errno.h>
  16. #include <linux/if_ether.h>
  17. #include <linux/netlink.h>
  18. #include <linux/jiffies.h>
  19. #include <linux/timer.h>
  20. #include <net/netlink.h>
  21. #include <linux/netfilter/ipset/pfxlen.h>
  22. #include <linux/netfilter/ipset/ip_set.h>
  23. #include <linux/netfilter/ipset/ip_set_bitmap.h>
  24. #define IPSET_TYPE_REV_MIN 0
  25. /* 1 Counter support added */
  26. /* 2 Comment support added */
  27. #define IPSET_TYPE_REV_MAX 3 /* skbinfo support added */
  28. MODULE_LICENSE("GPL");
  29. MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
  30. IP_SET_MODULE_DESC("bitmap:ip,mac", IPSET_TYPE_REV_MIN, IPSET_TYPE_REV_MAX);
  31. MODULE_ALIAS("ip_set_bitmap:ip,mac");
  32. #define MTYPE bitmap_ipmac
  33. #define HOST_MASK 32
  34. #define IP_SET_BITMAP_STORED_TIMEOUT
  35. enum {
  36. MAC_UNSET, /* element is set, without MAC */
  37. MAC_FILLED, /* element is set with MAC */
  38. };
  39. /* Type structure */
  40. struct bitmap_ipmac {
  41. void *members; /* the set members */
  42. u32 first_ip; /* host byte order, included in range */
  43. u32 last_ip; /* host byte order, included in range */
  44. u32 elements; /* number of max elements in the set */
  45. size_t memsize; /* members size */
  46. struct timer_list gc; /* garbage collector */
  47. unsigned char extensions[0] /* MAC + data extensions */
  48. __aligned(__alignof__(u64));
  49. };
  50. /* ADT structure for generic function args */
  51. struct bitmap_ipmac_adt_elem {
  52. unsigned char ether[ETH_ALEN] __aligned(2);
  53. u16 id;
  54. u16 add_mac;
  55. };
  56. struct bitmap_ipmac_elem {
  57. unsigned char ether[ETH_ALEN];
  58. unsigned char filled;
  59. } __aligned(__alignof__(u64));
  60. static inline u32
  61. ip_to_id(const struct bitmap_ipmac *m, u32 ip)
  62. {
  63. return ip - m->first_ip;
  64. }
  65. #define get_elem(extensions, id, dsize) \
  66. (struct bitmap_ipmac_elem *)(extensions + (id) * (dsize))
  67. #define get_const_elem(extensions, id, dsize) \
  68. (const struct bitmap_ipmac_elem *)(extensions + (id) * (dsize))
  69. /* Common functions */
  70. static inline int
  71. bitmap_ipmac_do_test(const struct bitmap_ipmac_adt_elem *e,
  72. const struct bitmap_ipmac *map, size_t dsize)
  73. {
  74. const struct bitmap_ipmac_elem *elem;
  75. if (!test_bit(e->id, map->members))
  76. return 0;
  77. elem = get_const_elem(map->extensions, e->id, dsize);
  78. if (e->add_mac && elem->filled == MAC_FILLED)
  79. return ether_addr_equal(e->ether, elem->ether);
  80. /* Trigger kernel to fill out the ethernet address */
  81. return -EAGAIN;
  82. }
  83. static inline int
  84. bitmap_ipmac_gc_test(u16 id, const struct bitmap_ipmac *map, size_t dsize)
  85. {
  86. const struct bitmap_ipmac_elem *elem;
  87. if (!test_bit(id, map->members))
  88. return 0;
  89. elem = get_const_elem(map->extensions, id, dsize);
  90. /* Timer not started for the incomplete elements */
  91. return elem->filled == MAC_FILLED;
  92. }
  93. static inline int
  94. bitmap_ipmac_is_filled(const struct bitmap_ipmac_elem *elem)
  95. {
  96. return elem->filled == MAC_FILLED;
  97. }
  98. static inline int
  99. bitmap_ipmac_add_timeout(unsigned long *timeout,
  100. const struct bitmap_ipmac_adt_elem *e,
  101. const struct ip_set_ext *ext, struct ip_set *set,
  102. struct bitmap_ipmac *map, int mode)
  103. {
  104. u32 t = ext->timeout;
  105. if (mode == IPSET_ADD_START_STORED_TIMEOUT) {
  106. if (t == set->timeout)
  107. /* Timeout was not specified, get stored one */
  108. t = *timeout;
  109. ip_set_timeout_set(timeout, t);
  110. } else {
  111. /* If MAC is unset yet, we store plain timeout value
  112. * because the timer is not activated yet
  113. * and we can reuse it later when MAC is filled out,
  114. * possibly by the kernel
  115. */
  116. if (e->add_mac)
  117. ip_set_timeout_set(timeout, t);
  118. else
  119. *timeout = t;
  120. }
  121. return 0;
  122. }
  123. static inline int
  124. bitmap_ipmac_do_add(const struct bitmap_ipmac_adt_elem *e,
  125. struct bitmap_ipmac *map, u32 flags, size_t dsize)
  126. {
  127. struct bitmap_ipmac_elem *elem;
  128. elem = get_elem(map->extensions, e->id, dsize);
  129. if (test_bit(e->id, map->members)) {
  130. if (elem->filled == MAC_FILLED) {
  131. if (e->add_mac &&
  132. (flags & IPSET_FLAG_EXIST) &&
  133. !ether_addr_equal(e->ether, elem->ether)) {
  134. /* memcpy isn't atomic */
  135. clear_bit(e->id, map->members);
  136. smp_mb__after_atomic();
  137. ether_addr_copy(elem->ether, e->ether);
  138. }
  139. return IPSET_ADD_FAILED;
  140. } else if (!e->add_mac)
  141. /* Already added without ethernet address */
  142. return IPSET_ADD_FAILED;
  143. /* Fill the MAC address and trigger the timer activation */
  144. clear_bit(e->id, map->members);
  145. smp_mb__after_atomic();
  146. ether_addr_copy(elem->ether, e->ether);
  147. elem->filled = MAC_FILLED;
  148. return IPSET_ADD_START_STORED_TIMEOUT;
  149. } else if (e->add_mac) {
  150. /* We can store MAC too */
  151. ether_addr_copy(elem->ether, e->ether);
  152. elem->filled = MAC_FILLED;
  153. return 0;
  154. }
  155. elem->filled = MAC_UNSET;
  156. /* MAC is not stored yet, don't start timer */
  157. return IPSET_ADD_STORE_PLAIN_TIMEOUT;
  158. }
  159. static inline int
  160. bitmap_ipmac_do_del(const struct bitmap_ipmac_adt_elem *e,
  161. struct bitmap_ipmac *map)
  162. {
  163. return !test_and_clear_bit(e->id, map->members);
  164. }
  165. static inline int
  166. bitmap_ipmac_do_list(struct sk_buff *skb, const struct bitmap_ipmac *map,
  167. u32 id, size_t dsize)
  168. {
  169. const struct bitmap_ipmac_elem *elem =
  170. get_const_elem(map->extensions, id, dsize);
  171. return nla_put_ipaddr4(skb, IPSET_ATTR_IP,
  172. htonl(map->first_ip + id)) ||
  173. (elem->filled == MAC_FILLED &&
  174. nla_put(skb, IPSET_ATTR_ETHER, ETH_ALEN, elem->ether));
  175. }
  176. static inline int
  177. bitmap_ipmac_do_head(struct sk_buff *skb, const struct bitmap_ipmac *map)
  178. {
  179. return nla_put_ipaddr4(skb, IPSET_ATTR_IP, htonl(map->first_ip)) ||
  180. nla_put_ipaddr4(skb, IPSET_ATTR_IP_TO, htonl(map->last_ip));
  181. }
  182. static int
  183. bitmap_ipmac_kadt(struct ip_set *set, const struct sk_buff *skb,
  184. const struct xt_action_param *par,
  185. enum ipset_adt adt, struct ip_set_adt_opt *opt)
  186. {
  187. struct bitmap_ipmac *map = set->data;
  188. ipset_adtfn adtfn = set->variant->adt[adt];
  189. struct bitmap_ipmac_adt_elem e = { .id = 0, .add_mac = 1 };
  190. struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
  191. u32 ip;
  192. /* MAC can be src only */
  193. if (!(opt->flags & IPSET_DIM_TWO_SRC))
  194. return 0;
  195. ip = ntohl(ip4addr(skb, opt->flags & IPSET_DIM_ONE_SRC));
  196. if (ip < map->first_ip || ip > map->last_ip)
  197. return -IPSET_ERR_BITMAP_RANGE;
  198. /* Backward compatibility: we don't check the second flag */
  199. if (skb_mac_header(skb) < skb->head ||
  200. (skb_mac_header(skb) + ETH_HLEN) > skb->data)
  201. return -EINVAL;
  202. e.id = ip_to_id(map, ip);
  203. memcpy(e.ether, eth_hdr(skb)->h_source, ETH_ALEN);
  204. return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
  205. }
  206. static int
  207. bitmap_ipmac_uadt(struct ip_set *set, struct nlattr *tb[],
  208. enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
  209. {
  210. const struct bitmap_ipmac *map = set->data;
  211. ipset_adtfn adtfn = set->variant->adt[adt];
  212. struct bitmap_ipmac_adt_elem e = { .id = 0 };
  213. struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
  214. u32 ip = 0;
  215. int ret = 0;
  216. if (tb[IPSET_ATTR_LINENO])
  217. *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
  218. if (unlikely(!tb[IPSET_ATTR_IP]))
  219. return -IPSET_ERR_PROTOCOL;
  220. ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip);
  221. if (ret)
  222. return ret;
  223. ret = ip_set_get_extensions(set, tb, &ext);
  224. if (ret)
  225. return ret;
  226. if (ip < map->first_ip || ip > map->last_ip)
  227. return -IPSET_ERR_BITMAP_RANGE;
  228. e.id = ip_to_id(map, ip);
  229. if (tb[IPSET_ATTR_ETHER]) {
  230. memcpy(e.ether, nla_data(tb[IPSET_ATTR_ETHER]), ETH_ALEN);
  231. e.add_mac = 1;
  232. }
  233. ret = adtfn(set, &e, &ext, &ext, flags);
  234. return ip_set_eexist(ret, flags) ? 0 : ret;
  235. }
  236. static bool
  237. bitmap_ipmac_same_set(const struct ip_set *a, const struct ip_set *b)
  238. {
  239. const struct bitmap_ipmac *x = a->data;
  240. const struct bitmap_ipmac *y = b->data;
  241. return x->first_ip == y->first_ip &&
  242. x->last_ip == y->last_ip &&
  243. a->timeout == b->timeout &&
  244. a->extensions == b->extensions;
  245. }
  246. /* Plain variant */
  247. #include "ip_set_bitmap_gen.h"
  248. /* Create bitmap:ip,mac type of sets */
  249. static bool
  250. init_map_ipmac(struct ip_set *set, struct bitmap_ipmac *map,
  251. u32 first_ip, u32 last_ip, u32 elements)
  252. {
  253. map->members = ip_set_alloc(map->memsize);
  254. if (!map->members)
  255. return false;
  256. map->first_ip = first_ip;
  257. map->last_ip = last_ip;
  258. map->elements = elements;
  259. set->timeout = IPSET_NO_TIMEOUT;
  260. set->data = map;
  261. set->family = NFPROTO_IPV4;
  262. return true;
  263. }
  264. static int
  265. bitmap_ipmac_create(struct net *net, struct ip_set *set, struct nlattr *tb[],
  266. u32 flags)
  267. {
  268. u32 first_ip = 0, last_ip = 0;
  269. u64 elements;
  270. struct bitmap_ipmac *map;
  271. int ret;
  272. if (unlikely(!tb[IPSET_ATTR_IP] ||
  273. !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
  274. !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS)))
  275. return -IPSET_ERR_PROTOCOL;
  276. ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &first_ip);
  277. if (ret)
  278. return ret;
  279. if (tb[IPSET_ATTR_IP_TO]) {
  280. ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &last_ip);
  281. if (ret)
  282. return ret;
  283. if (first_ip > last_ip) {
  284. u32 tmp = first_ip;
  285. first_ip = last_ip;
  286. last_ip = tmp;
  287. }
  288. } else if (tb[IPSET_ATTR_CIDR]) {
  289. u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
  290. if (cidr >= HOST_MASK)
  291. return -IPSET_ERR_INVALID_CIDR;
  292. ip_set_mask_from_to(first_ip, last_ip, cidr);
  293. } else {
  294. return -IPSET_ERR_PROTOCOL;
  295. }
  296. elements = (u64)last_ip - first_ip + 1;
  297. if (elements > IPSET_BITMAP_MAX_RANGE + 1)
  298. return -IPSET_ERR_BITMAP_RANGE_SIZE;
  299. set->dsize = ip_set_elem_len(set, tb,
  300. sizeof(struct bitmap_ipmac_elem),
  301. __alignof__(struct bitmap_ipmac_elem));
  302. map = ip_set_alloc(sizeof(*map) + elements * set->dsize);
  303. if (!map)
  304. return -ENOMEM;
  305. map->memsize = bitmap_bytes(0, elements - 1);
  306. set->variant = &bitmap_ipmac;
  307. if (!init_map_ipmac(set, map, first_ip, last_ip, elements)) {
  308. kfree(map);
  309. return -ENOMEM;
  310. }
  311. if (tb[IPSET_ATTR_TIMEOUT]) {
  312. set->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
  313. bitmap_ipmac_gc_init(set, bitmap_ipmac_gc);
  314. }
  315. return 0;
  316. }
  317. static struct ip_set_type bitmap_ipmac_type = {
  318. .name = "bitmap:ip,mac",
  319. .protocol = IPSET_PROTOCOL,
  320. .features = IPSET_TYPE_IP | IPSET_TYPE_MAC,
  321. .dimension = IPSET_DIM_TWO,
  322. .family = NFPROTO_IPV4,
  323. .revision_min = IPSET_TYPE_REV_MIN,
  324. .revision_max = IPSET_TYPE_REV_MAX,
  325. .create = bitmap_ipmac_create,
  326. .create_policy = {
  327. [IPSET_ATTR_IP] = { .type = NLA_NESTED },
  328. [IPSET_ATTR_IP_TO] = { .type = NLA_NESTED },
  329. [IPSET_ATTR_CIDR] = { .type = NLA_U8 },
  330. [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
  331. [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
  332. },
  333. .adt_policy = {
  334. [IPSET_ATTR_IP] = { .type = NLA_NESTED },
  335. [IPSET_ATTR_ETHER] = { .type = NLA_BINARY,
  336. .len = ETH_ALEN },
  337. [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
  338. [IPSET_ATTR_LINENO] = { .type = NLA_U32 },
  339. [IPSET_ATTR_BYTES] = { .type = NLA_U64 },
  340. [IPSET_ATTR_PACKETS] = { .type = NLA_U64 },
  341. [IPSET_ATTR_COMMENT] = { .type = NLA_NUL_STRING,
  342. .len = IPSET_MAX_COMMENT_SIZE },
  343. [IPSET_ATTR_SKBMARK] = { .type = NLA_U64 },
  344. [IPSET_ATTR_SKBPRIO] = { .type = NLA_U32 },
  345. [IPSET_ATTR_SKBQUEUE] = { .type = NLA_U16 },
  346. },
  347. .me = THIS_MODULE,
  348. };
  349. static int __init
  350. bitmap_ipmac_init(void)
  351. {
  352. return ip_set_type_register(&bitmap_ipmac_type);
  353. }
  354. static void __exit
  355. bitmap_ipmac_fini(void)
  356. {
  357. rcu_barrier();
  358. ip_set_type_unregister(&bitmap_ipmac_type);
  359. }
  360. module_init(bitmap_ipmac_init);
  361. module_exit(bitmap_ipmac_fini);