libxt_set.c revision d09b6d591ca7d7d7575cb6aa20384c9830f777ab
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 25static void 26set_help(void) 27{ 28 printf("set match options:\n" 29 " [!] --match-set name flags\n" 30 " 'name' is the set name from to match,\n" 31 " 'flags' are the comma separated list of\n" 32 " 'src' and 'dst' specifications.\n"); 33} 34 35static const struct option set_opts[] = { 36 {.name = "match-set", .has_arg = true, .val = '1'}, 37 {.name = "set", .has_arg = true, .val = '2'}, 38 XT_GETOPT_TABLEEND, 39}; 40 41static void 42set_check(unsigned int flags) 43{ 44 if (!flags) 45 xtables_error(PARAMETER_PROBLEM, 46 "You must specify `--match-set' with proper arguments"); 47} 48 49static int 50set_parse_v0(int c, char **argv, int invert, unsigned int *flags, 51 const void *entry, struct xt_entry_match **match) 52{ 53 struct xt_set_info_match_v0 *myinfo = 54 (struct xt_set_info_match_v0 *) (*match)->data; 55 struct xt_set_info_v0 *info = &myinfo->match_set; 56 57 switch (c) { 58 case '2': 59 fprintf(stderr, 60 "--set option deprecated, please use --match-set\n"); 61 case '1': /* --match-set <set> <flag>[,<flag> */ 62 if (info->u.flags[0]) 63 xtables_error(PARAMETER_PROBLEM, 64 "--match-set can be specified only once"); 65 66 xtables_check_inverse(optarg, &invert, &optind, 0, argv); 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 printf(" "); 112} 113 114/* Prints out the matchinfo. */ 115static void 116set_print_v0(const void *ip, const struct xt_entry_match *match, int numeric) 117{ 118 const struct xt_set_info_match_v0 *info = (const void *)match->data; 119 120 print_match_v0("match-set", &info->match_set); 121} 122 123static void 124set_save_v0(const void *ip, const struct xt_entry_match *match) 125{ 126 const struct xt_set_info_match_v0 *info = (const void *)match->data; 127 128 print_match_v0("--match-set", &info->match_set); 129} 130 131static int 132set_parse(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 *myinfo = 136 (struct xt_set_info_match *) (*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 148 xtables_check_inverse(optarg, &invert, &optind, 0, argv); 149 if (invert) 150 info->flags |= IPSET_INV_MATCH; 151 152 if (!argv[optind] 153 || argv[optind][0] == '-' 154 || argv[optind][0] == '!') 155 xtables_error(PARAMETER_PROBLEM, 156 "--match-set requires two args."); 157 158 if (strlen(optarg) > IPSET_MAXNAMELEN - 1) 159 xtables_error(PARAMETER_PROBLEM, 160 "setname `%s' too long, max %d characters.", 161 optarg, IPSET_MAXNAMELEN - 1); 162 163 get_set_byname(optarg, info); 164 parse_dirs(argv[optind], info); 165 DEBUGP("parse: set index %u\n", info->index); 166 optind++; 167 168 *flags = 1; 169 break; 170 } 171 172 return 1; 173} 174 175static void 176print_match(const char *prefix, const struct xt_set_info *info) 177{ 178 int i; 179 char setname[IPSET_MAXNAMELEN]; 180 181 get_set_byid(setname, info->index); 182 printf("%s%s %s", 183 (info->flags & IPSET_INV_MATCH) ? "! " : "", 184 prefix, 185 setname); 186 for (i = 1; i <= info->dim; i++) { 187 printf("%s%s", 188 i == 1 ? " " : ",", 189 info->flags & (1 << i) ? "src" : "dst"); 190 } 191 printf(" "); 192} 193 194/* Prints out the matchinfo. */ 195static void 196set_print(const void *ip, const struct xt_entry_match *match, int numeric) 197{ 198 const struct xt_set_info_match *info = (const void *)match->data; 199 200 print_match("match-set", &info->match_set); 201} 202 203static void 204set_save(const void *ip, const struct xt_entry_match *match) 205{ 206 const struct xt_set_info_match *info = (const void *)match->data; 207 208 print_match("--match-set", &info->match_set); 209} 210 211static struct xtables_match set_mt_reg[] = { 212 { 213 .name = "set", 214 .revision = 0, 215 .version = XTABLES_VERSION, 216 .family = NFPROTO_IPV4, 217 .size = XT_ALIGN(sizeof(struct xt_set_info_match_v0)), 218 .userspacesize = XT_ALIGN(sizeof(struct xt_set_info_match_v0)), 219 .help = set_help, 220 .parse = set_parse_v0, 221 .final_check = set_check, 222 .print = set_print_v0, 223 .save = set_save_v0, 224 .extra_opts = set_opts, 225 }, 226 { 227 .name = "set", 228 .revision = 1, 229 .version = XTABLES_VERSION, 230 .family = NFPROTO_UNSPEC, 231 .size = XT_ALIGN(sizeof(struct xt_set_info_match)), 232 .userspacesize = XT_ALIGN(sizeof(struct xt_set_info_match)), 233 .help = set_help, 234 .parse = set_parse, 235 .final_check = set_check, 236 .print = set_print, 237 .save = set_save, 238 .extra_opts = set_opts, 239 }, 240}; 241 242void _init(void) 243{ 244 xtables_register_matches(set_mt_reg, ARRAY_SIZE(set_mt_reg)); 245} 246