libxt_set.c revision d637ead63658d741501974c381889b3857073308
1/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu> 2 * Patrick Schaaf <bof@bof.de> 3 * Martin Josefsson <gandalf@wlug.westbo.se> 4 * Copyright (C) 2003-2010 Jozsef Kadlecsik <kadlec@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 27static void 28set_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 37static 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 43static void 44set_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 51static int 52set_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 93static void 94print_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. */ 114static void 115set_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 122static void 123set_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 */ 131static int 132set_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 173static void 174print_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. */ 192static void 193set_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 200static void 201set_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 */ 209static void 210set_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 219static 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 226static int 227set_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. */ 272static void 273set_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 282static void 283set_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 292static struct xtables_match set_mt_reg[] = { 293 { 294 .name = "set", 295 .revision = 0, 296 .version = XTABLES_VERSION, 297 .family = NFPROTO_IPV4, 298 .size = XT_ALIGN(sizeof(struct xt_set_info_match_v0)), 299 .userspacesize = XT_ALIGN(sizeof(struct xt_set_info_match_v0)), 300 .help = set_help_v0, 301 .parse = set_parse_v0, 302 .final_check = set_check_v0, 303 .print = set_print_v0, 304 .save = set_save_v0, 305 .extra_opts = set_opts_v0, 306 }, 307 { 308 .name = "set", 309 .revision = 1, 310 .version = XTABLES_VERSION, 311 .family = NFPROTO_UNSPEC, 312 .size = XT_ALIGN(sizeof(struct xt_set_info_match_v1)), 313 .userspacesize = XT_ALIGN(sizeof(struct xt_set_info_match_v1)), 314 .help = set_help_v0, 315 .parse = set_parse_v1, 316 .final_check = set_check_v0, 317 .print = set_print_v1, 318 .save = set_save_v1, 319 .extra_opts = set_opts_v0, 320 }, 321 { 322 .name = "set", 323 .revision = 2, 324 .version = XTABLES_VERSION, 325 .family = NFPROTO_UNSPEC, 326 .size = XT_ALIGN(sizeof(struct xt_set_info_match_v1)), 327 .userspacesize = XT_ALIGN(sizeof(struct xt_set_info_match_v1)), 328 .help = set_help_v2, 329 .parse = set_parse_v2, 330 .final_check = set_check_v0, 331 .print = set_print_v2, 332 .save = set_save_v2, 333 .extra_opts = set_opts_v2, 334 }, 335}; 336 337void _init(void) 338{ 339 xtables_register_matches(set_mt_reg, ARRAY_SIZE(set_mt_reg)); 340} 341