ip_set_hash_netiface.c 13 KB

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