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:ip,port,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 #include <net/tcp.h> 16 17 #include <linux/netfilter.h> 18 #include <linux/netfilter/ipset/pfxlen.h> 19 #include <linux/netfilter/ipset/ip_set.h> 20 #include <linux/netfilter/ipset/ip_set_getport.h> 21 #include <linux/netfilter/ipset/ip_set_hash.h> 22 23 #define IPSET_TYPE_REV_MIN 0 24 /* 0 Comments support added */ 25 /* 1 Forceadd support added */ 26 /* 2 skbinfo support added */ 27 #define IPSET_TYPE_REV_MAX 3 /* bucketsize, initval support added */ 28 29 MODULE_LICENSE("GPL"); 30 MODULE_AUTHOR("Oliver Smith <oliver@8.c.9.b.0.7.4.0.1.0.0.2.ip6.arpa>"); 31 IP_SET_MODULE_DESC("hash:net,port,net", IPSET_TYPE_REV_MIN, IPSET_TYPE_REV_MAX); 32 MODULE_ALIAS("ip_set_hash:net,port,net"); 33 34 /* Type specific function prefix */ 35 #define HTYPE hash_netportnet 36 #define IP_SET_HASH_WITH_PROTO 37 #define IP_SET_HASH_WITH_NETS 38 #define IPSET_NET_COUNT 2 39 40 /* IPv4 variant */ 41 42 /* Member elements */ 43 struct hash_netportnet4_elem { 44 union { 45 __be32 ip[2]; 46 __be64 ipcmp; 47 }; 48 __be16 port; 49 union { 50 u8 cidr[2]; 51 u16 ccmp; 52 }; 53 u16 padding; 54 u8 nomatch; 55 u8 proto; 56 }; 57 58 /* Common functions */ 59 60 static bool 61 hash_netportnet4_data_equal(const struct hash_netportnet4_elem *ip1, 62 const struct hash_netportnet4_elem *ip2, 63 u32 *multi) 64 { 65 return ip1->ipcmp == ip2->ipcmp && 66 ip1->ccmp == ip2->ccmp && 67 ip1->port == ip2->port && 68 ip1->proto == ip2->proto; 69 } 70 71 static int 72 hash_netportnet4_do_data_match(const struct hash_netportnet4_elem *elem) 73 { 74 return elem->nomatch ? -ENOTEMPTY : 1; 75 } 76 77 static void 78 hash_netportnet4_data_set_flags(struct hash_netportnet4_elem *elem, u32 flags) 79 { 80 elem->nomatch = !!((flags >> 16) & IPSET_FLAG_NOMATCH); 81 } 82 83 static void 84 hash_netportnet4_data_reset_flags(struct hash_netportnet4_elem *elem, u8 *flags) 85 { 86 swap(*flags, elem->nomatch); 87 } 88 89 static void 90 hash_netportnet4_data_reset_elem(struct hash_netportnet4_elem *elem, 91 struct hash_netportnet4_elem *orig) 92 { 93 elem->ip[1] = orig->ip[1]; 94 } 95 96 static void 97 hash_netportnet4_data_netmask(struct hash_netportnet4_elem *elem, 98 u8 cidr, bool inner) 99 { 100 if (inner) { 101 elem->ip[1] &= ip_set_netmask(cidr); 102 elem->cidr[1] = cidr; 103 } else { 104 elem->ip[0] &= ip_set_netmask(cidr); 105 elem->cidr[0] = cidr; 106 } 107 } 108 109 static bool 110 hash_netportnet4_data_list(struct sk_buff *skb, 111 const struct hash_netportnet4_elem *data) 112 { 113 u32 flags = data->nomatch ? IPSET_FLAG_NOMATCH : 0; 114 115 if (nla_put_ipaddr4(skb, IPSET_ATTR_IP, data->ip[0]) || 116 nla_put_ipaddr4(skb, IPSET_ATTR_IP2, data->ip[1]) || 117 nla_put_net16(skb, IPSET_ATTR_PORT, data->port) || 118 nla_put_u8(skb, IPSET_ATTR_CIDR, data->cidr[0]) || 119 nla_put_u8(skb, IPSET_ATTR_CIDR2, data->cidr[1]) || 120 nla_put_u8(skb, IPSET_ATTR_PROTO, data->proto) || 121 (flags && 122 nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags)))) 123 goto nla_put_failure; 124 return false; 125 126 nla_put_failure: 127 return true; 128 } 129 130 static void 131 hash_netportnet4_data_next(struct hash_netportnet4_elem *next, 132 const struct hash_netportnet4_elem *d) 133 { 134 next->ipcmp = d->ipcmp; 135 next->port = d->port; 136 } 137 138 #define MTYPE hash_netportnet4 139 #define HOST_MASK 32 140 #include "ip_set_hash_gen.h" 141 142 static void 143 hash_netportnet4_init(struct hash_netportnet4_elem *e) 144 { 145 e->cidr[0] = HOST_MASK; 146 e->cidr[1] = HOST_MASK; 147 } 148 149 static int 150 hash_netportnet4_kadt(struct ip_set *set, const struct sk_buff *skb, 151 const struct xt_action_param *par, 152 enum ipset_adt adt, struct ip_set_adt_opt *opt) 153 { 154 const struct hash_netportnet4 *h = set->data; 155 ipset_adtfn adtfn = set->variant->adt[adt]; 156 struct hash_netportnet4_elem e = { }; 157 struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set); 158 159 e.cidr[0] = INIT_CIDR(h->nets[0].cidr[0], HOST_MASK); 160 e.cidr[1] = INIT_CIDR(h->nets[0].cidr[1], HOST_MASK); 161 if (adt == IPSET_TEST) 162 e.ccmp = (HOST_MASK << (sizeof(e.cidr[0]) * 8)) | HOST_MASK; 163 164 if (!ip_set_get_ip4_port(skb, opt->flags & IPSET_DIM_TWO_SRC, 165 &e.port, &e.proto)) 166 return -EINVAL; 167 168 ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip[0]); 169 ip4addrptr(skb, opt->flags & IPSET_DIM_THREE_SRC, &e.ip[1]); 170 e.ip[0] &= ip_set_netmask(e.cidr[0]); 171 e.ip[1] &= ip_set_netmask(e.cidr[1]); 172 173 return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags); 174 } 175 176 static int 177 hash_netportnet4_uadt(struct ip_set *set, struct nlattr *tb[], 178 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried) 179 { 180 const struct hash_netportnet4 *h = set->data; 181 ipset_adtfn adtfn = set->variant->adt[adt]; 182 struct hash_netportnet4_elem e = { }; 183 struct ip_set_ext ext = IP_SET_INIT_UEXT(set); 184 u32 ip = 0, ip_to = 0, p = 0, port, port_to; 185 u32 ip2_from = 0, ip2_to = 0, ip2; 186 bool with_ports = false; 187 int ret; 188 189 if (tb[IPSET_ATTR_LINENO]) 190 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); 191 192 hash_netportnet4_init(&e); 193 if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] || 194 !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || 195 !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) || 196 !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS))) 197 return -IPSET_ERR_PROTOCOL; 198 199 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip); 200 if (ret) 201 return ret; 202 203 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP2], &ip2_from); 204 if (ret) 205 return ret; 206 207 ret = ip_set_get_extensions(set, tb, &ext); 208 if (ret) 209 return ret; 210 211 if (tb[IPSET_ATTR_CIDR]) { 212 e.cidr[0] = nla_get_u8(tb[IPSET_ATTR_CIDR]); 213 if (e.cidr[0] > HOST_MASK) 214 return -IPSET_ERR_INVALID_CIDR; 215 } 216 217 if (tb[IPSET_ATTR_CIDR2]) { 218 e.cidr[1] = nla_get_u8(tb[IPSET_ATTR_CIDR2]); 219 if (e.cidr[1] > HOST_MASK) 220 return -IPSET_ERR_INVALID_CIDR; 221 } 222 223 e.port = nla_get_be16(tb[IPSET_ATTR_PORT]); 224 225 if (tb[IPSET_ATTR_PROTO]) { 226 e.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); 227 with_ports = ip_set_proto_with_ports(e.proto); 228 229 if (e.proto == 0) 230 return -IPSET_ERR_INVALID_PROTO; 231 } else { 232 return -IPSET_ERR_MISSING_PROTO; 233 } 234 235 if (!(with_ports || e.proto == IPPROTO_ICMP)) 236 e.port = 0; 237 238 if (tb[IPSET_ATTR_CADT_FLAGS]) { 239 u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]); 240 241 if (cadt_flags & IPSET_FLAG_NOMATCH) 242 flags |= (IPSET_FLAG_NOMATCH << 16); 243 } 244 245 with_ports = with_ports && tb[IPSET_ATTR_PORT_TO]; 246 if (adt == IPSET_TEST || 247 !(tb[IPSET_ATTR_IP_TO] || with_ports || tb[IPSET_ATTR_IP2_TO])) { 248 e.ip[0] = htonl(ip & ip_set_hostmask(e.cidr[0])); 249 e.ip[1] = htonl(ip2_from & ip_set_hostmask(e.cidr[1])); 250 ret = adtfn(set, &e, &ext, &ext, flags); 251 return ip_set_enomatch(ret, flags, adt, set) ? -ret : 252 ip_set_eexist(ret, flags) ? 0 : ret; 253 } 254 255 ip_to = ip; 256 if (tb[IPSET_ATTR_IP_TO]) { 257 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to); 258 if (ret) 259 return ret; 260 if (ip > ip_to) 261 swap(ip, ip_to); 262 if (unlikely(ip + UINT_MAX == ip_to)) 263 return -IPSET_ERR_HASH_RANGE; 264 } else { 265 ip_set_mask_from_to(ip, ip_to, e.cidr[0]); 266 } 267 268 port_to = port = ntohs(e.port); 269 if (tb[IPSET_ATTR_PORT_TO]) { 270 port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]); 271 if (port > port_to) 272 swap(port, port_to); 273 } 274 275 ip2_to = ip2_from; 276 if (tb[IPSET_ATTR_IP2_TO]) { 277 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP2_TO], &ip2_to); 278 if (ret) 279 return ret; 280 if (ip2_from > ip2_to) 281 swap(ip2_from, ip2_to); 282 if (unlikely(ip2_from + UINT_MAX == ip2_to)) 283 return -IPSET_ERR_HASH_RANGE; 284 } else { 285 ip_set_mask_from_to(ip2_from, ip2_to, e.cidr[1]); 286 } 287 288 if (retried) { 289 ip = ntohl(h->next.ip[0]); 290 p = ntohs(h->next.port); 291 ip2 = ntohl(h->next.ip[1]); 292 } else { 293 p = port; 294 ip2 = ip2_from; 295 } 296 297 do { 298 e.ip[0] = htonl(ip); 299 ip = ip_set_range_to_cidr(ip, ip_to, &e.cidr[0]); 300 for (; p <= port_to; p++) { 301 e.port = htons(p); 302 do { 303 e.ip[1] = htonl(ip2); 304 ip2 = ip_set_range_to_cidr(ip2, ip2_to, 305 &e.cidr[1]); 306 ret = adtfn(set, &e, &ext, &ext, flags); 307 if (ret && !ip_set_eexist(ret, flags)) 308 return ret; 309 310 ret = 0; 311 } while (ip2++ < ip2_to); 312 ip2 = ip2_from; 313 } 314 p = port; 315 } while (ip++ < ip_to); 316 return ret; 317 } 318 319 /* IPv6 variant */ 320 321 struct hash_netportnet6_elem { 322 union nf_inet_addr ip[2]; 323 __be16 port; 324 union { 325 u8 cidr[2]; 326 u16 ccmp; 327 }; 328 u16 padding; 329 u8 nomatch; 330 u8 proto; 331 }; 332 333 /* Common functions */ 334 335 static bool 336 hash_netportnet6_data_equal(const struct hash_netportnet6_elem *ip1, 337 const struct hash_netportnet6_elem *ip2, 338 u32 *multi) 339 { 340 return ipv6_addr_equal(&ip1->ip[0].in6, &ip2->ip[0].in6) && 341 ipv6_addr_equal(&ip1->ip[1].in6, &ip2->ip[1].in6) && 342 ip1->ccmp == ip2->ccmp && 343 ip1->port == ip2->port && 344 ip1->proto == ip2->proto; 345 } 346 347 static int 348 hash_netportnet6_do_data_match(const struct hash_netportnet6_elem *elem) 349 { 350 return elem->nomatch ? -ENOTEMPTY : 1; 351 } 352 353 static void 354 hash_netportnet6_data_set_flags(struct hash_netportnet6_elem *elem, u32 flags) 355 { 356 elem->nomatch = !!((flags >> 16) & IPSET_FLAG_NOMATCH); 357 } 358 359 static void 360 hash_netportnet6_data_reset_flags(struct hash_netportnet6_elem *elem, u8 *flags) 361 { 362 swap(*flags, elem->nomatch); 363 } 364 365 static void 366 hash_netportnet6_data_reset_elem(struct hash_netportnet6_elem *elem, 367 struct hash_netportnet6_elem *orig) 368 { 369 elem->ip[1] = orig->ip[1]; 370 } 371 372 static void 373 hash_netportnet6_data_netmask(struct hash_netportnet6_elem *elem, 374 u8 cidr, bool inner) 375 { 376 if (inner) { 377 ip6_netmask(&elem->ip[1], cidr); 378 elem->cidr[1] = cidr; 379 } else { 380 ip6_netmask(&elem->ip[0], cidr); 381 elem->cidr[0] = cidr; 382 } 383 } 384 385 static bool 386 hash_netportnet6_data_list(struct sk_buff *skb, 387 const struct hash_netportnet6_elem *data) 388 { 389 u32 flags = data->nomatch ? IPSET_FLAG_NOMATCH : 0; 390 391 if (nla_put_ipaddr6(skb, IPSET_ATTR_IP, &data->ip[0].in6) || 392 nla_put_ipaddr6(skb, IPSET_ATTR_IP2, &data->ip[1].in6) || 393 nla_put_net16(skb, IPSET_ATTR_PORT, data->port) || 394 nla_put_u8(skb, IPSET_ATTR_CIDR, data->cidr[0]) || 395 nla_put_u8(skb, IPSET_ATTR_CIDR2, data->cidr[1]) || 396 nla_put_u8(skb, IPSET_ATTR_PROTO, data->proto) || 397 (flags && 398 nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags)))) 399 goto nla_put_failure; 400 return false; 401 402 nla_put_failure: 403 return true; 404 } 405 406 static void 407 hash_netportnet6_data_next(struct hash_netportnet6_elem *next, 408 const struct hash_netportnet6_elem *d) 409 { 410 next->port = d->port; 411 } 412 413 #undef MTYPE 414 #undef HOST_MASK 415 416 #define MTYPE hash_netportnet6 417 #define HOST_MASK 128 418 #define IP_SET_EMIT_CREATE 419 #include "ip_set_hash_gen.h" 420 421 static void 422 hash_netportnet6_init(struct hash_netportnet6_elem *e) 423 { 424 e->cidr[0] = HOST_MASK; 425 e->cidr[1] = HOST_MASK; 426 } 427 428 static int 429 hash_netportnet6_kadt(struct ip_set *set, const struct sk_buff *skb, 430 const struct xt_action_param *par, 431 enum ipset_adt adt, struct ip_set_adt_opt *opt) 432 { 433 const struct hash_netportnet6 *h = set->data; 434 ipset_adtfn adtfn = set->variant->adt[adt]; 435 struct hash_netportnet6_elem e = { }; 436 struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set); 437 438 e.cidr[0] = INIT_CIDR(h->nets[0].cidr[0], HOST_MASK); 439 e.cidr[1] = INIT_CIDR(h->nets[0].cidr[1], HOST_MASK); 440 if (adt == IPSET_TEST) 441 e.ccmp = (HOST_MASK << (sizeof(u8) * 8)) | HOST_MASK; 442 443 if (!ip_set_get_ip6_port(skb, opt->flags & IPSET_DIM_TWO_SRC, 444 &e.port, &e.proto)) 445 return -EINVAL; 446 447 ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip[0].in6); 448 ip6addrptr(skb, opt->flags & IPSET_DIM_THREE_SRC, &e.ip[1].in6); 449 ip6_netmask(&e.ip[0], e.cidr[0]); 450 ip6_netmask(&e.ip[1], e.cidr[1]); 451 452 return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags); 453 } 454 455 static int 456 hash_netportnet6_uadt(struct ip_set *set, struct nlattr *tb[], 457 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried) 458 { 459 const struct hash_netportnet6 *h = set->data; 460 ipset_adtfn adtfn = set->variant->adt[adt]; 461 struct hash_netportnet6_elem e = { }; 462 struct ip_set_ext ext = IP_SET_INIT_UEXT(set); 463 u32 port, port_to; 464 bool with_ports = false; 465 int ret; 466 467 if (tb[IPSET_ATTR_LINENO]) 468 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); 469 470 hash_netportnet6_init(&e); 471 if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] || 472 !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || 473 !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) || 474 !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS))) 475 return -IPSET_ERR_PROTOCOL; 476 if (unlikely(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_IP2_TO])) 477 return -IPSET_ERR_HASH_RANGE_UNSUPPORTED; 478 479 ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &e.ip[0]); 480 if (ret) 481 return ret; 482 483 ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP2], &e.ip[1]); 484 if (ret) 485 return ret; 486 487 ret = ip_set_get_extensions(set, tb, &ext); 488 if (ret) 489 return ret; 490 491 if (tb[IPSET_ATTR_CIDR]) { 492 e.cidr[0] = nla_get_u8(tb[IPSET_ATTR_CIDR]); 493 if (e.cidr[0] > HOST_MASK) 494 return -IPSET_ERR_INVALID_CIDR; 495 } 496 497 if (tb[IPSET_ATTR_CIDR2]) { 498 e.cidr[1] = nla_get_u8(tb[IPSET_ATTR_CIDR2]); 499 if (e.cidr[1] > HOST_MASK) 500 return -IPSET_ERR_INVALID_CIDR; 501 } 502 503 ip6_netmask(&e.ip[0], e.cidr[0]); 504 ip6_netmask(&e.ip[1], e.cidr[1]); 505 506 e.port = nla_get_be16(tb[IPSET_ATTR_PORT]); 507 508 if (tb[IPSET_ATTR_PROTO]) { 509 e.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); 510 with_ports = ip_set_proto_with_ports(e.proto); 511 512 if (e.proto == 0) 513 return -IPSET_ERR_INVALID_PROTO; 514 } else { 515 return -IPSET_ERR_MISSING_PROTO; 516 } 517 518 if (!(with_ports || e.proto == IPPROTO_ICMPV6)) 519 e.port = 0; 520 521 if (tb[IPSET_ATTR_CADT_FLAGS]) { 522 u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]); 523 524 if (cadt_flags & IPSET_FLAG_NOMATCH) 525 flags |= (IPSET_FLAG_NOMATCH << 16); 526 } 527 528 if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) { 529 ret = adtfn(set, &e, &ext, &ext, flags); 530 return ip_set_enomatch(ret, flags, adt, set) ? -ret : 531 ip_set_eexist(ret, flags) ? 0 : ret; 532 } 533 534 port = ntohs(e.port); 535 port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]); 536 if (port > port_to) 537 swap(port, port_to); 538 539 if (retried) 540 port = ntohs(h->next.port); 541 for (; port <= port_to; port++) { 542 e.port = htons(port); 543 ret = adtfn(set, &e, &ext, &ext, flags); 544 545 if (ret && !ip_set_eexist(ret, flags)) 546 return ret; 547 548 ret = 0; 549 } 550 return ret; 551 } 552 553 static struct ip_set_type hash_netportnet_type __read_mostly = { 554 .name = "hash:net,port,net", 555 .protocol = IPSET_PROTOCOL, 556 .features = IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_TYPE_IP2 | 557 IPSET_TYPE_NOMATCH, 558 .dimension = IPSET_DIM_THREE, 559 .family = NFPROTO_UNSPEC, 560 .revision_min = IPSET_TYPE_REV_MIN, 561 .revision_max = IPSET_TYPE_REV_MAX, 562 .create_flags[IPSET_TYPE_REV_MAX] = IPSET_CREATE_FLAG_BUCKETSIZE, 563 .create = hash_netportnet_create, 564 .create_policy = { 565 [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, 566 [IPSET_ATTR_MAXELEM] = { .type = NLA_U32 }, 567 [IPSET_ATTR_INITVAL] = { .type = NLA_U32 }, 568 [IPSET_ATTR_BUCKETSIZE] = { .type = NLA_U8 }, 569 [IPSET_ATTR_RESIZE] = { .type = NLA_U8 }, 570 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 571 [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 }, 572 }, 573 .adt_policy = { 574 [IPSET_ATTR_IP] = { .type = NLA_NESTED }, 575 [IPSET_ATTR_IP_TO] = { .type = NLA_NESTED }, 576 [IPSET_ATTR_IP2] = { .type = NLA_NESTED }, 577 [IPSET_ATTR_IP2_TO] = { .type = NLA_NESTED }, 578 [IPSET_ATTR_PORT] = { .type = NLA_U16 }, 579 [IPSET_ATTR_PORT_TO] = { .type = NLA_U16 }, 580 [IPSET_ATTR_CIDR] = { .type = NLA_U8 }, 581 [IPSET_ATTR_CIDR2] = { .type = NLA_U8 }, 582 [IPSET_ATTR_PROTO] = { .type = NLA_U8 }, 583 [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 }, 584 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 585 [IPSET_ATTR_LINENO] = { .type = NLA_U32 }, 586 [IPSET_ATTR_BYTES] = { .type = NLA_U64 }, 587 [IPSET_ATTR_PACKETS] = { .type = NLA_U64 }, 588 [IPSET_ATTR_COMMENT] = { .type = NLA_NUL_STRING, 589 .len = IPSET_MAX_COMMENT_SIZE }, 590 [IPSET_ATTR_SKBMARK] = { .type = NLA_U64 }, 591 [IPSET_ATTR_SKBPRIO] = { .type = NLA_U32 }, 592 [IPSET_ATTR_SKBQUEUE] = { .type = NLA_U16 }, 593 }, 594 .me = THIS_MODULE, 595 }; 596 597 static int __init 598 hash_netportnet_init(void) 599 { 600 return ip_set_type_register(&hash_netportnet_type); 601 } 602 603 static void __exit 604 hash_netportnet_fini(void) 605 { 606 rcu_barrier(); 607 ip_set_type_unregister(&hash_netportnet_type); 608 } 609 610 module_init(hash_netportnet_init); 611 module_exit(hash_netportnet_fini); 612