ip_set_hash_netportnet.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /* Copyright (C) 2003-2013 Jozsef Kadlecsik <kadlec@netfilter.org> */
  3. /* Kernel module implementing an IP set type: the hash:ip,port,net type */
  4. #include <linux/jhash.h>
  5. #include <linux/module.h>
  6. #include <linux/ip.h>
  7. #include <linux/skbuff.h>
  8. #include <linux/errno.h>
  9. #include <linux/random.h>
  10. #include <net/ip.h>
  11. #include <net/ipv6.h>
  12. #include <net/netlink.h>
  13. #include <net/tcp.h>
  14. #include <linux/netfilter.h>
  15. #include <linux/netfilter/ipset/pfxlen.h>
  16. #include <linux/netfilter/ipset/ip_set.h>
  17. #include <linux/netfilter/ipset/ip_set_getport.h>
  18. #include <linux/netfilter/ipset/ip_set_hash.h>
  19. #define IPSET_TYPE_REV_MIN 0
  20. /* 0 Comments support added */
  21. /* 1 Forceadd support added */
  22. #define IPSET_TYPE_REV_MAX 2 /* skbinfo support added */
  23. MODULE_LICENSE("GPL");
  24. MODULE_AUTHOR("Oliver Smith <oliver@8.c.9.b.0.7.4.0.1.0.0.2.ip6.arpa>");
  25. IP_SET_MODULE_DESC("hash:net,port,net", IPSET_TYPE_REV_MIN, IPSET_TYPE_REV_MAX);
  26. MODULE_ALIAS("ip_set_hash:net,port,net");
  27. /* Type specific function prefix */
  28. #define HTYPE hash_netportnet
  29. #define IP_SET_HASH_WITH_PROTO
  30. #define IP_SET_HASH_WITH_NETS
  31. #define IPSET_NET_COUNT 2
  32. /* IPv4 variant */
  33. /* Member elements */
  34. struct hash_netportnet4_elem {
  35. union {
  36. __be32 ip[2];
  37. __be64 ipcmp;
  38. };
  39. __be16 port;
  40. union {
  41. u8 cidr[2];
  42. u16 ccmp;
  43. };
  44. u16 padding;
  45. u8 nomatch;
  46. u8 proto;
  47. };
  48. /* Common functions */
  49. static bool
  50. hash_netportnet4_data_equal(const struct hash_netportnet4_elem *ip1,
  51. const struct hash_netportnet4_elem *ip2,
  52. u32 *multi)
  53. {
  54. return ip1->ipcmp == ip2->ipcmp &&
  55. ip1->ccmp == ip2->ccmp &&
  56. ip1->port == ip2->port &&
  57. ip1->proto == ip2->proto;
  58. }
  59. static int
  60. hash_netportnet4_do_data_match(const struct hash_netportnet4_elem *elem)
  61. {
  62. return elem->nomatch ? -ENOTEMPTY : 1;
  63. }
  64. static void
  65. hash_netportnet4_data_set_flags(struct hash_netportnet4_elem *elem, u32 flags)
  66. {
  67. elem->nomatch = !!((flags >> 16) & IPSET_FLAG_NOMATCH);
  68. }
  69. static void
  70. hash_netportnet4_data_reset_flags(struct hash_netportnet4_elem *elem, u8 *flags)
  71. {
  72. swap(*flags, elem->nomatch);
  73. }
  74. static void
  75. hash_netportnet4_data_reset_elem(struct hash_netportnet4_elem *elem,
  76. struct hash_netportnet4_elem *orig)
  77. {
  78. elem->ip[1] = orig->ip[1];
  79. }
  80. static void
  81. hash_netportnet4_data_netmask(struct hash_netportnet4_elem *elem,
  82. u8 cidr, bool inner)
  83. {
  84. if (inner) {
  85. elem->ip[1] &= ip_set_netmask(cidr);
  86. elem->cidr[1] = cidr;
  87. } else {
  88. elem->ip[0] &= ip_set_netmask(cidr);
  89. elem->cidr[0] = cidr;
  90. }
  91. }
  92. static bool
  93. hash_netportnet4_data_list(struct sk_buff *skb,
  94. const struct hash_netportnet4_elem *data)
  95. {
  96. u32 flags = data->nomatch ? IPSET_FLAG_NOMATCH : 0;
  97. if (nla_put_ipaddr4(skb, IPSET_ATTR_IP, data->ip[0]) ||
  98. nla_put_ipaddr4(skb, IPSET_ATTR_IP2, data->ip[1]) ||
  99. nla_put_net16(skb, IPSET_ATTR_PORT, data->port) ||
  100. nla_put_u8(skb, IPSET_ATTR_CIDR, data->cidr[0]) ||
  101. nla_put_u8(skb, IPSET_ATTR_CIDR2, data->cidr[1]) ||
  102. nla_put_u8(skb, IPSET_ATTR_PROTO, data->proto) ||
  103. (flags &&
  104. nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags))))
  105. goto nla_put_failure;
  106. return false;
  107. nla_put_failure:
  108. return true;
  109. }
  110. static void
  111. hash_netportnet4_data_next(struct hash_netportnet4_elem *next,
  112. const struct hash_netportnet4_elem *d)
  113. {
  114. next->ipcmp = d->ipcmp;
  115. next->port = d->port;
  116. }
  117. #define MTYPE hash_netportnet4
  118. #define HOST_MASK 32
  119. #include "ip_set_hash_gen.h"
  120. static void
  121. hash_netportnet4_init(struct hash_netportnet4_elem *e)
  122. {
  123. e->cidr[0] = HOST_MASK;
  124. e->cidr[1] = HOST_MASK;
  125. }
  126. static int
  127. hash_netportnet4_kadt(struct ip_set *set, const struct sk_buff *skb,
  128. const struct xt_action_param *par,
  129. enum ipset_adt adt, struct ip_set_adt_opt *opt)
  130. {
  131. const struct hash_netportnet4 *h = set->data;
  132. ipset_adtfn adtfn = set->variant->adt[adt];
  133. struct hash_netportnet4_elem e = { };
  134. struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
  135. e.cidr[0] = INIT_CIDR(h->nets[0].cidr[0], HOST_MASK);
  136. e.cidr[1] = INIT_CIDR(h->nets[0].cidr[1], HOST_MASK);
  137. if (adt == IPSET_TEST)
  138. e.ccmp = (HOST_MASK << (sizeof(e.cidr[0]) * 8)) | HOST_MASK;
  139. if (!ip_set_get_ip4_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
  140. &e.port, &e.proto))
  141. return -EINVAL;
  142. ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip[0]);
  143. ip4addrptr(skb, opt->flags & IPSET_DIM_THREE_SRC, &e.ip[1]);
  144. e.ip[0] &= ip_set_netmask(e.cidr[0]);
  145. e.ip[1] &= ip_set_netmask(e.cidr[1]);
  146. return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
  147. }
  148. static int
  149. hash_netportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
  150. enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
  151. {
  152. const struct hash_netportnet4 *h = set->data;
  153. ipset_adtfn adtfn = set->variant->adt[adt];
  154. struct hash_netportnet4_elem e = { };
  155. struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
  156. u32 ip = 0, ip_to = 0, p = 0, port, port_to;
  157. u32 ip2_from = 0, ip2_to = 0, ip2;
  158. bool with_ports = false;
  159. int ret;
  160. if (tb[IPSET_ATTR_LINENO])
  161. *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
  162. hash_netportnet4_init(&e);
  163. if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] ||
  164. !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
  165. !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
  166. !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS)))
  167. return -IPSET_ERR_PROTOCOL;
  168. ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip);
  169. if (ret)
  170. return ret;
  171. ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP2], &ip2_from);
  172. if (ret)
  173. return ret;
  174. ret = ip_set_get_extensions(set, tb, &ext);
  175. if (ret)
  176. return ret;
  177. if (tb[IPSET_ATTR_CIDR]) {
  178. e.cidr[0] = nla_get_u8(tb[IPSET_ATTR_CIDR]);
  179. if (e.cidr[0] > HOST_MASK)
  180. return -IPSET_ERR_INVALID_CIDR;
  181. }
  182. if (tb[IPSET_ATTR_CIDR2]) {
  183. e.cidr[1] = nla_get_u8(tb[IPSET_ATTR_CIDR2]);
  184. if (e.cidr[1] > HOST_MASK)
  185. return -IPSET_ERR_INVALID_CIDR;
  186. }
  187. e.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
  188. if (tb[IPSET_ATTR_PROTO]) {
  189. e.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
  190. with_ports = ip_set_proto_with_ports(e.proto);
  191. if (e.proto == 0)
  192. return -IPSET_ERR_INVALID_PROTO;
  193. } else {
  194. return -IPSET_ERR_MISSING_PROTO;
  195. }
  196. if (!(with_ports || e.proto == IPPROTO_ICMP))
  197. e.port = 0;
  198. if (tb[IPSET_ATTR_CADT_FLAGS]) {
  199. u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
  200. if (cadt_flags & IPSET_FLAG_NOMATCH)
  201. flags |= (IPSET_FLAG_NOMATCH << 16);
  202. }
  203. with_ports = with_ports && tb[IPSET_ATTR_PORT_TO];
  204. if (adt == IPSET_TEST ||
  205. !(tb[IPSET_ATTR_IP_TO] || with_ports || tb[IPSET_ATTR_IP2_TO])) {
  206. e.ip[0] = htonl(ip & ip_set_hostmask(e.cidr[0]));
  207. e.ip[1] = htonl(ip2_from & ip_set_hostmask(e.cidr[1]));
  208. ret = adtfn(set, &e, &ext, &ext, flags);
  209. return ip_set_enomatch(ret, flags, adt, set) ? -ret :
  210. ip_set_eexist(ret, flags) ? 0 : ret;
  211. }
  212. ip_to = ip;
  213. if (tb[IPSET_ATTR_IP_TO]) {
  214. ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
  215. if (ret)
  216. return ret;
  217. if (ip > ip_to)
  218. swap(ip, ip_to);
  219. if (unlikely(ip + UINT_MAX == ip_to))
  220. return -IPSET_ERR_HASH_RANGE;
  221. } else {
  222. ip_set_mask_from_to(ip, ip_to, e.cidr[0]);
  223. }
  224. port_to = port = ntohs(e.port);
  225. if (tb[IPSET_ATTR_PORT_TO]) {
  226. port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
  227. if (port > port_to)
  228. swap(port, port_to);
  229. }
  230. ip2_to = ip2_from;
  231. if (tb[IPSET_ATTR_IP2_TO]) {
  232. ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP2_TO], &ip2_to);
  233. if (ret)
  234. return ret;
  235. if (ip2_from > ip2_to)
  236. swap(ip2_from, ip2_to);
  237. if (unlikely(ip2_from + UINT_MAX == ip2_to))
  238. return -IPSET_ERR_HASH_RANGE;
  239. } else {
  240. ip_set_mask_from_to(ip2_from, ip2_to, e.cidr[1]);
  241. }
  242. if (retried) {
  243. ip = ntohl(h->next.ip[0]);
  244. p = ntohs(h->next.port);
  245. ip2 = ntohl(h->next.ip[1]);
  246. } else {
  247. p = port;
  248. ip2 = ip2_from;
  249. }
  250. do {
  251. e.ip[0] = htonl(ip);
  252. ip = ip_set_range_to_cidr(ip, ip_to, &e.cidr[0]);
  253. for (; p <= port_to; p++) {
  254. e.port = htons(p);
  255. do {
  256. e.ip[1] = htonl(ip2);
  257. ip2 = ip_set_range_to_cidr(ip2, ip2_to,
  258. &e.cidr[1]);
  259. ret = adtfn(set, &e, &ext, &ext, flags);
  260. if (ret && !ip_set_eexist(ret, flags))
  261. return ret;
  262. ret = 0;
  263. } while (ip2++ < ip2_to);
  264. ip2 = ip2_from;
  265. }
  266. p = port;
  267. } while (ip++ < ip_to);
  268. return ret;
  269. }
  270. /* IPv6 variant */
  271. struct hash_netportnet6_elem {
  272. union nf_inet_addr ip[2];
  273. __be16 port;
  274. union {
  275. u8 cidr[2];
  276. u16 ccmp;
  277. };
  278. u16 padding;
  279. u8 nomatch;
  280. u8 proto;
  281. };
  282. /* Common functions */
  283. static bool
  284. hash_netportnet6_data_equal(const struct hash_netportnet6_elem *ip1,
  285. const struct hash_netportnet6_elem *ip2,
  286. u32 *multi)
  287. {
  288. return ipv6_addr_equal(&ip1->ip[0].in6, &ip2->ip[0].in6) &&
  289. ipv6_addr_equal(&ip1->ip[1].in6, &ip2->ip[1].in6) &&
  290. ip1->ccmp == ip2->ccmp &&
  291. ip1->port == ip2->port &&
  292. ip1->proto == ip2->proto;
  293. }
  294. static int
  295. hash_netportnet6_do_data_match(const struct hash_netportnet6_elem *elem)
  296. {
  297. return elem->nomatch ? -ENOTEMPTY : 1;
  298. }
  299. static void
  300. hash_netportnet6_data_set_flags(struct hash_netportnet6_elem *elem, u32 flags)
  301. {
  302. elem->nomatch = !!((flags >> 16) & IPSET_FLAG_NOMATCH);
  303. }
  304. static void
  305. hash_netportnet6_data_reset_flags(struct hash_netportnet6_elem *elem, u8 *flags)
  306. {
  307. swap(*flags, elem->nomatch);
  308. }
  309. static void
  310. hash_netportnet6_data_reset_elem(struct hash_netportnet6_elem *elem,
  311. struct hash_netportnet6_elem *orig)
  312. {
  313. elem->ip[1] = orig->ip[1];
  314. }
  315. static void
  316. hash_netportnet6_data_netmask(struct hash_netportnet6_elem *elem,
  317. u8 cidr, bool inner)
  318. {
  319. if (inner) {
  320. ip6_netmask(&elem->ip[1], cidr);
  321. elem->cidr[1] = cidr;
  322. } else {
  323. ip6_netmask(&elem->ip[0], cidr);
  324. elem->cidr[0] = cidr;
  325. }
  326. }
  327. static bool
  328. hash_netportnet6_data_list(struct sk_buff *skb,
  329. const struct hash_netportnet6_elem *data)
  330. {
  331. u32 flags = data->nomatch ? IPSET_FLAG_NOMATCH : 0;
  332. if (nla_put_ipaddr6(skb, IPSET_ATTR_IP, &data->ip[0].in6) ||
  333. nla_put_ipaddr6(skb, IPSET_ATTR_IP2, &data->ip[1].in6) ||
  334. nla_put_net16(skb, IPSET_ATTR_PORT, data->port) ||
  335. nla_put_u8(skb, IPSET_ATTR_CIDR, data->cidr[0]) ||
  336. nla_put_u8(skb, IPSET_ATTR_CIDR2, data->cidr[1]) ||
  337. nla_put_u8(skb, IPSET_ATTR_PROTO, data->proto) ||
  338. (flags &&
  339. nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags))))
  340. goto nla_put_failure;
  341. return false;
  342. nla_put_failure:
  343. return true;
  344. }
  345. static void
  346. hash_netportnet6_data_next(struct hash_netportnet6_elem *next,
  347. const struct hash_netportnet6_elem *d)
  348. {
  349. next->port = d->port;
  350. }
  351. #undef MTYPE
  352. #undef HOST_MASK
  353. #define MTYPE hash_netportnet6
  354. #define HOST_MASK 128
  355. #define IP_SET_EMIT_CREATE
  356. #include "ip_set_hash_gen.h"
  357. static void
  358. hash_netportnet6_init(struct hash_netportnet6_elem *e)
  359. {
  360. e->cidr[0] = HOST_MASK;
  361. e->cidr[1] = HOST_MASK;
  362. }
  363. static int
  364. hash_netportnet6_kadt(struct ip_set *set, const struct sk_buff *skb,
  365. const struct xt_action_param *par,
  366. enum ipset_adt adt, struct ip_set_adt_opt *opt)
  367. {
  368. const struct hash_netportnet6 *h = set->data;
  369. ipset_adtfn adtfn = set->variant->adt[adt];
  370. struct hash_netportnet6_elem e = { };
  371. struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
  372. e.cidr[0] = INIT_CIDR(h->nets[0].cidr[0], HOST_MASK);
  373. e.cidr[1] = INIT_CIDR(h->nets[0].cidr[1], HOST_MASK);
  374. if (adt == IPSET_TEST)
  375. e.ccmp = (HOST_MASK << (sizeof(u8) * 8)) | HOST_MASK;
  376. if (!ip_set_get_ip6_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
  377. &e.port, &e.proto))
  378. return -EINVAL;
  379. ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip[0].in6);
  380. ip6addrptr(skb, opt->flags & IPSET_DIM_THREE_SRC, &e.ip[1].in6);
  381. ip6_netmask(&e.ip[0], e.cidr[0]);
  382. ip6_netmask(&e.ip[1], e.cidr[1]);
  383. return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
  384. }
  385. static int
  386. hash_netportnet6_uadt(struct ip_set *set, struct nlattr *tb[],
  387. enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
  388. {
  389. const struct hash_netportnet6 *h = set->data;
  390. ipset_adtfn adtfn = set->variant->adt[adt];
  391. struct hash_netportnet6_elem e = { };
  392. struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
  393. u32 port, port_to;
  394. bool with_ports = false;
  395. int ret;
  396. if (tb[IPSET_ATTR_LINENO])
  397. *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
  398. hash_netportnet6_init(&e);
  399. if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] ||
  400. !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
  401. !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
  402. !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS)))
  403. return -IPSET_ERR_PROTOCOL;
  404. if (unlikely(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_IP2_TO]))
  405. return -IPSET_ERR_HASH_RANGE_UNSUPPORTED;
  406. ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &e.ip[0]);
  407. if (ret)
  408. return ret;
  409. ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP2], &e.ip[1]);
  410. if (ret)
  411. return ret;
  412. ret = ip_set_get_extensions(set, tb, &ext);
  413. if (ret)
  414. return ret;
  415. if (tb[IPSET_ATTR_CIDR]) {
  416. e.cidr[0] = nla_get_u8(tb[IPSET_ATTR_CIDR]);
  417. if (e.cidr[0] > HOST_MASK)
  418. return -IPSET_ERR_INVALID_CIDR;
  419. }
  420. if (tb[IPSET_ATTR_CIDR2]) {
  421. e.cidr[1] = nla_get_u8(tb[IPSET_ATTR_CIDR2]);
  422. if (e.cidr[1] > HOST_MASK)
  423. return -IPSET_ERR_INVALID_CIDR;
  424. }
  425. ip6_netmask(&e.ip[0], e.cidr[0]);
  426. ip6_netmask(&e.ip[1], e.cidr[1]);
  427. e.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
  428. if (tb[IPSET_ATTR_PROTO]) {
  429. e.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
  430. with_ports = ip_set_proto_with_ports(e.proto);
  431. if (e.proto == 0)
  432. return -IPSET_ERR_INVALID_PROTO;
  433. } else {
  434. return -IPSET_ERR_MISSING_PROTO;
  435. }
  436. if (!(with_ports || e.proto == IPPROTO_ICMPV6))
  437. e.port = 0;
  438. if (tb[IPSET_ATTR_CADT_FLAGS]) {
  439. u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
  440. if (cadt_flags & IPSET_FLAG_NOMATCH)
  441. flags |= (IPSET_FLAG_NOMATCH << 16);
  442. }
  443. if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) {
  444. ret = adtfn(set, &e, &ext, &ext, flags);
  445. return ip_set_enomatch(ret, flags, adt, set) ? -ret :
  446. ip_set_eexist(ret, flags) ? 0 : ret;
  447. }
  448. port = ntohs(e.port);
  449. port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
  450. if (port > port_to)
  451. swap(port, port_to);
  452. if (retried)
  453. port = ntohs(h->next.port);
  454. for (; port <= port_to; port++) {
  455. e.port = htons(port);
  456. ret = adtfn(set, &e, &ext, &ext, flags);
  457. if (ret && !ip_set_eexist(ret, flags))
  458. return ret;
  459. ret = 0;
  460. }
  461. return ret;
  462. }
  463. static struct ip_set_type hash_netportnet_type __read_mostly = {
  464. .name = "hash:net,port,net",
  465. .protocol = IPSET_PROTOCOL,
  466. .features = IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_TYPE_IP2 |
  467. IPSET_TYPE_NOMATCH,
  468. .dimension = IPSET_DIM_THREE,
  469. .family = NFPROTO_UNSPEC,
  470. .revision_min = IPSET_TYPE_REV_MIN,
  471. .revision_max = IPSET_TYPE_REV_MAX,
  472. .create = hash_netportnet_create,
  473. .create_policy = {
  474. [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
  475. [IPSET_ATTR_MAXELEM] = { .type = NLA_U32 },
  476. [IPSET_ATTR_PROBES] = { .type = NLA_U8 },
  477. [IPSET_ATTR_RESIZE] = { .type = NLA_U8 },
  478. [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
  479. [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
  480. },
  481. .adt_policy = {
  482. [IPSET_ATTR_IP] = { .type = NLA_NESTED },
  483. [IPSET_ATTR_IP_TO] = { .type = NLA_NESTED },
  484. [IPSET_ATTR_IP2] = { .type = NLA_NESTED },
  485. [IPSET_ATTR_IP2_TO] = { .type = NLA_NESTED },
  486. [IPSET_ATTR_PORT] = { .type = NLA_U16 },
  487. [IPSET_ATTR_PORT_TO] = { .type = NLA_U16 },
  488. [IPSET_ATTR_CIDR] = { .type = NLA_U8 },
  489. [IPSET_ATTR_CIDR2] = { .type = NLA_U8 },
  490. [IPSET_ATTR_PROTO] = { .type = NLA_U8 },
  491. [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
  492. [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
  493. [IPSET_ATTR_LINENO] = { .type = NLA_U32 },
  494. [IPSET_ATTR_BYTES] = { .type = NLA_U64 },
  495. [IPSET_ATTR_PACKETS] = { .type = NLA_U64 },
  496. [IPSET_ATTR_COMMENT] = { .type = NLA_NUL_STRING,
  497. .len = IPSET_MAX_COMMENT_SIZE },
  498. [IPSET_ATTR_SKBMARK] = { .type = NLA_U64 },
  499. [IPSET_ATTR_SKBPRIO] = { .type = NLA_U32 },
  500. [IPSET_ATTR_SKBQUEUE] = { .type = NLA_U16 },
  501. },
  502. .me = THIS_MODULE,
  503. };
  504. static int __init
  505. hash_netportnet_init(void)
  506. {
  507. return ip_set_type_register(&hash_netportnet_type);
  508. }
  509. static void __exit
  510. hash_netportnet_fini(void)
  511. {
  512. rcu_barrier();
  513. ip_set_type_unregister(&hash_netportnet_type);
  514. }
  515. module_init(hash_netportnet_init);
  516. module_exit(hash_netportnet_fini);