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 30 MODULE_LICENSE("GPL"); 31 MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@netfilter.org>"); 32 IP_SET_MODULE_DESC("hash:net", IPSET_TYPE_REV_MIN, IPSET_TYPE_REV_MAX); 33 MODULE_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 */ 42 struct hash_net4_elem { 43 __be32 ip; 44 u16 padding0; 45 u8 nomatch; 46 u8 cidr; 47 }; 48 49 /* Common functions */ 50 51 static bool 52 hash_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 60 static int 61 hash_net4_do_data_match(const struct hash_net4_elem *elem) 62 { 63 return elem->nomatch ? -ENOTEMPTY : 1; 64 } 65 66 static void 67 hash_net4_data_set_flags(struct hash_net4_elem *elem, u32 flags) 68 { 69 elem->nomatch = (flags >> 16) & IPSET_FLAG_NOMATCH; 70 } 71 72 static void 73 hash_net4_data_reset_flags(struct hash_net4_elem *elem, u8 *flags) 74 { 75 swap(*flags, elem->nomatch); 76 } 77 78 static void 79 hash_net4_data_netmask(struct hash_net4_elem *elem, u8 cidr) 80 { 81 elem->ip &= ip_set_netmask(cidr); 82 elem->cidr = cidr; 83 } 84 85 static bool 86 hash_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 97 nla_put_failure: 98 return true; 99 } 100 101 static void 102 hash_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 112 static int 113 hash_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 135 static int 136 hash_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 213 struct hash_net6_elem { 214 union nf_inet_addr ip; 215 u16 padding0; 216 u8 nomatch; 217 u8 cidr; 218 }; 219 220 /* Common functions */ 221 222 static bool 223 hash_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 231 static int 232 hash_net6_do_data_match(const struct hash_net6_elem *elem) 233 { 234 return elem->nomatch ? -ENOTEMPTY : 1; 235 } 236 237 static void 238 hash_net6_data_set_flags(struct hash_net6_elem *elem, u32 flags) 239 { 240 elem->nomatch = (flags >> 16) & IPSET_FLAG_NOMATCH; 241 } 242 243 static void 244 hash_net6_data_reset_flags(struct hash_net6_elem *elem, u8 *flags) 245 { 246 swap(*flags, elem->nomatch); 247 } 248 249 static void 250 hash_net6_data_netmask(struct hash_net6_elem *elem, u8 cidr) 251 { 252 ip6_netmask(&elem->ip, cidr); 253 elem->cidr = cidr; 254 } 255 256 static bool 257 hash_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 268 nla_put_failure: 269 return true; 270 } 271 272 static void 273 hash_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 286 static int 287 hash_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 309 static int 310 hash_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 356 static 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 393 static int __init 394 hash_net_init(void) 395 { 396 return ip_set_type_register(&hash_net_type); 397 } 398 399 static void __exit 400 hash_net_fini(void) 401 { 402 rcu_barrier(); 403 ip_set_type_unregister(&hash_net_type); 404 } 405 406 module_init(hash_net_init); 407 module_exit(hash_net_fini); 408