ip_set_hash_netnet.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508
  1. /* Copyright (C) 2003-2013 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
  2. * Copyright (C) 2013 Oliver Smith <oliver@8.c.9.b.0.7.4.0.1.0.0.2.ip6.arpa>
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License version 2 as
  6. * published by the Free Software Foundation.
  7. */
  8. /* Kernel module implementing an IP set type: the hash:net type */
  9. #include <linux/jhash.h>
  10. #include <linux/module.h>
  11. #include <linux/ip.h>
  12. #include <linux/skbuff.h>
  13. #include <linux/errno.h>
  14. #include <linux/random.h>
  15. #include <net/ip.h>
  16. #include <net/ipv6.h>
  17. #include <net/netlink.h>
  18. #include <linux/netfilter.h>
  19. #include <linux/netfilter/ipset/pfxlen.h>
  20. #include <linux/netfilter/ipset/ip_set.h>
  21. #include <linux/netfilter/ipset/ip_set_hash.h>
  22. #define IPSET_TYPE_REV_MIN 0
  23. /* 1 Forceadd support added */
  24. #define IPSET_TYPE_REV_MAX 2 /* skbinfo support added */
  25. MODULE_LICENSE("GPL");
  26. MODULE_AUTHOR("Oliver Smith <oliver@8.c.9.b.0.7.4.0.1.0.0.2.ip6.arpa>");
  27. IP_SET_MODULE_DESC("hash:net,net", IPSET_TYPE_REV_MIN, IPSET_TYPE_REV_MAX);
  28. MODULE_ALIAS("ip_set_hash:net,net");
  29. /* Type specific function prefix */
  30. #define HTYPE hash_netnet
  31. #define IP_SET_HASH_WITH_NETS
  32. #define IPSET_NET_COUNT 2
  33. /* IPv4 variants */
  34. /* Member elements */
  35. struct hash_netnet4_elem {
  36. union {
  37. __be32 ip[2];
  38. __be64 ipcmp;
  39. };
  40. u8 nomatch;
  41. u8 padding;
  42. union {
  43. u8 cidr[2];
  44. u16 ccmp;
  45. };
  46. };
  47. /* Common functions */
  48. static inline bool
  49. hash_netnet4_data_equal(const struct hash_netnet4_elem *ip1,
  50. const struct hash_netnet4_elem *ip2,
  51. u32 *multi)
  52. {
  53. return ip1->ipcmp == ip2->ipcmp &&
  54. ip1->ccmp == ip2->ccmp;
  55. }
  56. static inline int
  57. hash_netnet4_do_data_match(const struct hash_netnet4_elem *elem)
  58. {
  59. return elem->nomatch ? -ENOTEMPTY : 1;
  60. }
  61. static inline void
  62. hash_netnet4_data_set_flags(struct hash_netnet4_elem *elem, u32 flags)
  63. {
  64. elem->nomatch = (flags >> 16) & IPSET_FLAG_NOMATCH;
  65. }
  66. static inline void
  67. hash_netnet4_data_reset_flags(struct hash_netnet4_elem *elem, u8 *flags)
  68. {
  69. swap(*flags, elem->nomatch);
  70. }
  71. static inline void
  72. hash_netnet4_data_reset_elem(struct hash_netnet4_elem *elem,
  73. struct hash_netnet4_elem *orig)
  74. {
  75. elem->ip[1] = orig->ip[1];
  76. }
  77. static inline void
  78. hash_netnet4_data_netmask(struct hash_netnet4_elem *elem, u8 cidr, bool inner)
  79. {
  80. if (inner) {
  81. elem->ip[1] &= ip_set_netmask(cidr);
  82. elem->cidr[1] = cidr;
  83. } else {
  84. elem->ip[0] &= ip_set_netmask(cidr);
  85. elem->cidr[0] = cidr;
  86. }
  87. }
  88. static bool
  89. hash_netnet4_data_list(struct sk_buff *skb,
  90. const struct hash_netnet4_elem *data)
  91. {
  92. u32 flags = data->nomatch ? IPSET_FLAG_NOMATCH : 0;
  93. if (nla_put_ipaddr4(skb, IPSET_ATTR_IP, data->ip[0]) ||
  94. nla_put_ipaddr4(skb, IPSET_ATTR_IP2, data->ip[1]) ||
  95. nla_put_u8(skb, IPSET_ATTR_CIDR, data->cidr[0]) ||
  96. nla_put_u8(skb, IPSET_ATTR_CIDR2, data->cidr[1]) ||
  97. (flags &&
  98. nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags))))
  99. goto nla_put_failure;
  100. return false;
  101. nla_put_failure:
  102. return true;
  103. }
  104. static inline void
  105. hash_netnet4_data_next(struct hash_netnet4_elem *next,
  106. const struct hash_netnet4_elem *d)
  107. {
  108. next->ipcmp = d->ipcmp;
  109. }
  110. #define MTYPE hash_netnet4
  111. #define HOST_MASK 32
  112. #include "ip_set_hash_gen.h"
  113. static void
  114. hash_netnet4_init(struct hash_netnet4_elem *e)
  115. {
  116. e->cidr[0] = HOST_MASK;
  117. e->cidr[1] = HOST_MASK;
  118. }
  119. static int
  120. hash_netnet4_kadt(struct ip_set *set, const struct sk_buff *skb,
  121. const struct xt_action_param *par,
  122. enum ipset_adt adt, struct ip_set_adt_opt *opt)
  123. {
  124. const struct hash_netnet *h = set->data;
  125. ipset_adtfn adtfn = set->variant->adt[adt];
  126. struct hash_netnet4_elem e = { };
  127. struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
  128. e.cidr[0] = INIT_CIDR(h->nets[0].cidr[0], HOST_MASK);
  129. e.cidr[1] = INIT_CIDR(h->nets[0].cidr[1], HOST_MASK);
  130. if (adt == IPSET_TEST)
  131. e.ccmp = (HOST_MASK << (sizeof(e.cidr[0]) * 8)) | HOST_MASK;
  132. ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip[0]);
  133. ip4addrptr(skb, opt->flags & IPSET_DIM_TWO_SRC, &e.ip[1]);
  134. e.ip[0] &= ip_set_netmask(e.cidr[0]);
  135. e.ip[1] &= ip_set_netmask(e.cidr[1]);
  136. return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
  137. }
  138. static int
  139. hash_netnet4_uadt(struct ip_set *set, struct nlattr *tb[],
  140. enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
  141. {
  142. const struct hash_netnet *h = set->data;
  143. ipset_adtfn adtfn = set->variant->adt[adt];
  144. struct hash_netnet4_elem e = { };
  145. struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
  146. u32 ip = 0, ip_to = 0, last;
  147. u32 ip2 = 0, ip2_from = 0, ip2_to = 0, last2;
  148. int ret;
  149. if (tb[IPSET_ATTR_LINENO])
  150. *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
  151. hash_netnet4_init(&e);
  152. if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] ||
  153. !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS)))
  154. return -IPSET_ERR_PROTOCOL;
  155. ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip);
  156. if (ret)
  157. return ret;
  158. ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP2], &ip2_from);
  159. if (ret)
  160. return ret;
  161. ret = ip_set_get_extensions(set, tb, &ext);
  162. if (ret)
  163. return ret;
  164. if (tb[IPSET_ATTR_CIDR]) {
  165. e.cidr[0] = nla_get_u8(tb[IPSET_ATTR_CIDR]);
  166. if (!e.cidr[0] || e.cidr[0] > HOST_MASK)
  167. return -IPSET_ERR_INVALID_CIDR;
  168. }
  169. if (tb[IPSET_ATTR_CIDR2]) {
  170. e.cidr[1] = nla_get_u8(tb[IPSET_ATTR_CIDR2]);
  171. if (!e.cidr[1] || e.cidr[1] > HOST_MASK)
  172. return -IPSET_ERR_INVALID_CIDR;
  173. }
  174. if (tb[IPSET_ATTR_CADT_FLAGS]) {
  175. u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
  176. if (cadt_flags & IPSET_FLAG_NOMATCH)
  177. flags |= (IPSET_FLAG_NOMATCH << 16);
  178. }
  179. if (adt == IPSET_TEST || !(tb[IPSET_ATTR_IP_TO] ||
  180. tb[IPSET_ATTR_IP2_TO])) {
  181. e.ip[0] = htonl(ip & ip_set_hostmask(e.cidr[0]));
  182. e.ip[1] = htonl(ip2_from & ip_set_hostmask(e.cidr[1]));
  183. ret = adtfn(set, &e, &ext, &ext, flags);
  184. return ip_set_enomatch(ret, flags, adt, set) ? -ret :
  185. ip_set_eexist(ret, flags) ? 0 : ret;
  186. }
  187. ip_to = ip;
  188. if (tb[IPSET_ATTR_IP_TO]) {
  189. ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
  190. if (ret)
  191. return ret;
  192. if (ip_to < ip)
  193. swap(ip, ip_to);
  194. if (unlikely(ip + UINT_MAX == ip_to))
  195. return -IPSET_ERR_HASH_RANGE;
  196. } else {
  197. ip_set_mask_from_to(ip, ip_to, e.cidr[0]);
  198. }
  199. ip2_to = ip2_from;
  200. if (tb[IPSET_ATTR_IP2_TO]) {
  201. ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP2_TO], &ip2_to);
  202. if (ret)
  203. return ret;
  204. if (ip2_to < ip2_from)
  205. swap(ip2_from, ip2_to);
  206. if (unlikely(ip2_from + UINT_MAX == ip2_to))
  207. return -IPSET_ERR_HASH_RANGE;
  208. } else {
  209. ip_set_mask_from_to(ip2_from, ip2_to, e.cidr[1]);
  210. }
  211. if (retried)
  212. ip = ntohl(h->next.ip[0]);
  213. while (!after(ip, ip_to)) {
  214. e.ip[0] = htonl(ip);
  215. last = ip_set_range_to_cidr(ip, ip_to, &e.cidr[0]);
  216. ip2 = (retried &&
  217. ip == ntohl(h->next.ip[0])) ? ntohl(h->next.ip[1])
  218. : ip2_from;
  219. while (!after(ip2, ip2_to)) {
  220. e.ip[1] = htonl(ip2);
  221. last2 = ip_set_range_to_cidr(ip2, ip2_to, &e.cidr[1]);
  222. ret = adtfn(set, &e, &ext, &ext, flags);
  223. if (ret && !ip_set_eexist(ret, flags))
  224. return ret;
  225. ret = 0;
  226. ip2 = last2 + 1;
  227. }
  228. ip = last + 1;
  229. }
  230. return ret;
  231. }
  232. /* IPv6 variants */
  233. struct hash_netnet6_elem {
  234. union nf_inet_addr ip[2];
  235. u8 nomatch;
  236. u8 padding;
  237. union {
  238. u8 cidr[2];
  239. u16 ccmp;
  240. };
  241. };
  242. /* Common functions */
  243. static inline bool
  244. hash_netnet6_data_equal(const struct hash_netnet6_elem *ip1,
  245. const struct hash_netnet6_elem *ip2,
  246. u32 *multi)
  247. {
  248. return ipv6_addr_equal(&ip1->ip[0].in6, &ip2->ip[0].in6) &&
  249. ipv6_addr_equal(&ip1->ip[1].in6, &ip2->ip[1].in6) &&
  250. ip1->ccmp == ip2->ccmp;
  251. }
  252. static inline int
  253. hash_netnet6_do_data_match(const struct hash_netnet6_elem *elem)
  254. {
  255. return elem->nomatch ? -ENOTEMPTY : 1;
  256. }
  257. static inline void
  258. hash_netnet6_data_set_flags(struct hash_netnet6_elem *elem, u32 flags)
  259. {
  260. elem->nomatch = (flags >> 16) & IPSET_FLAG_NOMATCH;
  261. }
  262. static inline void
  263. hash_netnet6_data_reset_flags(struct hash_netnet6_elem *elem, u8 *flags)
  264. {
  265. swap(*flags, elem->nomatch);
  266. }
  267. static inline void
  268. hash_netnet6_data_reset_elem(struct hash_netnet6_elem *elem,
  269. struct hash_netnet6_elem *orig)
  270. {
  271. elem->ip[1] = orig->ip[1];
  272. }
  273. static inline void
  274. hash_netnet6_data_netmask(struct hash_netnet6_elem *elem, u8 cidr, bool inner)
  275. {
  276. if (inner) {
  277. ip6_netmask(&elem->ip[1], cidr);
  278. elem->cidr[1] = cidr;
  279. } else {
  280. ip6_netmask(&elem->ip[0], cidr);
  281. elem->cidr[0] = cidr;
  282. }
  283. }
  284. static bool
  285. hash_netnet6_data_list(struct sk_buff *skb,
  286. const struct hash_netnet6_elem *data)
  287. {
  288. u32 flags = data->nomatch ? IPSET_FLAG_NOMATCH : 0;
  289. if (nla_put_ipaddr6(skb, IPSET_ATTR_IP, &data->ip[0].in6) ||
  290. nla_put_ipaddr6(skb, IPSET_ATTR_IP2, &data->ip[1].in6) ||
  291. nla_put_u8(skb, IPSET_ATTR_CIDR, data->cidr[0]) ||
  292. nla_put_u8(skb, IPSET_ATTR_CIDR2, data->cidr[1]) ||
  293. (flags &&
  294. nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags))))
  295. goto nla_put_failure;
  296. return false;
  297. nla_put_failure:
  298. return true;
  299. }
  300. static inline void
  301. hash_netnet6_data_next(struct hash_netnet4_elem *next,
  302. const struct hash_netnet6_elem *d)
  303. {
  304. }
  305. #undef MTYPE
  306. #undef HOST_MASK
  307. #define MTYPE hash_netnet6
  308. #define HOST_MASK 128
  309. #define IP_SET_EMIT_CREATE
  310. #include "ip_set_hash_gen.h"
  311. static void
  312. hash_netnet6_init(struct hash_netnet6_elem *e)
  313. {
  314. e->cidr[0] = HOST_MASK;
  315. e->cidr[1] = HOST_MASK;
  316. }
  317. static int
  318. hash_netnet6_kadt(struct ip_set *set, const struct sk_buff *skb,
  319. const struct xt_action_param *par,
  320. enum ipset_adt adt, struct ip_set_adt_opt *opt)
  321. {
  322. const struct hash_netnet *h = set->data;
  323. ipset_adtfn adtfn = set->variant->adt[adt];
  324. struct hash_netnet6_elem e = { };
  325. struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
  326. e.cidr[0] = INIT_CIDR(h->nets[0].cidr[0], HOST_MASK);
  327. e.cidr[1] = INIT_CIDR(h->nets[0].cidr[1], HOST_MASK);
  328. if (adt == IPSET_TEST)
  329. e.ccmp = (HOST_MASK << (sizeof(u8) * 8)) | HOST_MASK;
  330. ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip[0].in6);
  331. ip6addrptr(skb, opt->flags & IPSET_DIM_TWO_SRC, &e.ip[1].in6);
  332. ip6_netmask(&e.ip[0], e.cidr[0]);
  333. ip6_netmask(&e.ip[1], e.cidr[1]);
  334. return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
  335. }
  336. static int
  337. hash_netnet6_uadt(struct ip_set *set, struct nlattr *tb[],
  338. enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
  339. {
  340. ipset_adtfn adtfn = set->variant->adt[adt];
  341. struct hash_netnet6_elem e = { };
  342. struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
  343. int ret;
  344. if (tb[IPSET_ATTR_LINENO])
  345. *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
  346. hash_netnet6_init(&e);
  347. if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] ||
  348. !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS)))
  349. return -IPSET_ERR_PROTOCOL;
  350. if (unlikely(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_IP2_TO]))
  351. return -IPSET_ERR_HASH_RANGE_UNSUPPORTED;
  352. ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &e.ip[0]);
  353. if (ret)
  354. return ret;
  355. ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP2], &e.ip[1]);
  356. if (ret)
  357. return ret;
  358. ret = ip_set_get_extensions(set, tb, &ext);
  359. if (ret)
  360. return ret;
  361. if (tb[IPSET_ATTR_CIDR]) {
  362. e.cidr[0] = nla_get_u8(tb[IPSET_ATTR_CIDR]);
  363. if (!e.cidr[0] || e.cidr[0] > HOST_MASK)
  364. return -IPSET_ERR_INVALID_CIDR;
  365. }
  366. if (tb[IPSET_ATTR_CIDR2]) {
  367. e.cidr[1] = nla_get_u8(tb[IPSET_ATTR_CIDR2]);
  368. if (!e.cidr[1] || e.cidr[1] > HOST_MASK)
  369. return -IPSET_ERR_INVALID_CIDR;
  370. }
  371. ip6_netmask(&e.ip[0], e.cidr[0]);
  372. ip6_netmask(&e.ip[1], e.cidr[1]);
  373. if (tb[IPSET_ATTR_CADT_FLAGS]) {
  374. u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
  375. if (cadt_flags & IPSET_FLAG_NOMATCH)
  376. flags |= (IPSET_FLAG_NOMATCH << 16);
  377. }
  378. ret = adtfn(set, &e, &ext, &ext, flags);
  379. return ip_set_enomatch(ret, flags, adt, set) ? -ret :
  380. ip_set_eexist(ret, flags) ? 0 : ret;
  381. }
  382. static struct ip_set_type hash_netnet_type __read_mostly = {
  383. .name = "hash:net,net",
  384. .protocol = IPSET_PROTOCOL,
  385. .features = IPSET_TYPE_IP | IPSET_TYPE_IP2 | IPSET_TYPE_NOMATCH,
  386. .dimension = IPSET_DIM_TWO,
  387. .family = NFPROTO_UNSPEC,
  388. .revision_min = IPSET_TYPE_REV_MIN,
  389. .revision_max = IPSET_TYPE_REV_MAX,
  390. .create = hash_netnet_create,
  391. .create_policy = {
  392. [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
  393. [IPSET_ATTR_MAXELEM] = { .type = NLA_U32 },
  394. [IPSET_ATTR_PROBES] = { .type = NLA_U8 },
  395. [IPSET_ATTR_RESIZE] = { .type = NLA_U8 },
  396. [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
  397. [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
  398. },
  399. .adt_policy = {
  400. [IPSET_ATTR_IP] = { .type = NLA_NESTED },
  401. [IPSET_ATTR_IP_TO] = { .type = NLA_NESTED },
  402. [IPSET_ATTR_IP2] = { .type = NLA_NESTED },
  403. [IPSET_ATTR_IP2_TO] = { .type = NLA_NESTED },
  404. [IPSET_ATTR_CIDR] = { .type = NLA_U8 },
  405. [IPSET_ATTR_CIDR2] = { .type = NLA_U8 },
  406. [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
  407. [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
  408. [IPSET_ATTR_BYTES] = { .type = NLA_U64 },
  409. [IPSET_ATTR_PACKETS] = { .type = NLA_U64 },
  410. [IPSET_ATTR_COMMENT] = { .type = NLA_NUL_STRING,
  411. .len = IPSET_MAX_COMMENT_SIZE },
  412. [IPSET_ATTR_SKBMARK] = { .type = NLA_U64 },
  413. [IPSET_ATTR_SKBPRIO] = { .type = NLA_U32 },
  414. [IPSET_ATTR_SKBQUEUE] = { .type = NLA_U16 },
  415. },
  416. .me = THIS_MODULE,
  417. };
  418. static int __init
  419. hash_netnet_init(void)
  420. {
  421. return ip_set_type_register(&hash_netnet_type);
  422. }
  423. static void __exit
  424. hash_netnet_fini(void)
  425. {
  426. rcu_barrier();
  427. ip_set_type_unregister(&hash_netnet_type);
  428. }
  429. module_init(hash_netnet_init);
  430. module_exit(hash_netnet_fini);