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 const 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; 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 if (retried) 192 ip = ntohl(h->next.ip); 193 do { 194 e.ip = htonl(ip); 195 ip = ip_set_range_to_cidr(ip, ip_to, &e.cidr); 196 ret = adtfn(set, &e, &ext, &ext, flags); 197 if (ret && !ip_set_eexist(ret, flags)) 198 return ret; 199 200 ret = 0; 201 } while (ip++ < ip_to); 202 return ret; 203 } 204 205 /* IPv6 variant */ 206 207 struct hash_net6_elem { 208 union nf_inet_addr ip; 209 u16 padding0; 210 u8 nomatch; 211 u8 cidr; 212 }; 213 214 /* Common functions */ 215 216 static bool 217 hash_net6_data_equal(const struct hash_net6_elem *ip1, 218 const struct hash_net6_elem *ip2, 219 u32 *multi) 220 { 221 return ipv6_addr_equal(&ip1->ip.in6, &ip2->ip.in6) && 222 ip1->cidr == ip2->cidr; 223 } 224 225 static int 226 hash_net6_do_data_match(const struct hash_net6_elem *elem) 227 { 228 return elem->nomatch ? -ENOTEMPTY : 1; 229 } 230 231 static void 232 hash_net6_data_set_flags(struct hash_net6_elem *elem, u32 flags) 233 { 234 elem->nomatch = (flags >> 16) & IPSET_FLAG_NOMATCH; 235 } 236 237 static void 238 hash_net6_data_reset_flags(struct hash_net6_elem *elem, u8 *flags) 239 { 240 swap(*flags, elem->nomatch); 241 } 242 243 static void 244 hash_net6_data_netmask(struct hash_net6_elem *elem, u8 cidr) 245 { 246 ip6_netmask(&elem->ip, cidr); 247 elem->cidr = cidr; 248 } 249 250 static bool 251 hash_net6_data_list(struct sk_buff *skb, const struct hash_net6_elem *data) 252 { 253 u32 flags = data->nomatch ? IPSET_FLAG_NOMATCH : 0; 254 255 if (nla_put_ipaddr6(skb, IPSET_ATTR_IP, &data->ip.in6) || 256 nla_put_u8(skb, IPSET_ATTR_CIDR, data->cidr) || 257 (flags && 258 nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags)))) 259 goto nla_put_failure; 260 return false; 261 262 nla_put_failure: 263 return true; 264 } 265 266 static void 267 hash_net6_data_next(struct hash_net6_elem *next, 268 const struct hash_net6_elem *d) 269 { 270 } 271 272 #undef MTYPE 273 #undef HOST_MASK 274 275 #define MTYPE hash_net6 276 #define HOST_MASK 128 277 #define IP_SET_EMIT_CREATE 278 #include "ip_set_hash_gen.h" 279 280 static int 281 hash_net6_kadt(struct ip_set *set, const struct sk_buff *skb, 282 const struct xt_action_param *par, 283 enum ipset_adt adt, struct ip_set_adt_opt *opt) 284 { 285 const struct hash_net6 *h = set->data; 286 ipset_adtfn adtfn = set->variant->adt[adt]; 287 struct hash_net6_elem e = { 288 .cidr = INIT_CIDR(h->nets[0].cidr[0], HOST_MASK), 289 }; 290 struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set); 291 292 if (e.cidr == 0) 293 return -EINVAL; 294 if (adt == IPSET_TEST) 295 e.cidr = HOST_MASK; 296 297 ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip.in6); 298 ip6_netmask(&e.ip, e.cidr); 299 300 return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags); 301 } 302 303 static int 304 hash_net6_uadt(struct ip_set *set, struct nlattr *tb[], 305 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried) 306 { 307 ipset_adtfn adtfn = set->variant->adt[adt]; 308 struct hash_net6_elem e = { .cidr = HOST_MASK }; 309 struct ip_set_ext ext = IP_SET_INIT_UEXT(set); 310 int ret; 311 312 if (tb[IPSET_ATTR_LINENO]) 313 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); 314 315 if (unlikely(!tb[IPSET_ATTR_IP] || 316 !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS))) 317 return -IPSET_ERR_PROTOCOL; 318 if (unlikely(tb[IPSET_ATTR_IP_TO])) 319 return -IPSET_ERR_HASH_RANGE_UNSUPPORTED; 320 321 ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &e.ip); 322 if (ret) 323 return ret; 324 325 ret = ip_set_get_extensions(set, tb, &ext); 326 if (ret) 327 return ret; 328 329 if (tb[IPSET_ATTR_CIDR]) { 330 e.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); 331 if (!e.cidr || e.cidr > HOST_MASK) 332 return -IPSET_ERR_INVALID_CIDR; 333 } 334 335 ip6_netmask(&e.ip, e.cidr); 336 337 if (tb[IPSET_ATTR_CADT_FLAGS]) { 338 u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]); 339 340 if (cadt_flags & IPSET_FLAG_NOMATCH) 341 flags |= (IPSET_FLAG_NOMATCH << 16); 342 } 343 344 ret = adtfn(set, &e, &ext, &ext, flags); 345 346 return ip_set_enomatch(ret, flags, adt, set) ? -ret : 347 ip_set_eexist(ret, flags) ? 0 : ret; 348 } 349 350 static struct ip_set_type hash_net_type __read_mostly = { 351 .name = "hash:net", 352 .protocol = IPSET_PROTOCOL, 353 .features = IPSET_TYPE_IP | IPSET_TYPE_NOMATCH, 354 .dimension = IPSET_DIM_ONE, 355 .family = NFPROTO_UNSPEC, 356 .revision_min = IPSET_TYPE_REV_MIN, 357 .revision_max = IPSET_TYPE_REV_MAX, 358 .create_flags[IPSET_TYPE_REV_MAX] = IPSET_CREATE_FLAG_BUCKETSIZE, 359 .create = hash_net_create, 360 .create_policy = { 361 [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, 362 [IPSET_ATTR_MAXELEM] = { .type = NLA_U32 }, 363 [IPSET_ATTR_INITVAL] = { .type = NLA_U32 }, 364 [IPSET_ATTR_BUCKETSIZE] = { .type = NLA_U8 }, 365 [IPSET_ATTR_RESIZE] = { .type = NLA_U8 }, 366 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 367 [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 }, 368 }, 369 .adt_policy = { 370 [IPSET_ATTR_IP] = { .type = NLA_NESTED }, 371 [IPSET_ATTR_IP_TO] = { .type = NLA_NESTED }, 372 [IPSET_ATTR_CIDR] = { .type = NLA_U8 }, 373 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 374 [IPSET_ATTR_LINENO] = { .type = NLA_U32 }, 375 [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 }, 376 [IPSET_ATTR_BYTES] = { .type = NLA_U64 }, 377 [IPSET_ATTR_PACKETS] = { .type = NLA_U64 }, 378 [IPSET_ATTR_COMMENT] = { .type = NLA_NUL_STRING, 379 .len = IPSET_MAX_COMMENT_SIZE }, 380 [IPSET_ATTR_SKBMARK] = { .type = NLA_U64 }, 381 [IPSET_ATTR_SKBPRIO] = { .type = NLA_U32 }, 382 [IPSET_ATTR_SKBQUEUE] = { .type = NLA_U16 }, 383 }, 384 .me = THIS_MODULE, 385 }; 386 387 static int __init 388 hash_net_init(void) 389 { 390 return ip_set_type_register(&hash_net_type); 391 } 392 393 static void __exit 394 hash_net_fini(void) 395 { 396 rcu_barrier(); 397 ip_set_type_unregister(&hash_net_type); 398 } 399 400 module_init(hash_net_init); 401 module_exit(hash_net_fini); 402