1 /* Copyright (C) 2000-2002 Joakim Axelsson <gozem (at) linux.nu> 2 * Patrick Schaaf <bof (at) bof.de> 3 * Martin Josefsson <gandalf (at) wlug.westbo.se> 4 * Copyright (C) 2003-2010 Jozsef Kadlecsik <kadlec (at) blackhole.kfki.hu> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 as 8 * published by the Free Software Foundation. 9 */ 10 11 /* Shared library add-on to iptables to add IP set matching. */ 12 #include <stdbool.h> 13 #include <stdio.h> 14 #include <netdb.h> 15 #include <string.h> 16 #include <stdlib.h> 17 #include <getopt.h> 18 #include <ctype.h> 19 #include <errno.h> 20 21 #include <xtables.h> 22 #include <linux/netfilter/xt_set.h> 23 #include "libxt_set.h" 24 25 /* Revision 0 */ 26 27 static void 28 set_help_v0(void) 29 { 30 printf("set match options:\n" 31 " [!] --match-set name flags\n" 32 " 'name' is the set name from to match,\n" 33 " 'flags' are the comma separated list of\n" 34 " 'src' and 'dst' specifications.\n"); 35 } 36 37 static const struct option set_opts_v0[] = { 38 {.name = "match-set", .has_arg = true, .val = '1'}, 39 {.name = "set", .has_arg = true, .val = '2'}, 40 XT_GETOPT_TABLEEND, 41 }; 42 43 static void 44 set_check_v0(unsigned int flags) 45 { 46 if (!flags) 47 xtables_error(PARAMETER_PROBLEM, 48 "You must specify `--match-set' with proper arguments"); 49 } 50 51 static int 52 set_parse_v0(int c, char **argv, int invert, unsigned int *flags, 53 const void *entry, struct xt_entry_match **match) 54 { 55 struct xt_set_info_match_v0 *myinfo = 56 (struct xt_set_info_match_v0 *) (*match)->data; 57 struct xt_set_info_v0 *info = &myinfo->match_set; 58 59 switch (c) { 60 case '2': 61 fprintf(stderr, 62 "--set option deprecated, please use --match-set\n"); 63 case '1': /* --match-set <set> <flag>[,<flag> */ 64 if (info->u.flags[0]) 65 xtables_error(PARAMETER_PROBLEM, 66 "--match-set can be specified only once"); 67 if (invert) 68 info->u.flags[0] |= IPSET_MATCH_INV; 69 70 if (!argv[optind] 71 || argv[optind][0] == '-' 72 || argv[optind][0] == '!') 73 xtables_error(PARAMETER_PROBLEM, 74 "--match-set requires two args."); 75 76 if (strlen(optarg) > IPSET_MAXNAMELEN - 1) 77 xtables_error(PARAMETER_PROBLEM, 78 "setname `%s' too long, max %d characters.", 79 optarg, IPSET_MAXNAMELEN - 1); 80 81 get_set_byname(optarg, (struct xt_set_info *)info); 82 parse_dirs_v0(argv[optind], info); 83 DEBUGP("parse: set index %u\n", info->index); 84 optind++; 85 86 *flags = 1; 87 break; 88 } 89 90 return 1; 91 } 92 93 static void 94 print_match_v0(const char *prefix, const struct xt_set_info_v0 *info) 95 { 96 int i; 97 char setname[IPSET_MAXNAMELEN]; 98 99 get_set_byid(setname, info->index); 100 printf("%s %s %s", 101 (info->u.flags[0] & IPSET_MATCH_INV) ? " !" : "", 102 prefix, 103 setname); 104 for (i = 0; i < IPSET_DIM_MAX; i++) { 105 if (!info->u.flags[i]) 106 break; 107 printf("%s%s", 108 i == 0 ? " " : ",", 109 info->u.flags[i] & IPSET_SRC ? "src" : "dst"); 110 } 111 } 112 113 /* Prints out the matchinfo. */ 114 static void 115 set_print_v0(const void *ip, const struct xt_entry_match *match, int numeric) 116 { 117 const struct xt_set_info_match_v0 *info = (const void *)match->data; 118 119 print_match_v0("match-set", &info->match_set); 120 } 121 122 static void 123 set_save_v0(const void *ip, const struct xt_entry_match *match) 124 { 125 const struct xt_set_info_match_v0 *info = (const void *)match->data; 126 127 print_match_v0("--match-set", &info->match_set); 128 } 129 130 /* Revision 1 */ 131 static int 132 set_parse_v1(int c, char **argv, int invert, unsigned int *flags, 133 const void *entry, struct xt_entry_match **match) 134 { 135 struct xt_set_info_match_v1 *myinfo = 136 (struct xt_set_info_match_v1 *) (*match)->data; 137 struct xt_set_info *info = &myinfo->match_set; 138 139 switch (c) { 140 case '2': 141 fprintf(stderr, 142 "--set option deprecated, please use --match-set\n"); 143 case '1': /* --match-set <set> <flag>[,<flag> */ 144 if (info->dim) 145 xtables_error(PARAMETER_PROBLEM, 146 "--match-set can be specified only once"); 147 if (invert) 148 info->flags |= IPSET_INV_MATCH; 149 150 if (!argv[optind] 151 || argv[optind][0] == '-' 152 || argv[optind][0] == '!') 153 xtables_error(PARAMETER_PROBLEM, 154 "--match-set requires two args."); 155 156 if (strlen(optarg) > IPSET_MAXNAMELEN - 1) 157 xtables_error(PARAMETER_PROBLEM, 158 "setname `%s' too long, max %d characters.", 159 optarg, IPSET_MAXNAMELEN - 1); 160 161 get_set_byname(optarg, info); 162 parse_dirs(argv[optind], info); 163 DEBUGP("parse: set index %u\n", info->index); 164 optind++; 165 166 *flags = 1; 167 break; 168 } 169 170 return 1; 171 } 172 173 static void 174 print_match(const char *prefix, const struct xt_set_info *info) 175 { 176 int i; 177 char setname[IPSET_MAXNAMELEN]; 178 179 get_set_byid(setname, info->index); 180 printf("%s %s %s", 181 (info->flags & IPSET_INV_MATCH) ? " !" : "", 182 prefix, 183 setname); 184 for (i = 1; i <= info->dim; i++) { 185 printf("%s%s", 186 i == 1 ? " " : ",", 187 info->flags & (1 << i) ? "src" : "dst"); 188 } 189 } 190 191 /* Prints out the matchinfo. */ 192 static void 193 set_print_v1(const void *ip, const struct xt_entry_match *match, int numeric) 194 { 195 const struct xt_set_info_match_v1 *info = (const void *)match->data; 196 197 print_match("match-set", &info->match_set); 198 } 199 200 static void 201 set_save_v1(const void *ip, const struct xt_entry_match *match) 202 { 203 const struct xt_set_info_match_v1 *info = (const void *)match->data; 204 205 print_match("--match-set", &info->match_set); 206 } 207 208 /* Revision 2 */ 209 static void 210 set_help_v2(void) 211 { 212 printf("set match options:\n" 213 " [!] --match-set name flags [--return-nomatch]\n" 214 " 'name' is the set name from to match,\n" 215 " 'flags' are the comma separated list of\n" 216 " 'src' and 'dst' specifications.\n"); 217 } 218 219 static const struct option set_opts_v2[] = { 220 {.name = "match-set", .has_arg = true, .val = '1'}, 221 {.name = "set", .has_arg = true, .val = '2'}, 222 {.name = "return-nomatch", .has_arg = false, .val = '3'}, 223 XT_GETOPT_TABLEEND, 224 }; 225 226 static int 227 set_parse_v2(int c, char **argv, int invert, unsigned int *flags, 228 const void *entry, struct xt_entry_match **match) 229 { 230 struct xt_set_info_match_v1 *myinfo = 231 (struct xt_set_info_match_v1 *) (*match)->data; 232 struct xt_set_info *info = &myinfo->match_set; 233 234 switch (c) { 235 case '3': 236 info->flags |= IPSET_RETURN_NOMATCH; 237 break; 238 case '2': 239 fprintf(stderr, 240 "--set option deprecated, please use --match-set\n"); 241 case '1': /* --match-set <set> <flag>[,<flag> */ 242 if (info->dim) 243 xtables_error(PARAMETER_PROBLEM, 244 "--match-set can be specified only once"); 245 if (invert) 246 info->flags |= IPSET_INV_MATCH; 247 248 if (!argv[optind] 249 || argv[optind][0] == '-' 250 || argv[optind][0] == '!') 251 xtables_error(PARAMETER_PROBLEM, 252 "--match-set requires two args."); 253 254 if (strlen(optarg) > IPSET_MAXNAMELEN - 1) 255 xtables_error(PARAMETER_PROBLEM, 256 "setname `%s' too long, max %d characters.", 257 optarg, IPSET_MAXNAMELEN - 1); 258 259 get_set_byname(optarg, info); 260 parse_dirs(argv[optind], info); 261 DEBUGP("parse: set index %u\n", info->index); 262 optind++; 263 264 *flags = 1; 265 break; 266 } 267 268 return 1; 269 } 270 271 /* Prints out the matchinfo. */ 272 static void 273 set_print_v2(const void *ip, const struct xt_entry_match *match, int numeric) 274 { 275 const struct xt_set_info_match_v1 *info = (const void *)match->data; 276 277 print_match("match-set", &info->match_set); 278 if (info->match_set.flags & IPSET_RETURN_NOMATCH) 279 printf(" return-nomatch"); 280 } 281 282 static void 283 set_save_v2(const void *ip, const struct xt_entry_match *match) 284 { 285 const struct xt_set_info_match_v1 *info = (const void *)match->data; 286 287 print_match("--match-set", &info->match_set); 288 if (info->match_set.flags & IPSET_RETURN_NOMATCH) 289 printf(" --return-nomatch"); 290 } 291 292 /* Revision 3 */ 293 static void 294 set_help_v3(void) 295 { 296 printf("set match options:\n" 297 " [!] --match-set name flags [--return-nomatch]\n" 298 " [! --update-counters] [! --update-subcounters]\n" 299 " [[!] --packets-eq value | --packets-lt value | --packets-gt value\n" 300 " [[!] --bytes-eq value | --bytes-lt value | --bytes-gt value\n" 301 " 'name' is the set name from to match,\n" 302 " 'flags' are the comma separated list of\n" 303 " 'src' and 'dst' specifications.\n"); 304 } 305 306 static const struct option set_opts_v3[] = { 307 {.name = "match-set", .has_arg = true, .val = '1'}, 308 {.name = "set", .has_arg = true, .val = '2'}, 309 {.name = "return-nomatch", .has_arg = false, .val = '3'}, 310 {.name = "update-counters", .has_arg = false, .val = '4'}, 311 {.name = "packets-eq", .has_arg = true, .val = '5'}, 312 {.name = "packets-lt", .has_arg = true, .val = '6'}, 313 {.name = "packets-gt", .has_arg = true, .val = '7'}, 314 {.name = "bytes-eq", .has_arg = true, .val = '8'}, 315 {.name = "bytes-lt", .has_arg = true, .val = '9'}, 316 {.name = "bytes-gt", .has_arg = true, .val = '0'}, 317 {.name = "update-subcounters", .has_arg = false, .val = 'a'}, 318 XT_GETOPT_TABLEEND, 319 }; 320 321 static uint64_t 322 parse_counter(const char *opt) 323 { 324 uintmax_t value; 325 326 if (!xtables_strtoul(opt, NULL, &value, 0, UINT64_MAX)) 327 xtables_error(PARAMETER_PROBLEM, 328 "Cannot parse %s as a counter value\n", 329 opt); 330 return (uint64_t)value; 331 } 332 333 static int 334 set_parse_v3(int c, char **argv, int invert, unsigned int *flags, 335 const void *entry, struct xt_entry_match **match) 336 { 337 struct xt_set_info_match_v3 *info = 338 (struct xt_set_info_match_v3 *) (*match)->data; 339 340 switch (c) { 341 case 'a': 342 if (invert) 343 info->flags |= IPSET_FLAG_SKIP_SUBCOUNTER_UPDATE; 344 break; 345 case '0': 346 if (info->bytes.op != IPSET_COUNTER_NONE) 347 xtables_error(PARAMETER_PROBLEM, 348 "only one of the --bytes-[eq|lt|gt]" 349 " is allowed\n"); 350 if (invert) 351 xtables_error(PARAMETER_PROBLEM, 352 "--bytes-gt option cannot be inverted\n"); 353 info->bytes.op = IPSET_COUNTER_GT; 354 info->bytes.value = parse_counter(optarg); 355 break; 356 case '9': 357 if (info->bytes.op != IPSET_COUNTER_NONE) 358 xtables_error(PARAMETER_PROBLEM, 359 "only one of the --bytes-[eq|lt|gt]" 360 " is allowed\n"); 361 if (invert) 362 xtables_error(PARAMETER_PROBLEM, 363 "--bytes-lt option cannot be inverted\n"); 364 info->bytes.op = IPSET_COUNTER_LT; 365 info->bytes.value = parse_counter(optarg); 366 break; 367 case '8': 368 if (info->bytes.op != IPSET_COUNTER_NONE) 369 xtables_error(PARAMETER_PROBLEM, 370 "only one of the --bytes-[eq|lt|gt]" 371 " is allowed\n"); 372 info->bytes.op = invert ? IPSET_COUNTER_NE : IPSET_COUNTER_EQ; 373 info->bytes.value = parse_counter(optarg); 374 break; 375 case '7': 376 if (info->packets.op != IPSET_COUNTER_NONE) 377 xtables_error(PARAMETER_PROBLEM, 378 "only one of the --packets-[eq|lt|gt]" 379 " is allowed\n"); 380 if (invert) 381 xtables_error(PARAMETER_PROBLEM, 382 "--packets-gt option cannot be inverted\n"); 383 info->packets.op = IPSET_COUNTER_GT; 384 info->packets.value = parse_counter(optarg); 385 break; 386 case '6': 387 if (info->packets.op != IPSET_COUNTER_NONE) 388 xtables_error(PARAMETER_PROBLEM, 389 "only one of the --packets-[eq|lt|gt]" 390 " is allowed\n"); 391 if (invert) 392 xtables_error(PARAMETER_PROBLEM, 393 "--packets-lt option cannot be inverted\n"); 394 info->packets.op = IPSET_COUNTER_LT; 395 info->packets.value = parse_counter(optarg); 396 break; 397 case '5': 398 if (info->packets.op != IPSET_COUNTER_NONE) 399 xtables_error(PARAMETER_PROBLEM, 400 "only one of the --packets-[eq|lt|gt]" 401 " is allowed\n"); 402 info->packets.op = invert ? IPSET_COUNTER_NE : IPSET_COUNTER_EQ; 403 info->packets.value = parse_counter(optarg); 404 break; 405 case '4': 406 if (invert) 407 info->flags |= IPSET_FLAG_SKIP_COUNTER_UPDATE; 408 break; 409 case '3': 410 if (invert) 411 xtables_error(PARAMETER_PROBLEM, 412 "--return-nomatch flag cannot be inverted\n"); 413 info->flags |= IPSET_FLAG_RETURN_NOMATCH; 414 break; 415 case '2': 416 fprintf(stderr, 417 "--set option deprecated, please use --match-set\n"); 418 case '1': /* --match-set <set> <flag>[,<flag> */ 419 if (info->match_set.dim) 420 xtables_error(PARAMETER_PROBLEM, 421 "--match-set can be specified only once"); 422 if (invert) 423 info->match_set.flags |= IPSET_INV_MATCH; 424 425 if (!argv[optind] 426 || argv[optind][0] == '-' 427 || argv[optind][0] == '!') 428 xtables_error(PARAMETER_PROBLEM, 429 "--match-set requires two args."); 430 431 if (strlen(optarg) > IPSET_MAXNAMELEN - 1) 432 xtables_error(PARAMETER_PROBLEM, 433 "setname `%s' too long, max %d characters.", 434 optarg, IPSET_MAXNAMELEN - 1); 435 436 get_set_byname(optarg, &info->match_set); 437 parse_dirs(argv[optind], &info->match_set); 438 DEBUGP("parse: set index %u\n", info->match_set.index); 439 optind++; 440 441 *flags = 1; 442 break; 443 } 444 445 return 1; 446 } 447 448 static void 449 set_printv3_counter(const struct ip_set_counter_match0 *c, const char *name, 450 const char *sep) 451 { 452 switch (c->op) { 453 case IPSET_COUNTER_EQ: 454 printf(" %s%s-eq %llu", sep, name, c->value); 455 break; 456 case IPSET_COUNTER_NE: 457 printf(" ! %s%s-eq %llu", sep, name, c->value); 458 break; 459 case IPSET_COUNTER_LT: 460 printf(" %s%s-lt %llu", sep, name, c->value); 461 break; 462 case IPSET_COUNTER_GT: 463 printf(" %s%s-gt %llu", sep, name, c->value); 464 break; 465 } 466 } 467 468 static void 469 set_print_v3_matchinfo(const struct xt_set_info_match_v3 *info, 470 const char *opt, const char *sep) 471 { 472 print_match(opt, &info->match_set); 473 if (info->flags & IPSET_FLAG_RETURN_NOMATCH) 474 printf(" %sreturn-nomatch", sep); 475 if ((info->flags & IPSET_FLAG_SKIP_COUNTER_UPDATE)) 476 printf(" ! %supdate-counters", sep); 477 if ((info->flags & IPSET_FLAG_SKIP_SUBCOUNTER_UPDATE)) 478 printf(" ! %supdate-subcounters", sep); 479 set_printv3_counter(&info->packets, "packets", sep); 480 set_printv3_counter(&info->bytes, "bytes", sep); 481 } 482 483 /* Prints out the matchinfo. */ 484 static void 485 set_print_v3(const void *ip, const struct xt_entry_match *match, int numeric) 486 { 487 const struct xt_set_info_match_v3 *info = (const void *)match->data; 488 489 set_print_v3_matchinfo(info, "match-set", ""); 490 } 491 492 static void 493 set_save_v3(const void *ip, const struct xt_entry_match *match) 494 { 495 const struct xt_set_info_match_v3 *info = (const void *)match->data; 496 497 set_print_v3_matchinfo(info, "--match-set", "--"); 498 } 499 500 /* Revision 4 */ 501 static int 502 set_parse_v4(int c, char **argv, int invert, unsigned int *flags, 503 const void *entry, struct xt_entry_match **match) 504 { 505 struct xt_set_info_match_v4 *info = 506 (struct xt_set_info_match_v4 *) (*match)->data; 507 508 switch (c) { 509 case 'a': 510 if (invert) 511 info->flags |= IPSET_FLAG_SKIP_SUBCOUNTER_UPDATE; 512 break; 513 case '0': 514 if (info->bytes.op != IPSET_COUNTER_NONE) 515 xtables_error(PARAMETER_PROBLEM, 516 "only one of the --bytes-[eq|lt|gt]" 517 " is allowed\n"); 518 if (invert) 519 xtables_error(PARAMETER_PROBLEM, 520 "--bytes-gt option cannot be inverted\n"); 521 info->bytes.op = IPSET_COUNTER_GT; 522 info->bytes.value = parse_counter(optarg); 523 break; 524 case '9': 525 if (info->bytes.op != IPSET_COUNTER_NONE) 526 xtables_error(PARAMETER_PROBLEM, 527 "only one of the --bytes-[eq|lt|gt]" 528 " is allowed\n"); 529 if (invert) 530 xtables_error(PARAMETER_PROBLEM, 531 "--bytes-lt option cannot be inverted\n"); 532 info->bytes.op = IPSET_COUNTER_LT; 533 info->bytes.value = parse_counter(optarg); 534 break; 535 case '8': 536 if (info->bytes.op != IPSET_COUNTER_NONE) 537 xtables_error(PARAMETER_PROBLEM, 538 "only one of the --bytes-[eq|lt|gt]" 539 " is allowed\n"); 540 info->bytes.op = invert ? IPSET_COUNTER_NE : IPSET_COUNTER_EQ; 541 info->bytes.value = parse_counter(optarg); 542 break; 543 case '7': 544 if (info->packets.op != IPSET_COUNTER_NONE) 545 xtables_error(PARAMETER_PROBLEM, 546 "only one of the --packets-[eq|lt|gt]" 547 " is allowed\n"); 548 if (invert) 549 xtables_error(PARAMETER_PROBLEM, 550 "--packets-gt option cannot be inverted\n"); 551 info->packets.op = IPSET_COUNTER_GT; 552 info->packets.value = parse_counter(optarg); 553 break; 554 case '6': 555 if (info->packets.op != IPSET_COUNTER_NONE) 556 xtables_error(PARAMETER_PROBLEM, 557 "only one of the --packets-[eq|lt|gt]" 558 " is allowed\n"); 559 if (invert) 560 xtables_error(PARAMETER_PROBLEM, 561 "--packets-lt option cannot be inverted\n"); 562 info->packets.op = IPSET_COUNTER_LT; 563 info->packets.value = parse_counter(optarg); 564 break; 565 case '5': 566 if (info->packets.op != IPSET_COUNTER_NONE) 567 xtables_error(PARAMETER_PROBLEM, 568 "only one of the --packets-[eq|lt|gt]" 569 " is allowed\n"); 570 info->packets.op = invert ? IPSET_COUNTER_NE : IPSET_COUNTER_EQ; 571 info->packets.value = parse_counter(optarg); 572 break; 573 case '4': 574 if (invert) 575 info->flags |= IPSET_FLAG_SKIP_COUNTER_UPDATE; 576 break; 577 case '3': 578 if (invert) 579 xtables_error(PARAMETER_PROBLEM, 580 "--return-nomatch flag cannot be inverted\n"); 581 info->flags |= IPSET_FLAG_RETURN_NOMATCH; 582 break; 583 case '2': 584 fprintf(stderr, 585 "--set option deprecated, please use --match-set\n"); 586 case '1': /* --match-set <set> <flag>[,<flag> */ 587 if (info->match_set.dim) 588 xtables_error(PARAMETER_PROBLEM, 589 "--match-set can be specified only once"); 590 if (invert) 591 info->match_set.flags |= IPSET_INV_MATCH; 592 593 if (!argv[optind] 594 || argv[optind][0] == '-' 595 || argv[optind][0] == '!') 596 xtables_error(PARAMETER_PROBLEM, 597 "--match-set requires two args."); 598 599 if (strlen(optarg) > IPSET_MAXNAMELEN - 1) 600 xtables_error(PARAMETER_PROBLEM, 601 "setname `%s' too long, max %d characters.", 602 optarg, IPSET_MAXNAMELEN - 1); 603 604 get_set_byname(optarg, &info->match_set); 605 parse_dirs(argv[optind], &info->match_set); 606 DEBUGP("parse: set index %u\n", info->match_set.index); 607 optind++; 608 609 *flags = 1; 610 break; 611 } 612 613 return 1; 614 } 615 616 static void 617 set_printv4_counter(const struct ip_set_counter_match *c, const char *name, 618 const char *sep) 619 { 620 switch (c->op) { 621 case IPSET_COUNTER_EQ: 622 printf(" %s%s-eq %llu", sep, name, c->value); 623 break; 624 case IPSET_COUNTER_NE: 625 printf(" ! %s%s-eq %llu", sep, name, c->value); 626 break; 627 case IPSET_COUNTER_LT: 628 printf(" %s%s-lt %llu", sep, name, c->value); 629 break; 630 case IPSET_COUNTER_GT: 631 printf(" %s%s-gt %llu", sep, name, c->value); 632 break; 633 } 634 } 635 636 static void 637 set_print_v4_matchinfo(const struct xt_set_info_match_v4 *info, 638 const char *opt, const char *sep) 639 { 640 print_match(opt, &info->match_set); 641 if (info->flags & IPSET_FLAG_RETURN_NOMATCH) 642 printf(" %sreturn-nomatch", sep); 643 if ((info->flags & IPSET_FLAG_SKIP_COUNTER_UPDATE)) 644 printf(" ! %supdate-counters", sep); 645 if ((info->flags & IPSET_FLAG_SKIP_SUBCOUNTER_UPDATE)) 646 printf(" ! %supdate-subcounters", sep); 647 set_printv4_counter(&info->packets, "packets", sep); 648 set_printv4_counter(&info->bytes, "bytes", sep); 649 } 650 651 /* Prints out the matchinfo. */ 652 static void 653 set_print_v4(const void *ip, const struct xt_entry_match *match, int numeric) 654 { 655 const struct xt_set_info_match_v4 *info = (const void *)match->data; 656 657 set_print_v4_matchinfo(info, "match-set", ""); 658 } 659 660 static void 661 set_save_v4(const void *ip, const struct xt_entry_match *match) 662 { 663 const struct xt_set_info_match_v4 *info = (const void *)match->data; 664 665 set_print_v4_matchinfo(info, "--match-set", "--"); 666 } 667 668 static struct xtables_match set_mt_reg[] = { 669 { 670 .name = "set", 671 .revision = 0, 672 .version = XTABLES_VERSION, 673 .family = NFPROTO_IPV4, 674 .size = XT_ALIGN(sizeof(struct xt_set_info_match_v0)), 675 .userspacesize = XT_ALIGN(sizeof(struct xt_set_info_match_v0)), 676 .help = set_help_v0, 677 .parse = set_parse_v0, 678 .final_check = set_check_v0, 679 .print = set_print_v0, 680 .save = set_save_v0, 681 .extra_opts = set_opts_v0, 682 }, 683 { 684 .name = "set", 685 .revision = 1, 686 .version = XTABLES_VERSION, 687 .family = NFPROTO_UNSPEC, 688 .size = XT_ALIGN(sizeof(struct xt_set_info_match_v1)), 689 .userspacesize = XT_ALIGN(sizeof(struct xt_set_info_match_v1)), 690 .help = set_help_v0, 691 .parse = set_parse_v1, 692 .final_check = set_check_v0, 693 .print = set_print_v1, 694 .save = set_save_v1, 695 .extra_opts = set_opts_v0, 696 }, 697 { 698 .name = "set", 699 .revision = 2, 700 .version = XTABLES_VERSION, 701 .family = NFPROTO_UNSPEC, 702 .size = XT_ALIGN(sizeof(struct xt_set_info_match_v1)), 703 .userspacesize = XT_ALIGN(sizeof(struct xt_set_info_match_v1)), 704 .help = set_help_v2, 705 .parse = set_parse_v2, 706 .final_check = set_check_v0, 707 .print = set_print_v2, 708 .save = set_save_v2, 709 .extra_opts = set_opts_v2, 710 }, 711 { 712 .name = "set", 713 .revision = 3, 714 .version = XTABLES_VERSION, 715 .family = NFPROTO_UNSPEC, 716 .size = XT_ALIGN(sizeof(struct xt_set_info_match_v3)), 717 .userspacesize = XT_ALIGN(sizeof(struct xt_set_info_match_v3)), 718 .help = set_help_v3, 719 .parse = set_parse_v3, 720 .final_check = set_check_v0, 721 .print = set_print_v3, 722 .save = set_save_v3, 723 .extra_opts = set_opts_v3, 724 }, 725 { 726 .name = "set", 727 .revision = 4, 728 .version = XTABLES_VERSION, 729 .family = NFPROTO_UNSPEC, 730 .size = XT_ALIGN(sizeof(struct xt_set_info_match_v4)), 731 .userspacesize = XT_ALIGN(sizeof(struct xt_set_info_match_v4)), 732 .help = set_help_v3, 733 .parse = set_parse_v4, 734 .final_check = set_check_v0, 735 .print = set_print_v4, 736 .save = set_save_v4, 737 .extra_opts = set_opts_v3, 738 }, 739 }; 740 741 void _init(void) 742 { 743 xtables_register_matches(set_mt_reg, ARRAY_SIZE(set_mt_reg)); 744 } 745