1// SPDX-License-Identifier: GPL-2.0-only 2/* Copyright (C) 2003-2013 Jozsef Kadlecsik <kadlec@netfilter.org> */ 3 4/* Kernel module implementing an IP set type: the hash:net type */ 5 6#include <linux/jhash.h> 7#include <linux/module.h> 8#include <linux/ip.h> 9#include <linux/skbuff.h> 10#include <linux/errno.h> 11#include <linux/random.h> 12#include <net/ip.h> 13#include <net/ipv6.h> 14#include <net/netlink.h> 15 16#include <linux/netfilter.h> 17#include <linux/netfilter/ipset/pfxlen.h> 18#include <linux/netfilter/ipset/ip_set.h> 19#include <linux/netfilter/ipset/ip_set_hash.h> 20 21#define IPSET_TYPE_REV_MIN 0 22/* 1 Range as input support for IPv4 added */ 23/* 2 nomatch flag support added */ 24/* 3 Counters support added */ 25/* 4 Comments support added */ 26/* 5 Forceadd support added */ 27/* 6 skbinfo support added */ 28#define IPSET_TYPE_REV_MAX 7 /* bucketsize, initval support added */ 29 30MODULE_LICENSE("GPL"); 31MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@netfilter.org>"); 32IP_SET_MODULE_DESC("hash:net", IPSET_TYPE_REV_MIN, IPSET_TYPE_REV_MAX); 33MODULE_ALIAS("ip_set_hash:net"); 34 35/* Type specific function prefix */ 36#define HTYPE hash_net 37#define IP_SET_HASH_WITH_NETS 38 39/* IPv4 variant */ 40 41/* Member elements */ 42struct hash_net4_elem { 43 __be32 ip; 44 u16 padding0; 45 u8 nomatch; 46 u8 cidr; 47}; 48 49/* Common functions */ 50 51static bool 52hash_net4_data_equal(const struct hash_net4_elem *ip1, 53 const struct hash_net4_elem *ip2, 54 u32 *multi) 55{ 56 return ip1->ip == ip2->ip && 57 ip1->cidr == ip2->cidr; 58} 59 60static int 61hash_net4_do_data_match(const struct hash_net4_elem *elem) 62{ 63 return elem->nomatch ? -ENOTEMPTY : 1; 64} 65 66static void 67hash_net4_data_set_flags(struct hash_net4_elem *elem, u32 flags) 68{ 69 elem->nomatch = (flags >> 16) & IPSET_FLAG_NOMATCH; 70} 71 72static void 73hash_net4_data_reset_flags(struct hash_net4_elem *elem, u8 *flags) 74{ 75 swap(*flags, elem->nomatch); 76} 77 78static void 79hash_net4_data_netmask(struct hash_net4_elem *elem, u8 cidr) 80{ 81 elem->ip &= ip_set_netmask(cidr); 82 elem->cidr = cidr; 83} 84 85static bool 86hash_net4_data_list(struct sk_buff *skb, const struct hash_net4_elem *data) 87{ 88 u32 flags = data->nomatch ? IPSET_FLAG_NOMATCH : 0; 89 90 if (nla_put_ipaddr4(skb, IPSET_ATTR_IP, data->ip) || 91 nla_put_u8(skb, IPSET_ATTR_CIDR, data->cidr) || 92 (flags && 93 nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags)))) 94 goto nla_put_failure; 95 return false; 96 97nla_put_failure: 98 return true; 99} 100 101static void 102hash_net4_data_next(struct hash_net4_elem *next, 103 const struct hash_net4_elem *d) 104{ 105 next->ip = d->ip; 106} 107 108#define MTYPE hash_net4 109#define HOST_MASK 32 110#include "ip_set_hash_gen.h" 111 112static int 113hash_net4_kadt(struct ip_set *set, const struct sk_buff *skb, 114 const struct xt_action_param *par, 115 enum ipset_adt adt, struct ip_set_adt_opt *opt) 116{ 117 const struct hash_net4 *h = set->data; 118 ipset_adtfn adtfn = set->variant->adt[adt]; 119 struct hash_net4_elem e = { 120 .cidr = INIT_CIDR(h->nets[0].cidr[0], HOST_MASK), 121 }; 122 struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set); 123 124 if (e.cidr == 0) 125 return -EINVAL; 126 if (adt == IPSET_TEST) 127 e.cidr = HOST_MASK; 128 129 ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip); 130 e.ip &= ip_set_netmask(e.cidr); 131 132 return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags); 133} 134 135static int 136hash_net4_uadt(struct ip_set *set, struct nlattr *tb[], 137 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried) 138{ 139 struct hash_net4 *h = set->data; 140 ipset_adtfn adtfn = set->variant->adt[adt]; 141 struct hash_net4_elem e = { .cidr = HOST_MASK }; 142 struct ip_set_ext ext = IP_SET_INIT_UEXT(set); 143 u32 ip = 0, ip_to = 0, i = 0; 144 int ret; 145 146 if (tb[IPSET_ATTR_LINENO]) 147 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); 148 149 if (unlikely(!tb[IPSET_ATTR_IP] || 150 !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS))) 151 return -IPSET_ERR_PROTOCOL; 152 153 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip); 154 if (ret) 155 return ret; 156 157 ret = ip_set_get_extensions(set, tb, &ext); 158 if (ret) 159 return ret; 160 161 if (tb[IPSET_ATTR_CIDR]) { 162 e.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); 163 if (!e.cidr || e.cidr > HOST_MASK) 164 return -IPSET_ERR_INVALID_CIDR; 165 } 166 167 if (tb[IPSET_ATTR_CADT_FLAGS]) { 168 u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]); 169 170 if (cadt_flags & IPSET_FLAG_NOMATCH) 171 flags |= (IPSET_FLAG_NOMATCH << 16); 172 } 173 174 if (adt == IPSET_TEST || !tb[IPSET_ATTR_IP_TO]) { 175 e.ip = htonl(ip & ip_set_hostmask(e.cidr)); 176 ret = adtfn(set, &e, &ext, &ext, flags); 177 return ip_set_enomatch(ret, flags, adt, set) ? -ret : 178 ip_set_eexist(ret, flags) ? 0 : ret; 179 } 180 181 ip_to = ip; 182 if (tb[IPSET_ATTR_IP_TO]) { 183 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to); 184 if (ret) 185 return ret; 186 if (ip_to < ip) 187 swap(ip, ip_to); 188 if (ip + UINT_MAX == ip_to) 189 return -IPSET_ERR_HASH_RANGE; 190 } 191 192 if (retried) 193 ip = ntohl(h->next.ip); 194 do { 195 i++; 196 e.ip = htonl(ip); 197 if (i > IPSET_MAX_RANGE) { 198 hash_net4_data_next(&h->next, &e); 199 return -ERANGE; 200 } 201 ip = ip_set_range_to_cidr(ip, ip_to, &e.cidr); 202 ret = adtfn(set, &e, &ext, &ext, flags); 203 if (ret && !ip_set_eexist(ret, flags)) 204 return ret; 205 206 ret = 0; 207 } while (ip++ < ip_to); 208 return ret; 209} 210 211/* IPv6 variant */ 212 213struct hash_net6_elem { 214 union nf_inet_addr ip; 215 u16 padding0; 216 u8 nomatch; 217 u8 cidr; 218}; 219 220/* Common functions */ 221 222static bool 223hash_net6_data_equal(const struct hash_net6_elem *ip1, 224 const struct hash_net6_elem *ip2, 225 u32 *multi) 226{ 227 return ipv6_addr_equal(&ip1->ip.in6, &ip2->ip.in6) && 228 ip1->cidr == ip2->cidr; 229} 230 231static int 232hash_net6_do_data_match(const struct hash_net6_elem *elem) 233{ 234 return elem->nomatch ? -ENOTEMPTY : 1; 235} 236 237static void 238hash_net6_data_set_flags(struct hash_net6_elem *elem, u32 flags) 239{ 240 elem->nomatch = (flags >> 16) & IPSET_FLAG_NOMATCH; 241} 242 243static void 244hash_net6_data_reset_flags(struct hash_net6_elem *elem, u8 *flags) 245{ 246 swap(*flags, elem->nomatch); 247} 248 249static void 250hash_net6_data_netmask(struct hash_net6_elem *elem, u8 cidr) 251{ 252 ip6_netmask(&elem->ip, cidr); 253 elem->cidr = cidr; 254} 255 256static bool 257hash_net6_data_list(struct sk_buff *skb, const struct hash_net6_elem *data) 258{ 259 u32 flags = data->nomatch ? IPSET_FLAG_NOMATCH : 0; 260 261 if (nla_put_ipaddr6(skb, IPSET_ATTR_IP, &data->ip.in6) || 262 nla_put_u8(skb, IPSET_ATTR_CIDR, data->cidr) || 263 (flags && 264 nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags)))) 265 goto nla_put_failure; 266 return false; 267 268nla_put_failure: 269 return true; 270} 271 272static void 273hash_net6_data_next(struct hash_net6_elem *next, 274 const struct hash_net6_elem *d) 275{ 276} 277 278#undef MTYPE 279#undef HOST_MASK 280 281#define MTYPE hash_net6 282#define HOST_MASK 128 283#define IP_SET_EMIT_CREATE 284#include "ip_set_hash_gen.h" 285 286static int 287hash_net6_kadt(struct ip_set *set, const struct sk_buff *skb, 288 const struct xt_action_param *par, 289 enum ipset_adt adt, struct ip_set_adt_opt *opt) 290{ 291 const struct hash_net6 *h = set->data; 292 ipset_adtfn adtfn = set->variant->adt[adt]; 293 struct hash_net6_elem e = { 294 .cidr = INIT_CIDR(h->nets[0].cidr[0], HOST_MASK), 295 }; 296 struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set); 297 298 if (e.cidr == 0) 299 return -EINVAL; 300 if (adt == IPSET_TEST) 301 e.cidr = HOST_MASK; 302 303 ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip.in6); 304 ip6_netmask(&e.ip, e.cidr); 305 306 return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags); 307} 308 309static int 310hash_net6_uadt(struct ip_set *set, struct nlattr *tb[], 311 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried) 312{ 313 ipset_adtfn adtfn = set->variant->adt[adt]; 314 struct hash_net6_elem e = { .cidr = HOST_MASK }; 315 struct ip_set_ext ext = IP_SET_INIT_UEXT(set); 316 int ret; 317 318 if (tb[IPSET_ATTR_LINENO]) 319 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); 320 321 if (unlikely(!tb[IPSET_ATTR_IP] || 322 !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS))) 323 return -IPSET_ERR_PROTOCOL; 324 if (unlikely(tb[IPSET_ATTR_IP_TO])) 325 return -IPSET_ERR_HASH_RANGE_UNSUPPORTED; 326 327 ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &e.ip); 328 if (ret) 329 return ret; 330 331 ret = ip_set_get_extensions(set, tb, &ext); 332 if (ret) 333 return ret; 334 335 if (tb[IPSET_ATTR_CIDR]) { 336 e.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); 337 if (!e.cidr || e.cidr > HOST_MASK) 338 return -IPSET_ERR_INVALID_CIDR; 339 } 340 341 ip6_netmask(&e.ip, e.cidr); 342 343 if (tb[IPSET_ATTR_CADT_FLAGS]) { 344 u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]); 345 346 if (cadt_flags & IPSET_FLAG_NOMATCH) 347 flags |= (IPSET_FLAG_NOMATCH << 16); 348 } 349 350 ret = adtfn(set, &e, &ext, &ext, flags); 351 352 return ip_set_enomatch(ret, flags, adt, set) ? -ret : 353 ip_set_eexist(ret, flags) ? 0 : ret; 354} 355 356static struct ip_set_type hash_net_type __read_mostly = { 357 .name = "hash:net", 358 .protocol = IPSET_PROTOCOL, 359 .features = IPSET_TYPE_IP | IPSET_TYPE_NOMATCH, 360 .dimension = IPSET_DIM_ONE, 361 .family = NFPROTO_UNSPEC, 362 .revision_min = IPSET_TYPE_REV_MIN, 363 .revision_max = IPSET_TYPE_REV_MAX, 364 .create_flags[IPSET_TYPE_REV_MAX] = IPSET_CREATE_FLAG_BUCKETSIZE, 365 .create = hash_net_create, 366 .create_policy = { 367 [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, 368 [IPSET_ATTR_MAXELEM] = { .type = NLA_U32 }, 369 [IPSET_ATTR_INITVAL] = { .type = NLA_U32 }, 370 [IPSET_ATTR_BUCKETSIZE] = { .type = NLA_U8 }, 371 [IPSET_ATTR_RESIZE] = { .type = NLA_U8 }, 372 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 373 [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 }, 374 }, 375 .adt_policy = { 376 [IPSET_ATTR_IP] = { .type = NLA_NESTED }, 377 [IPSET_ATTR_IP_TO] = { .type = NLA_NESTED }, 378 [IPSET_ATTR_CIDR] = { .type = NLA_U8 }, 379 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 380 [IPSET_ATTR_LINENO] = { .type = NLA_U32 }, 381 [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 }, 382 [IPSET_ATTR_BYTES] = { .type = NLA_U64 }, 383 [IPSET_ATTR_PACKETS] = { .type = NLA_U64 }, 384 [IPSET_ATTR_COMMENT] = { .type = NLA_NUL_STRING, 385 .len = IPSET_MAX_COMMENT_SIZE }, 386 [IPSET_ATTR_SKBMARK] = { .type = NLA_U64 }, 387 [IPSET_ATTR_SKBPRIO] = { .type = NLA_U32 }, 388 [IPSET_ATTR_SKBQUEUE] = { .type = NLA_U16 }, 389 }, 390 .me = THIS_MODULE, 391}; 392 393static int __init 394hash_net_init(void) 395{ 396 return ip_set_type_register(&hash_net_type); 397} 398 399static void __exit 400hash_net_fini(void) 401{ 402 rcu_barrier(); 403 ip_set_type_unregister(&hash_net_type); 404} 405 406module_init(hash_net_init); 407module_exit(hash_net_fini); 408