1/* Copyright (C) 2003-2013 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> 2 * 3 * This program is free software; you can redistribute it and/or modify 4 * it under the terms of the GNU General Public License version 2 as 5 * published by the Free Software Foundation. 6 */ 7 8/* Kernel module implementing an IP set type: the hash:ip,port,net type */ 9 10#include <linux/jhash.h> 11#include <linux/module.h> 12#include <linux/ip.h> 13#include <linux/skbuff.h> 14#include <linux/errno.h> 15#include <linux/random.h> 16#include <net/ip.h> 17#include <net/ipv6.h> 18#include <net/netlink.h> 19#include <net/tcp.h> 20 21#include <linux/netfilter.h> 22#include <linux/netfilter/ipset/pfxlen.h> 23#include <linux/netfilter/ipset/ip_set.h> 24#include <linux/netfilter/ipset/ip_set_getport.h> 25#include <linux/netfilter/ipset/ip_set_hash.h> 26 27#define REVISION_MIN 0 28/* 1 SCTP and UDPLITE support added */ 29/* 2 Range as input support for IPv4 added */ 30/* 3 nomatch flag support added */ 31#define REVISION_MAX 4 /* Counters support added */ 32 33MODULE_LICENSE("GPL"); 34MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); 35IP_SET_MODULE_DESC("hash:ip,port,net", REVISION_MIN, REVISION_MAX); 36MODULE_ALIAS("ip_set_hash:ip,port,net"); 37 38/* Type specific function prefix */ 39#define HTYPE hash_ipportnet 40 41/* We squeeze the "nomatch" flag into cidr: we don't support cidr == 0 42 * However this way we have to store internally cidr - 1, 43 * dancing back and forth. 44 */ 45#define IP_SET_HASH_WITH_NETS_PACKED 46#define IP_SET_HASH_WITH_PROTO 47#define IP_SET_HASH_WITH_NETS 48 49/* IPv4 variants */ 50 51/* Member elements */ 52struct hash_ipportnet4_elem { 53 __be32 ip; 54 __be32 ip2; 55 __be16 port; 56 u8 cidr:7; 57 u8 nomatch:1; 58 u8 proto; 59}; 60 61struct hash_ipportnet4t_elem { 62 __be32 ip; 63 __be32 ip2; 64 __be16 port; 65 u8 cidr:7; 66 u8 nomatch:1; 67 u8 proto; 68 unsigned long timeout; 69}; 70 71struct hash_ipportnet4c_elem { 72 __be32 ip; 73 __be32 ip2; 74 __be16 port; 75 u8 cidr:7; 76 u8 nomatch:1; 77 u8 proto; 78 struct ip_set_counter counter; 79}; 80 81struct hash_ipportnet4ct_elem { 82 __be32 ip; 83 __be32 ip2; 84 __be16 port; 85 u8 cidr:7; 86 u8 nomatch:1; 87 u8 proto; 88 struct ip_set_counter counter; 89 unsigned long timeout; 90}; 91 92/* Common functions */ 93 94static inline bool 95hash_ipportnet4_data_equal(const struct hash_ipportnet4_elem *ip1, 96 const struct hash_ipportnet4_elem *ip2, 97 u32 *multi) 98{ 99 return ip1->ip == ip2->ip && 100 ip1->ip2 == ip2->ip2 && 101 ip1->cidr == ip2->cidr && 102 ip1->port == ip2->port && 103 ip1->proto == ip2->proto; 104} 105 106static inline int 107hash_ipportnet4_do_data_match(const struct hash_ipportnet4_elem *elem) 108{ 109 return elem->nomatch ? -ENOTEMPTY : 1; 110} 111 112static inline void 113hash_ipportnet4_data_set_flags(struct hash_ipportnet4_elem *elem, u32 flags) 114{ 115 elem->nomatch = !!((flags >> 16) & IPSET_FLAG_NOMATCH); 116} 117 118static inline void 119hash_ipportnet4_data_reset_flags(struct hash_ipportnet4_elem *elem, u8 *flags) 120{ 121 swap(*flags, elem->nomatch); 122} 123 124static inline void 125hash_ipportnet4_data_netmask(struct hash_ipportnet4_elem *elem, u8 cidr) 126{ 127 elem->ip2 &= ip_set_netmask(cidr); 128 elem->cidr = cidr - 1; 129} 130 131static bool 132hash_ipportnet4_data_list(struct sk_buff *skb, 133 const struct hash_ipportnet4_elem *data) 134{ 135 u32 flags = data->nomatch ? IPSET_FLAG_NOMATCH : 0; 136 137 if (nla_put_ipaddr4(skb, IPSET_ATTR_IP, data->ip) || 138 nla_put_ipaddr4(skb, IPSET_ATTR_IP2, data->ip2) || 139 nla_put_net16(skb, IPSET_ATTR_PORT, data->port) || 140 nla_put_u8(skb, IPSET_ATTR_CIDR2, data->cidr + 1) || 141 nla_put_u8(skb, IPSET_ATTR_PROTO, data->proto) || 142 (flags && 143 nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags)))) 144 goto nla_put_failure; 145 return 0; 146 147nla_put_failure: 148 return 1; 149} 150 151static inline void 152hash_ipportnet4_data_next(struct hash_ipportnet4_elem *next, 153 const struct hash_ipportnet4_elem *d) 154{ 155 next->ip = d->ip; 156 next->port = d->port; 157 next->ip2 = d->ip2; 158} 159 160#define MTYPE hash_ipportnet4 161#define PF 4 162#define HOST_MASK 32 163#include "ip_set_hash_gen.h" 164 165static int 166hash_ipportnet4_kadt(struct ip_set *set, const struct sk_buff *skb, 167 const struct xt_action_param *par, 168 enum ipset_adt adt, struct ip_set_adt_opt *opt) 169{ 170 const struct hash_ipportnet *h = set->data; 171 ipset_adtfn adtfn = set->variant->adt[adt]; 172 struct hash_ipportnet4_elem e = { 173 .cidr = h->nets[0].cidr ? h->nets[0].cidr - 1 : HOST_MASK - 1 174 }; 175 struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, h); 176 177 if (adt == IPSET_TEST) 178 e.cidr = HOST_MASK - 1; 179 180 if (!ip_set_get_ip4_port(skb, opt->flags & IPSET_DIM_TWO_SRC, 181 &e.port, &e.proto)) 182 return -EINVAL; 183 184 ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip); 185 ip4addrptr(skb, opt->flags & IPSET_DIM_THREE_SRC, &e.ip2); 186 e.ip2 &= ip_set_netmask(e.cidr + 1); 187 188 return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags); 189} 190 191static int 192hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[], 193 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried) 194{ 195 const struct hash_ipportnet *h = set->data; 196 ipset_adtfn adtfn = set->variant->adt[adt]; 197 struct hash_ipportnet4_elem e = { .cidr = HOST_MASK - 1 }; 198 struct ip_set_ext ext = IP_SET_INIT_UEXT(h); 199 u32 ip, ip_to, p = 0, port, port_to; 200 u32 ip2_from, ip2_to, ip2_last, ip2; 201 bool with_ports = false; 202 u8 cidr; 203 int ret; 204 205 if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] || 206 !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || 207 !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) || 208 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || 209 !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS) || 210 !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) || 211 !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES))) 212 return -IPSET_ERR_PROTOCOL; 213 214 if (tb[IPSET_ATTR_LINENO]) 215 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); 216 217 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip) || 218 ip_set_get_extensions(set, tb, &ext); 219 if (ret) 220 return ret; 221 222 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP2], &ip2_from); 223 if (ret) 224 return ret; 225 226 if (tb[IPSET_ATTR_CIDR2]) { 227 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR2]); 228 if (!cidr || cidr > HOST_MASK) 229 return -IPSET_ERR_INVALID_CIDR; 230 e.cidr = cidr - 1; 231 } 232 233 if (tb[IPSET_ATTR_PORT]) 234 e.port = nla_get_be16(tb[IPSET_ATTR_PORT]); 235 else 236 return -IPSET_ERR_PROTOCOL; 237 238 if (tb[IPSET_ATTR_PROTO]) { 239 e.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); 240 with_ports = ip_set_proto_with_ports(e.proto); 241 242 if (e.proto == 0) 243 return -IPSET_ERR_INVALID_PROTO; 244 } else 245 return -IPSET_ERR_MISSING_PROTO; 246 247 if (!(with_ports || e.proto == IPPROTO_ICMP)) 248 e.port = 0; 249 250 if (tb[IPSET_ATTR_CADT_FLAGS]) { 251 u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]); 252 if (cadt_flags & IPSET_FLAG_NOMATCH) 253 flags |= (IPSET_FLAG_NOMATCH << 16); 254 } 255 256 with_ports = with_ports && tb[IPSET_ATTR_PORT_TO]; 257 if (adt == IPSET_TEST || 258 !(tb[IPSET_ATTR_CIDR] || tb[IPSET_ATTR_IP_TO] || with_ports || 259 tb[IPSET_ATTR_IP2_TO])) { 260 e.ip = htonl(ip); 261 e.ip2 = htonl(ip2_from & ip_set_hostmask(e.cidr + 1)); 262 ret = adtfn(set, &e, &ext, &ext, flags); 263 return ip_set_enomatch(ret, flags, adt) ? 1 : 264 ip_set_eexist(ret, flags) ? 0 : ret; 265 } 266 267 ip_to = ip; 268 if (tb[IPSET_ATTR_IP_TO]) { 269 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to); 270 if (ret) 271 return ret; 272 if (ip > ip_to) 273 swap(ip, ip_to); 274 } else if (tb[IPSET_ATTR_CIDR]) { 275 u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); 276 277 if (!cidr || cidr > 32) 278 return -IPSET_ERR_INVALID_CIDR; 279 ip_set_mask_from_to(ip, ip_to, cidr); 280 } 281 282 port_to = port = ntohs(e.port); 283 if (tb[IPSET_ATTR_PORT_TO]) { 284 port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]); 285 if (port > port_to) 286 swap(port, port_to); 287 } 288 289 ip2_to = ip2_from; 290 if (tb[IPSET_ATTR_IP2_TO]) { 291 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP2_TO], &ip2_to); 292 if (ret) 293 return ret; 294 if (ip2_from > ip2_to) 295 swap(ip2_from, ip2_to); 296 if (ip2_from + UINT_MAX == ip2_to) 297 return -IPSET_ERR_HASH_RANGE; 298 } else 299 ip_set_mask_from_to(ip2_from, ip2_to, e.cidr + 1); 300 301 if (retried) 302 ip = ntohl(h->next.ip); 303 for (; !before(ip_to, ip); ip++) { 304 e.ip = htonl(ip); 305 p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port) 306 : port; 307 for (; p <= port_to; p++) { 308 e.port = htons(p); 309 ip2 = retried 310 && ip == ntohl(h->next.ip) 311 && p == ntohs(h->next.port) 312 ? ntohl(h->next.ip2) : ip2_from; 313 while (!after(ip2, ip2_to)) { 314 e.ip2 = htonl(ip2); 315 ip2_last = ip_set_range_to_cidr(ip2, ip2_to, 316 &cidr); 317 e.cidr = cidr - 1; 318 ret = adtfn(set, &e, &ext, &ext, flags); 319 320 if (ret && !ip_set_eexist(ret, flags)) 321 return ret; 322 else 323 ret = 0; 324 ip2 = ip2_last + 1; 325 } 326 } 327 } 328 return ret; 329} 330 331/* IPv6 variants */ 332 333struct hash_ipportnet6_elem { 334 union nf_inet_addr ip; 335 union nf_inet_addr ip2; 336 __be16 port; 337 u8 cidr:7; 338 u8 nomatch:1; 339 u8 proto; 340}; 341 342struct hash_ipportnet6t_elem { 343 union nf_inet_addr ip; 344 union nf_inet_addr ip2; 345 __be16 port; 346 u8 cidr:7; 347 u8 nomatch:1; 348 u8 proto; 349 unsigned long timeout; 350}; 351 352struct hash_ipportnet6c_elem { 353 union nf_inet_addr ip; 354 union nf_inet_addr ip2; 355 __be16 port; 356 u8 cidr:7; 357 u8 nomatch:1; 358 u8 proto; 359 struct ip_set_counter counter; 360}; 361 362struct hash_ipportnet6ct_elem { 363 union nf_inet_addr ip; 364 union nf_inet_addr ip2; 365 __be16 port; 366 u8 cidr:7; 367 u8 nomatch:1; 368 u8 proto; 369 struct ip_set_counter counter; 370 unsigned long timeout; 371}; 372 373/* Common functions */ 374 375static inline bool 376hash_ipportnet6_data_equal(const struct hash_ipportnet6_elem *ip1, 377 const struct hash_ipportnet6_elem *ip2, 378 u32 *multi) 379{ 380 return ipv6_addr_equal(&ip1->ip.in6, &ip2->ip.in6) && 381 ipv6_addr_equal(&ip1->ip2.in6, &ip2->ip2.in6) && 382 ip1->cidr == ip2->cidr && 383 ip1->port == ip2->port && 384 ip1->proto == ip2->proto; 385} 386 387static inline int 388hash_ipportnet6_do_data_match(const struct hash_ipportnet6_elem *elem) 389{ 390 return elem->nomatch ? -ENOTEMPTY : 1; 391} 392 393static inline void 394hash_ipportnet6_data_set_flags(struct hash_ipportnet6_elem *elem, u32 flags) 395{ 396 elem->nomatch = !!((flags >> 16) & IPSET_FLAG_NOMATCH); 397} 398 399static inline void 400hash_ipportnet6_data_reset_flags(struct hash_ipportnet6_elem *elem, u8 *flags) 401{ 402 swap(*flags, elem->nomatch); 403} 404 405static inline void 406hash_ipportnet6_data_netmask(struct hash_ipportnet6_elem *elem, u8 cidr) 407{ 408 ip6_netmask(&elem->ip2, cidr); 409 elem->cidr = cidr - 1; 410} 411 412static bool 413hash_ipportnet6_data_list(struct sk_buff *skb, 414 const struct hash_ipportnet6_elem *data) 415{ 416 u32 flags = data->nomatch ? IPSET_FLAG_NOMATCH : 0; 417 418 if (nla_put_ipaddr6(skb, IPSET_ATTR_IP, &data->ip.in6) || 419 nla_put_ipaddr6(skb, IPSET_ATTR_IP2, &data->ip2.in6) || 420 nla_put_net16(skb, IPSET_ATTR_PORT, data->port) || 421 nla_put_u8(skb, IPSET_ATTR_CIDR2, data->cidr + 1) || 422 nla_put_u8(skb, IPSET_ATTR_PROTO, data->proto) || 423 (flags && 424 nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags)))) 425 goto nla_put_failure; 426 return 0; 427 428nla_put_failure: 429 return 1; 430} 431 432static inline void 433hash_ipportnet6_data_next(struct hash_ipportnet4_elem *next, 434 const struct hash_ipportnet6_elem *d) 435{ 436 next->port = d->port; 437} 438 439#undef MTYPE 440#undef PF 441#undef HOST_MASK 442 443#define MTYPE hash_ipportnet6 444#define PF 6 445#define HOST_MASK 128 446#define IP_SET_EMIT_CREATE 447#include "ip_set_hash_gen.h" 448 449static int 450hash_ipportnet6_kadt(struct ip_set *set, const struct sk_buff *skb, 451 const struct xt_action_param *par, 452 enum ipset_adt adt, struct ip_set_adt_opt *opt) 453{ 454 const struct hash_ipportnet *h = set->data; 455 ipset_adtfn adtfn = set->variant->adt[adt]; 456 struct hash_ipportnet6_elem e = { 457 .cidr = h->nets[0].cidr ? h->nets[0].cidr - 1 : HOST_MASK - 1 458 }; 459 struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, h); 460 461 if (adt == IPSET_TEST) 462 e.cidr = HOST_MASK - 1; 463 464 if (!ip_set_get_ip6_port(skb, opt->flags & IPSET_DIM_TWO_SRC, 465 &e.port, &e.proto)) 466 return -EINVAL; 467 468 ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip.in6); 469 ip6addrptr(skb, opt->flags & IPSET_DIM_THREE_SRC, &e.ip2.in6); 470 ip6_netmask(&e.ip2, e.cidr + 1); 471 472 return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags); 473} 474 475static int 476hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *tb[], 477 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried) 478{ 479 const struct hash_ipportnet *h = set->data; 480 ipset_adtfn adtfn = set->variant->adt[adt]; 481 struct hash_ipportnet6_elem e = { .cidr = HOST_MASK - 1 }; 482 struct ip_set_ext ext = IP_SET_INIT_UEXT(h); 483 u32 port, port_to; 484 bool with_ports = false; 485 u8 cidr; 486 int ret; 487 488 if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] || 489 !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || 490 !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) || 491 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || 492 !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS) || 493 !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) || 494 !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES) || 495 tb[IPSET_ATTR_IP_TO] || 496 tb[IPSET_ATTR_CIDR])) 497 return -IPSET_ERR_PROTOCOL; 498 if (unlikely(tb[IPSET_ATTR_IP_TO])) 499 return -IPSET_ERR_HASH_RANGE_UNSUPPORTED; 500 501 if (tb[IPSET_ATTR_LINENO]) 502 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); 503 504 ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &e.ip) || 505 ip_set_get_extensions(set, tb, &ext); 506 if (ret) 507 return ret; 508 509 ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP2], &e.ip2); 510 if (ret) 511 return ret; 512 513 if (tb[IPSET_ATTR_CIDR2]) { 514 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR2]); 515 if (!cidr || cidr > HOST_MASK) 516 return -IPSET_ERR_INVALID_CIDR; 517 e.cidr = cidr - 1; 518 } 519 520 ip6_netmask(&e.ip2, e.cidr + 1); 521 522 if (tb[IPSET_ATTR_PORT]) 523 e.port = nla_get_be16(tb[IPSET_ATTR_PORT]); 524 else 525 return -IPSET_ERR_PROTOCOL; 526 527 if (tb[IPSET_ATTR_PROTO]) { 528 e.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); 529 with_ports = ip_set_proto_with_ports(e.proto); 530 531 if (e.proto == 0) 532 return -IPSET_ERR_INVALID_PROTO; 533 } else 534 return -IPSET_ERR_MISSING_PROTO; 535 536 if (!(with_ports || e.proto == IPPROTO_ICMPV6)) 537 e.port = 0; 538 539 if (tb[IPSET_ATTR_CADT_FLAGS]) { 540 u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]); 541 if (cadt_flags & IPSET_FLAG_NOMATCH) 542 flags |= (IPSET_FLAG_NOMATCH << 16); 543 } 544 545 if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) { 546 ret = adtfn(set, &e, &ext, &ext, flags); 547 return ip_set_enomatch(ret, flags, adt) ? 1 : 548 ip_set_eexist(ret, flags) ? 0 : ret; 549 } 550 551 port = ntohs(e.port); 552 port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]); 553 if (port > port_to) 554 swap(port, port_to); 555 556 if (retried) 557 port = ntohs(h->next.port); 558 for (; port <= port_to; port++) { 559 e.port = htons(port); 560 ret = adtfn(set, &e, &ext, &ext, flags); 561 562 if (ret && !ip_set_eexist(ret, flags)) 563 return ret; 564 else 565 ret = 0; 566 } 567 return ret; 568} 569 570static struct ip_set_type hash_ipportnet_type __read_mostly = { 571 .name = "hash:ip,port,net", 572 .protocol = IPSET_PROTOCOL, 573 .features = IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_TYPE_IP2 | 574 IPSET_TYPE_NOMATCH, 575 .dimension = IPSET_DIM_THREE, 576 .family = NFPROTO_UNSPEC, 577 .revision_min = REVISION_MIN, 578 .revision_max = REVISION_MAX, 579 .create = hash_ipportnet_create, 580 .create_policy = { 581 [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, 582 [IPSET_ATTR_MAXELEM] = { .type = NLA_U32 }, 583 [IPSET_ATTR_PROBES] = { .type = NLA_U8 }, 584 [IPSET_ATTR_RESIZE] = { .type = NLA_U8 }, 585 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 586 [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 }, 587 }, 588 .adt_policy = { 589 [IPSET_ATTR_IP] = { .type = NLA_NESTED }, 590 [IPSET_ATTR_IP_TO] = { .type = NLA_NESTED }, 591 [IPSET_ATTR_IP2] = { .type = NLA_NESTED }, 592 [IPSET_ATTR_IP2_TO] = { .type = NLA_NESTED }, 593 [IPSET_ATTR_PORT] = { .type = NLA_U16 }, 594 [IPSET_ATTR_PORT_TO] = { .type = NLA_U16 }, 595 [IPSET_ATTR_CIDR] = { .type = NLA_U8 }, 596 [IPSET_ATTR_CIDR2] = { .type = NLA_U8 }, 597 [IPSET_ATTR_PROTO] = { .type = NLA_U8 }, 598 [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 }, 599 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 600 [IPSET_ATTR_LINENO] = { .type = NLA_U32 }, 601 [IPSET_ATTR_BYTES] = { .type = NLA_U64 }, 602 [IPSET_ATTR_PACKETS] = { .type = NLA_U64 }, 603 }, 604 .me = THIS_MODULE, 605}; 606 607static int __init 608hash_ipportnet_init(void) 609{ 610 return ip_set_type_register(&hash_ipportnet_type); 611} 612 613static void __exit 614hash_ipportnet_fini(void) 615{ 616 ip_set_type_unregister(&hash_ipportnet_type); 617} 618 619module_init(hash_ipportnet_init); 620module_exit(hash_ipportnet_fini); 621