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, ipn; 186 u64 n = 0, m = 0; 187 bool with_ports = false; 188 int ret; 189 190 if (tb[IPSET_ATTR_LINENO]) 191 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); 192 193 hash_netportnet4_init(&e); 194 if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] || 195 !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || 196 !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) || 197 !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS))) 198 return -IPSET_ERR_PROTOCOL; 199 200 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip); 201 if (ret) 202 return ret; 203 204 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP2], &ip2_from); 205 if (ret) 206 return ret; 207 208 ret = ip_set_get_extensions(set, tb, &ext); 209 if (ret) 210 return ret; 211 212 if (tb[IPSET_ATTR_CIDR]) { 213 e.cidr[0] = nla_get_u8(tb[IPSET_ATTR_CIDR]); 214 if (e.cidr[0] > HOST_MASK) 215 return -IPSET_ERR_INVALID_CIDR; 216 } 217 218 if (tb[IPSET_ATTR_CIDR2]) { 219 e.cidr[1] = nla_get_u8(tb[IPSET_ATTR_CIDR2]); 220 if (e.cidr[1] > HOST_MASK) 221 return -IPSET_ERR_INVALID_CIDR; 222 } 223 224 e.port = nla_get_be16(tb[IPSET_ATTR_PORT]); 225 226 if (tb[IPSET_ATTR_PROTO]) { 227 e.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); 228 with_ports = ip_set_proto_with_ports(e.proto); 229 230 if (e.proto == 0) 231 return -IPSET_ERR_INVALID_PROTO; 232 } else { 233 return -IPSET_ERR_MISSING_PROTO; 234 } 235 236 if (!(with_ports || e.proto == IPPROTO_ICMP)) 237 e.port = 0; 238 239 if (tb[IPSET_ATTR_CADT_FLAGS]) { 240 u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]); 241 242 if (cadt_flags & IPSET_FLAG_NOMATCH) 243 flags |= (IPSET_FLAG_NOMATCH << 16); 244 } 245 246 with_ports = with_ports && tb[IPSET_ATTR_PORT_TO]; 247 if (adt == IPSET_TEST || 248 !(tb[IPSET_ATTR_IP_TO] || with_ports || tb[IPSET_ATTR_IP2_TO])) { 249 e.ip[0] = htonl(ip & ip_set_hostmask(e.cidr[0])); 250 e.ip[1] = htonl(ip2_from & ip_set_hostmask(e.cidr[1])); 251 ret = adtfn(set, &e, &ext, &ext, flags); 252 return ip_set_enomatch(ret, flags, adt, set) ? -ret : 253 ip_set_eexist(ret, flags) ? 0 : ret; 254 } 255 256 ip_to = ip; 257 if (tb[IPSET_ATTR_IP_TO]) { 258 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to); 259 if (ret) 260 return ret; 261 if (ip > ip_to) 262 swap(ip, ip_to); 263 if (unlikely(ip + UINT_MAX == ip_to)) 264 return -IPSET_ERR_HASH_RANGE; 265 } else { 266 ip_set_mask_from_to(ip, ip_to, e.cidr[0]); 267 } 268 269 port_to = port = ntohs(e.port); 270 if (tb[IPSET_ATTR_PORT_TO]) { 271 port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]); 272 if (port > port_to) 273 swap(port, port_to); 274 } 275 276 ip2_to = ip2_from; 277 if (tb[IPSET_ATTR_IP2_TO]) { 278 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP2_TO], &ip2_to); 279 if (ret) 280 return ret; 281 if (ip2_from > ip2_to) 282 swap(ip2_from, ip2_to); 283 if (unlikely(ip2_from + UINT_MAX == ip2_to)) 284 return -IPSET_ERR_HASH_RANGE; 285 } else { 286 ip_set_mask_from_to(ip2_from, ip2_to, e.cidr[1]); 287 } 288 ipn = ip; 289 do { 290 ipn = ip_set_range_to_cidr(ipn, ip_to, &e.cidr[0]); 291 n++; 292 } while (ipn++ < ip_to); 293 ipn = ip2_from; 294 do { 295 ipn = ip_set_range_to_cidr(ipn, ip2_to, &e.cidr[1]); 296 m++; 297 } while (ipn++ < ip2_to); 298 299 if (n*m*(port_to - port + 1) > IPSET_MAX_RANGE) 300 return -ERANGE; 301 302 if (retried) { 303 ip = ntohl(h->next.ip[0]); 304 p = ntohs(h->next.port); 305 ip2 = ntohl(h->next.ip[1]); 306 } else { 307 p = port; 308 ip2 = ip2_from; 309 } 310 311 do { 312 e.ip[0] = htonl(ip); 313 ip = ip_set_range_to_cidr(ip, ip_to, &e.cidr[0]); 314 for (; p <= port_to; p++) { 315 e.port = htons(p); 316 do { 317 e.ip[1] = htonl(ip2); 318 ip2 = ip_set_range_to_cidr(ip2, ip2_to, 319 &e.cidr[1]); 320 ret = adtfn(set, &e, &ext, &ext, flags); 321 if (ret && !ip_set_eexist(ret, flags)) 322 return ret; 323 324 ret = 0; 325 } while (ip2++ < ip2_to); 326 ip2 = ip2_from; 327 } 328 p = port; 329 } while (ip++ < ip_to); 330 return ret; 331 } 332 333 /* IPv6 variant */ 334 335 struct hash_netportnet6_elem { 336 union nf_inet_addr ip[2]; 337 __be16 port; 338 union { 339 u8 cidr[2]; 340 u16 ccmp; 341 }; 342 u16 padding; 343 u8 nomatch; 344 u8 proto; 345 }; 346 347 /* Common functions */ 348 349 static bool 350 hash_netportnet6_data_equal(const struct hash_netportnet6_elem *ip1, 351 const struct hash_netportnet6_elem *ip2, 352 u32 *multi) 353 { 354 return ipv6_addr_equal(&ip1->ip[0].in6, &ip2->ip[0].in6) && 355 ipv6_addr_equal(&ip1->ip[1].in6, &ip2->ip[1].in6) && 356 ip1->ccmp == ip2->ccmp && 357 ip1->port == ip2->port && 358 ip1->proto == ip2->proto; 359 } 360 361 static int 362 hash_netportnet6_do_data_match(const struct hash_netportnet6_elem *elem) 363 { 364 return elem->nomatch ? -ENOTEMPTY : 1; 365 } 366 367 static void 368 hash_netportnet6_data_set_flags(struct hash_netportnet6_elem *elem, u32 flags) 369 { 370 elem->nomatch = !!((flags >> 16) & IPSET_FLAG_NOMATCH); 371 } 372 373 static void 374 hash_netportnet6_data_reset_flags(struct hash_netportnet6_elem *elem, u8 *flags) 375 { 376 swap(*flags, elem->nomatch); 377 } 378 379 static void 380 hash_netportnet6_data_reset_elem(struct hash_netportnet6_elem *elem, 381 struct hash_netportnet6_elem *orig) 382 { 383 elem->ip[1] = orig->ip[1]; 384 } 385 386 static void 387 hash_netportnet6_data_netmask(struct hash_netportnet6_elem *elem, 388 u8 cidr, bool inner) 389 { 390 if (inner) { 391 ip6_netmask(&elem->ip[1], cidr); 392 elem->cidr[1] = cidr; 393 } else { 394 ip6_netmask(&elem->ip[0], cidr); 395 elem->cidr[0] = cidr; 396 } 397 } 398 399 static bool 400 hash_netportnet6_data_list(struct sk_buff *skb, 401 const struct hash_netportnet6_elem *data) 402 { 403 u32 flags = data->nomatch ? IPSET_FLAG_NOMATCH : 0; 404 405 if (nla_put_ipaddr6(skb, IPSET_ATTR_IP, &data->ip[0].in6) || 406 nla_put_ipaddr6(skb, IPSET_ATTR_IP2, &data->ip[1].in6) || 407 nla_put_net16(skb, IPSET_ATTR_PORT, data->port) || 408 nla_put_u8(skb, IPSET_ATTR_CIDR, data->cidr[0]) || 409 nla_put_u8(skb, IPSET_ATTR_CIDR2, data->cidr[1]) || 410 nla_put_u8(skb, IPSET_ATTR_PROTO, data->proto) || 411 (flags && 412 nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags)))) 413 goto nla_put_failure; 414 return false; 415 416 nla_put_failure: 417 return true; 418 } 419 420 static void 421 hash_netportnet6_data_next(struct hash_netportnet6_elem *next, 422 const struct hash_netportnet6_elem *d) 423 { 424 next->port = d->port; 425 } 426 427 #undef MTYPE 428 #undef HOST_MASK 429 430 #define MTYPE hash_netportnet6 431 #define HOST_MASK 128 432 #define IP_SET_EMIT_CREATE 433 #include "ip_set_hash_gen.h" 434 435 static void 436 hash_netportnet6_init(struct hash_netportnet6_elem *e) 437 { 438 e->cidr[0] = HOST_MASK; 439 e->cidr[1] = HOST_MASK; 440 } 441 442 static int 443 hash_netportnet6_kadt(struct ip_set *set, const struct sk_buff *skb, 444 const struct xt_action_param *par, 445 enum ipset_adt adt, struct ip_set_adt_opt *opt) 446 { 447 const struct hash_netportnet6 *h = set->data; 448 ipset_adtfn adtfn = set->variant->adt[adt]; 449 struct hash_netportnet6_elem e = { }; 450 struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set); 451 452 e.cidr[0] = INIT_CIDR(h->nets[0].cidr[0], HOST_MASK); 453 e.cidr[1] = INIT_CIDR(h->nets[0].cidr[1], HOST_MASK); 454 if (adt == IPSET_TEST) 455 e.ccmp = (HOST_MASK << (sizeof(u8) * 8)) | HOST_MASK; 456 457 if (!ip_set_get_ip6_port(skb, opt->flags & IPSET_DIM_TWO_SRC, 458 &e.port, &e.proto)) 459 return -EINVAL; 460 461 ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip[0].in6); 462 ip6addrptr(skb, opt->flags & IPSET_DIM_THREE_SRC, &e.ip[1].in6); 463 ip6_netmask(&e.ip[0], e.cidr[0]); 464 ip6_netmask(&e.ip[1], e.cidr[1]); 465 466 return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags); 467 } 468 469 static int 470 hash_netportnet6_uadt(struct ip_set *set, struct nlattr *tb[], 471 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried) 472 { 473 const struct hash_netportnet6 *h = set->data; 474 ipset_adtfn adtfn = set->variant->adt[adt]; 475 struct hash_netportnet6_elem e = { }; 476 struct ip_set_ext ext = IP_SET_INIT_UEXT(set); 477 u32 port, port_to; 478 bool with_ports = false; 479 int ret; 480 481 if (tb[IPSET_ATTR_LINENO]) 482 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); 483 484 hash_netportnet6_init(&e); 485 if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] || 486 !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || 487 !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) || 488 !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS))) 489 return -IPSET_ERR_PROTOCOL; 490 if (unlikely(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_IP2_TO])) 491 return -IPSET_ERR_HASH_RANGE_UNSUPPORTED; 492 493 ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &e.ip[0]); 494 if (ret) 495 return ret; 496 497 ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP2], &e.ip[1]); 498 if (ret) 499 return ret; 500 501 ret = ip_set_get_extensions(set, tb, &ext); 502 if (ret) 503 return ret; 504 505 if (tb[IPSET_ATTR_CIDR]) { 506 e.cidr[0] = nla_get_u8(tb[IPSET_ATTR_CIDR]); 507 if (e.cidr[0] > HOST_MASK) 508 return -IPSET_ERR_INVALID_CIDR; 509 } 510 511 if (tb[IPSET_ATTR_CIDR2]) { 512 e.cidr[1] = nla_get_u8(tb[IPSET_ATTR_CIDR2]); 513 if (e.cidr[1] > HOST_MASK) 514 return -IPSET_ERR_INVALID_CIDR; 515 } 516 517 ip6_netmask(&e.ip[0], e.cidr[0]); 518 ip6_netmask(&e.ip[1], e.cidr[1]); 519 520 e.port = nla_get_be16(tb[IPSET_ATTR_PORT]); 521 522 if (tb[IPSET_ATTR_PROTO]) { 523 e.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); 524 with_ports = ip_set_proto_with_ports(e.proto); 525 526 if (e.proto == 0) 527 return -IPSET_ERR_INVALID_PROTO; 528 } else { 529 return -IPSET_ERR_MISSING_PROTO; 530 } 531 532 if (!(with_ports || e.proto == IPPROTO_ICMPV6)) 533 e.port = 0; 534 535 if (tb[IPSET_ATTR_CADT_FLAGS]) { 536 u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]); 537 538 if (cadt_flags & IPSET_FLAG_NOMATCH) 539 flags |= (IPSET_FLAG_NOMATCH << 16); 540 } 541 542 if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) { 543 ret = adtfn(set, &e, &ext, &ext, flags); 544 return ip_set_enomatch(ret, flags, adt, set) ? -ret : 545 ip_set_eexist(ret, flags) ? 0 : ret; 546 } 547 548 port = ntohs(e.port); 549 port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]); 550 if (port > port_to) 551 swap(port, port_to); 552 553 if (retried) 554 port = ntohs(h->next.port); 555 for (; port <= port_to; port++) { 556 e.port = htons(port); 557 ret = adtfn(set, &e, &ext, &ext, flags); 558 559 if (ret && !ip_set_eexist(ret, flags)) 560 return ret; 561 562 ret = 0; 563 } 564 return ret; 565 } 566 567 static struct ip_set_type hash_netportnet_type __read_mostly = { 568 .name = "hash:net,port,net", 569 .protocol = IPSET_PROTOCOL, 570 .features = IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_TYPE_IP2 | 571 IPSET_TYPE_NOMATCH, 572 .dimension = IPSET_DIM_THREE, 573 .family = NFPROTO_UNSPEC, 574 .revision_min = IPSET_TYPE_REV_MIN, 575 .revision_max = IPSET_TYPE_REV_MAX, 576 .create_flags[IPSET_TYPE_REV_MAX] = IPSET_CREATE_FLAG_BUCKETSIZE, 577 .create = hash_netportnet_create, 578 .create_policy = { 579 [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, 580 [IPSET_ATTR_MAXELEM] = { .type = NLA_U32 }, 581 [IPSET_ATTR_INITVAL] = { .type = NLA_U32 }, 582 [IPSET_ATTR_BUCKETSIZE] = { .type = NLA_U8 }, 583 [IPSET_ATTR_RESIZE] = { .type = NLA_U8 }, 584 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 585 [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 }, 586 }, 587 .adt_policy = { 588 [IPSET_ATTR_IP] = { .type = NLA_NESTED }, 589 [IPSET_ATTR_IP_TO] = { .type = NLA_NESTED }, 590 [IPSET_ATTR_IP2] = { .type = NLA_NESTED }, 591 [IPSET_ATTR_IP2_TO] = { .type = NLA_NESTED }, 592 [IPSET_ATTR_PORT] = { .type = NLA_U16 }, 593 [IPSET_ATTR_PORT_TO] = { .type = NLA_U16 }, 594 [IPSET_ATTR_CIDR] = { .type = NLA_U8 }, 595 [IPSET_ATTR_CIDR2] = { .type = NLA_U8 }, 596 [IPSET_ATTR_PROTO] = { .type = NLA_U8 }, 597 [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 }, 598 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 599 [IPSET_ATTR_LINENO] = { .type = NLA_U32 }, 600 [IPSET_ATTR_BYTES] = { .type = NLA_U64 }, 601 [IPSET_ATTR_PACKETS] = { .type = NLA_U64 }, 602 [IPSET_ATTR_COMMENT] = { .type = NLA_NUL_STRING, 603 .len = IPSET_MAX_COMMENT_SIZE }, 604 [IPSET_ATTR_SKBMARK] = { .type = NLA_U64 }, 605 [IPSET_ATTR_SKBPRIO] = { .type = NLA_U32 }, 606 [IPSET_ATTR_SKBQUEUE] = { .type = NLA_U16 }, 607 }, 608 .me = THIS_MODULE, 609 }; 610 611 static int __init 612 hash_netportnet_init(void) 613 { 614 return ip_set_type_register(&hash_netportnet_type); 615 } 616 617 static void __exit 618 hash_netportnet_fini(void) 619 { 620 rcu_barrier(); 621 ip_set_type_unregister(&hash_netportnet_type); 622 } 623 624 module_init(hash_netportnet_init); 625 module_exit(hash_netportnet_fini); 626