PageRenderTime 47ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/net/netfilter/ipset/ip_set_hash_ipportip.c

http://github.com/torvalds/linux
C | 403 lines | 325 code | 65 blank | 13 comment | 69 complexity | 94f406f634e92cf0f015f80b359c496e MD5 | raw file
Possible License(s): LGPL-2.0, AGPL-1.0, GPL-2.0
  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,ip 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. /* 1 SCTP and UDPLITE support added */
  21. /* 2 Counters support added */
  22. /* 3 Comments support added */
  23. /* 4 Forceadd support added */
  24. #define IPSET_TYPE_REV_MAX 5 /* skbinfo support added */
  25. MODULE_LICENSE("GPL");
  26. MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@netfilter.org>");
  27. IP_SET_MODULE_DESC("hash:ip,port,ip", IPSET_TYPE_REV_MIN, IPSET_TYPE_REV_MAX);
  28. MODULE_ALIAS("ip_set_hash:ip,port,ip");
  29. /* Type specific function prefix */
  30. #define HTYPE hash_ipportip
  31. /* IPv4 variant */
  32. /* Member elements */
  33. struct hash_ipportip4_elem {
  34. __be32 ip;
  35. __be32 ip2;
  36. __be16 port;
  37. u8 proto;
  38. u8 padding;
  39. };
  40. static bool
  41. hash_ipportip4_data_equal(const struct hash_ipportip4_elem *ip1,
  42. const struct hash_ipportip4_elem *ip2,
  43. u32 *multi)
  44. {
  45. return ip1->ip == ip2->ip &&
  46. ip1->ip2 == ip2->ip2 &&
  47. ip1->port == ip2->port &&
  48. ip1->proto == ip2->proto;
  49. }
  50. static bool
  51. hash_ipportip4_data_list(struct sk_buff *skb,
  52. const struct hash_ipportip4_elem *data)
  53. {
  54. if (nla_put_ipaddr4(skb, IPSET_ATTR_IP, data->ip) ||
  55. nla_put_ipaddr4(skb, IPSET_ATTR_IP2, data->ip2) ||
  56. nla_put_net16(skb, IPSET_ATTR_PORT, data->port) ||
  57. nla_put_u8(skb, IPSET_ATTR_PROTO, data->proto))
  58. goto nla_put_failure;
  59. return false;
  60. nla_put_failure:
  61. return true;
  62. }
  63. static void
  64. hash_ipportip4_data_next(struct hash_ipportip4_elem *next,
  65. const struct hash_ipportip4_elem *d)
  66. {
  67. next->ip = d->ip;
  68. next->port = d->port;
  69. }
  70. /* Common functions */
  71. #define MTYPE hash_ipportip4
  72. #define HOST_MASK 32
  73. #include "ip_set_hash_gen.h"
  74. static int
  75. hash_ipportip4_kadt(struct ip_set *set, const struct sk_buff *skb,
  76. const struct xt_action_param *par,
  77. enum ipset_adt adt, struct ip_set_adt_opt *opt)
  78. {
  79. ipset_adtfn adtfn = set->variant->adt[adt];
  80. struct hash_ipportip4_elem e = { .ip = 0 };
  81. struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
  82. if (!ip_set_get_ip4_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
  83. &e.port, &e.proto))
  84. return -EINVAL;
  85. ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip);
  86. ip4addrptr(skb, opt->flags & IPSET_DIM_THREE_SRC, &e.ip2);
  87. return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
  88. }
  89. static int
  90. hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
  91. enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
  92. {
  93. const struct hash_ipportip4 *h = set->data;
  94. ipset_adtfn adtfn = set->variant->adt[adt];
  95. struct hash_ipportip4_elem e = { .ip = 0 };
  96. struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
  97. u32 ip, ip_to = 0, p = 0, port, port_to;
  98. bool with_ports = false;
  99. int ret;
  100. if (tb[IPSET_ATTR_LINENO])
  101. *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
  102. if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] ||
  103. !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
  104. !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO)))
  105. return -IPSET_ERR_PROTOCOL;
  106. ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP], &e.ip);
  107. if (ret)
  108. return ret;
  109. ret = ip_set_get_extensions(set, tb, &ext);
  110. if (ret)
  111. return ret;
  112. ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP2], &e.ip2);
  113. if (ret)
  114. return ret;
  115. e.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
  116. if (tb[IPSET_ATTR_PROTO]) {
  117. e.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
  118. with_ports = ip_set_proto_with_ports(e.proto);
  119. if (e.proto == 0)
  120. return -IPSET_ERR_INVALID_PROTO;
  121. } else {
  122. return -IPSET_ERR_MISSING_PROTO;
  123. }
  124. if (!(with_ports || e.proto == IPPROTO_ICMP))
  125. e.port = 0;
  126. if (adt == IPSET_TEST ||
  127. !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] ||
  128. tb[IPSET_ATTR_PORT_TO])) {
  129. ret = adtfn(set, &e, &ext, &ext, flags);
  130. return ip_set_eexist(ret, flags) ? 0 : ret;
  131. }
  132. ip_to = ip = ntohl(e.ip);
  133. if (tb[IPSET_ATTR_IP_TO]) {
  134. ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
  135. if (ret)
  136. return ret;
  137. if (ip > ip_to)
  138. swap(ip, ip_to);
  139. } else if (tb[IPSET_ATTR_CIDR]) {
  140. u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
  141. if (!cidr || cidr > HOST_MASK)
  142. return -IPSET_ERR_INVALID_CIDR;
  143. ip_set_mask_from_to(ip, ip_to, cidr);
  144. }
  145. port_to = port = ntohs(e.port);
  146. if (with_ports && tb[IPSET_ATTR_PORT_TO]) {
  147. port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
  148. if (port > port_to)
  149. swap(port, port_to);
  150. }
  151. if (retried)
  152. ip = ntohl(h->next.ip);
  153. for (; ip <= ip_to; ip++) {
  154. p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port)
  155. : port;
  156. for (; p <= port_to; p++) {
  157. e.ip = htonl(ip);
  158. e.port = htons(p);
  159. ret = adtfn(set, &e, &ext, &ext, flags);
  160. if (ret && !ip_set_eexist(ret, flags))
  161. return ret;
  162. ret = 0;
  163. }
  164. }
  165. return ret;
  166. }
  167. /* IPv6 variant */
  168. struct hash_ipportip6_elem {
  169. union nf_inet_addr ip;
  170. union nf_inet_addr ip2;
  171. __be16 port;
  172. u8 proto;
  173. u8 padding;
  174. };
  175. /* Common functions */
  176. static bool
  177. hash_ipportip6_data_equal(const struct hash_ipportip6_elem *ip1,
  178. const struct hash_ipportip6_elem *ip2,
  179. u32 *multi)
  180. {
  181. return ipv6_addr_equal(&ip1->ip.in6, &ip2->ip.in6) &&
  182. ipv6_addr_equal(&ip1->ip2.in6, &ip2->ip2.in6) &&
  183. ip1->port == ip2->port &&
  184. ip1->proto == ip2->proto;
  185. }
  186. static bool
  187. hash_ipportip6_data_list(struct sk_buff *skb,
  188. const struct hash_ipportip6_elem *data)
  189. {
  190. if (nla_put_ipaddr6(skb, IPSET_ATTR_IP, &data->ip.in6) ||
  191. nla_put_ipaddr6(skb, IPSET_ATTR_IP2, &data->ip2.in6) ||
  192. nla_put_net16(skb, IPSET_ATTR_PORT, data->port) ||
  193. nla_put_u8(skb, IPSET_ATTR_PROTO, data->proto))
  194. goto nla_put_failure;
  195. return false;
  196. nla_put_failure:
  197. return true;
  198. }
  199. static void
  200. hash_ipportip6_data_next(struct hash_ipportip6_elem *next,
  201. const struct hash_ipportip6_elem *d)
  202. {
  203. next->port = d->port;
  204. }
  205. #undef MTYPE
  206. #undef HOST_MASK
  207. #define MTYPE hash_ipportip6
  208. #define HOST_MASK 128
  209. #define IP_SET_EMIT_CREATE
  210. #include "ip_set_hash_gen.h"
  211. static int
  212. hash_ipportip6_kadt(struct ip_set *set, const struct sk_buff *skb,
  213. const struct xt_action_param *par,
  214. enum ipset_adt adt, struct ip_set_adt_opt *opt)
  215. {
  216. ipset_adtfn adtfn = set->variant->adt[adt];
  217. struct hash_ipportip6_elem e = { .ip = { .all = { 0 } } };
  218. struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
  219. if (!ip_set_get_ip6_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
  220. &e.port, &e.proto))
  221. return -EINVAL;
  222. ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip.in6);
  223. ip6addrptr(skb, opt->flags & IPSET_DIM_THREE_SRC, &e.ip2.in6);
  224. return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
  225. }
  226. static int
  227. hash_ipportip6_uadt(struct ip_set *set, struct nlattr *tb[],
  228. enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
  229. {
  230. const struct hash_ipportip6 *h = set->data;
  231. ipset_adtfn adtfn = set->variant->adt[adt];
  232. struct hash_ipportip6_elem e = { .ip = { .all = { 0 } } };
  233. struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
  234. u32 port, port_to;
  235. bool with_ports = false;
  236. int ret;
  237. if (tb[IPSET_ATTR_LINENO])
  238. *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
  239. if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] ||
  240. !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
  241. !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO)))
  242. return -IPSET_ERR_PROTOCOL;
  243. if (unlikely(tb[IPSET_ATTR_IP_TO]))
  244. return -IPSET_ERR_HASH_RANGE_UNSUPPORTED;
  245. if (unlikely(tb[IPSET_ATTR_CIDR])) {
  246. u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
  247. if (cidr != HOST_MASK)
  248. return -IPSET_ERR_INVALID_CIDR;
  249. }
  250. ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &e.ip);
  251. if (ret)
  252. return ret;
  253. ret = ip_set_get_extensions(set, tb, &ext);
  254. if (ret)
  255. return ret;
  256. ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP2], &e.ip2);
  257. if (ret)
  258. return ret;
  259. e.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
  260. if (tb[IPSET_ATTR_PROTO]) {
  261. e.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
  262. with_ports = ip_set_proto_with_ports(e.proto);
  263. if (e.proto == 0)
  264. return -IPSET_ERR_INVALID_PROTO;
  265. } else {
  266. return -IPSET_ERR_MISSING_PROTO;
  267. }
  268. if (!(with_ports || e.proto == IPPROTO_ICMPV6))
  269. e.port = 0;
  270. if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) {
  271. ret = adtfn(set, &e, &ext, &ext, flags);
  272. return ip_set_eexist(ret, flags) ? 0 : ret;
  273. }
  274. port = ntohs(e.port);
  275. port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
  276. if (port > port_to)
  277. swap(port, port_to);
  278. if (retried)
  279. port = ntohs(h->next.port);
  280. for (; port <= port_to; port++) {
  281. e.port = htons(port);
  282. ret = adtfn(set, &e, &ext, &ext, flags);
  283. if (ret && !ip_set_eexist(ret, flags))
  284. return ret;
  285. ret = 0;
  286. }
  287. return ret;
  288. }
  289. static struct ip_set_type hash_ipportip_type __read_mostly = {
  290. .name = "hash:ip,port,ip",
  291. .protocol = IPSET_PROTOCOL,
  292. .features = IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_TYPE_IP2,
  293. .dimension = IPSET_DIM_THREE,
  294. .family = NFPROTO_UNSPEC,
  295. .revision_min = IPSET_TYPE_REV_MIN,
  296. .revision_max = IPSET_TYPE_REV_MAX,
  297. .create = hash_ipportip_create,
  298. .create_policy = {
  299. [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
  300. [IPSET_ATTR_MAXELEM] = { .type = NLA_U32 },
  301. [IPSET_ATTR_PROBES] = { .type = NLA_U8 },
  302. [IPSET_ATTR_RESIZE] = { .type = NLA_U8 },
  303. [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
  304. [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
  305. },
  306. .adt_policy = {
  307. [IPSET_ATTR_IP] = { .type = NLA_NESTED },
  308. [IPSET_ATTR_IP_TO] = { .type = NLA_NESTED },
  309. [IPSET_ATTR_IP2] = { .type = NLA_NESTED },
  310. [IPSET_ATTR_PORT] = { .type = NLA_U16 },
  311. [IPSET_ATTR_PORT_TO] = { .type = NLA_U16 },
  312. [IPSET_ATTR_CIDR] = { .type = NLA_U8 },
  313. [IPSET_ATTR_PROTO] = { .type = NLA_U8 },
  314. [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
  315. [IPSET_ATTR_LINENO] = { .type = NLA_U32 },
  316. [IPSET_ATTR_BYTES] = { .type = NLA_U64 },
  317. [IPSET_ATTR_PACKETS] = { .type = NLA_U64 },
  318. [IPSET_ATTR_COMMENT] = { .type = NLA_NUL_STRING,
  319. .len = IPSET_MAX_COMMENT_SIZE },
  320. [IPSET_ATTR_SKBMARK] = { .type = NLA_U64 },
  321. [IPSET_ATTR_SKBPRIO] = { .type = NLA_U32 },
  322. [IPSET_ATTR_SKBQUEUE] = { .type = NLA_U16 },
  323. },
  324. .me = THIS_MODULE,
  325. };
  326. static int __init
  327. hash_ipportip_init(void)
  328. {
  329. return ip_set_type_register(&hash_ipportip_type);
  330. }
  331. static void __exit
  332. hash_ipportip_fini(void)
  333. {
  334. rcu_barrier();
  335. ip_set_type_unregister(&hash_ipportip_type);
  336. }
  337. module_init(hash_ipportip_init);
  338. module_exit(hash_ipportip_fini);