libxt_set.c revision d40f1628c3717daebc437a398a285e371b5b6f7f
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 <stdio.h> 13#include <netdb.h> 14#include <string.h> 15#include <stdlib.h> 16#include <getopt.h> 17#include <ctype.h> 18#include <errno.h> 19 20#include <xtables.h> 21#include <linux/netfilter/xt_set.h> 22#include "libxt_set.h" 23 24static void 25set_help(void) 26{ 27 printf("set match options:\n" 28 " [!] --match-set name flags\n" 29 " 'name' is the set name from to match,\n" 30 " 'flags' are the comma separated list of\n" 31 " 'src' and 'dst' specifications.\n"); 32} 33 34static const struct option set_opts[] = { 35 { .name = "match-set", .has_arg = true, .val = '1'}, 36 { .name = "set", .has_arg = true, .val = '2'}, 37 { .name = NULL } 38}; 39 40static void 41set_check(unsigned int flags) 42{ 43 if (!flags) 44 xtables_error(PARAMETER_PROBLEM, 45 "You must specify `--match-set' with proper arguments"); 46} 47 48static int 49set_parse_v0(int c, char **argv, int invert, unsigned int *flags, 50 const void *entry, struct xt_entry_match **match) 51{ 52 struct xt_set_info_match_v0 *myinfo = 53 (struct xt_set_info_match_v0 *) (*match)->data; 54 struct xt_set_info_v0 *info = &myinfo->match_set; 55 56 switch (c) { 57 case '2': 58 fprintf(stderr, 59 "--set option deprecated, please use --match-set\n"); 60 case '1': /* --match-set <set> <flag>[,<flag> */ 61 if (info->u.flags[0]) 62 xtables_error(PARAMETER_PROBLEM, 63 "--match-set can be specified only once"); 64 65 xtables_check_inverse(optarg, &invert, &optind, 0, argv); 66 if (invert) 67 info->u.flags[0] |= IPSET_MATCH_INV; 68 69 if (!argv[optind] 70 || argv[optind][0] == '-' 71 || argv[optind][0] == '!') 72 xtables_error(PARAMETER_PROBLEM, 73 "--match-set requires two args."); 74 75 if (strlen(optarg) > IPSET_MAXNAMELEN - 1) 76 xtables_error(PARAMETER_PROBLEM, 77 "setname `%s' too long, max %d characters.", 78 optarg, IPSET_MAXNAMELEN - 1); 79 80 get_set_byname(optarg, (struct xt_set_info *)info); 81 parse_dirs_v0(argv[optind], info); 82 DEBUGP("parse: set index %u\n", info->index); 83 optind++; 84 85 *flags = 1; 86 break; 87 88 default: 89 return 0; 90 } 91 92 return 1; 93} 94 95static void 96print_match_v0(const char *prefix, const struct xt_set_info_v0 *info) 97{ 98 int i; 99 char setname[IPSET_MAXNAMELEN]; 100 101 get_set_byid(setname, info->index); 102 printf("%s%s %s", 103 (info->u.flags[0] & IPSET_MATCH_INV) ? "! " : "", 104 prefix, 105 setname); 106 for (i = 0; i < IPSET_DIM_MAX; i++) { 107 if (!info->u.flags[i]) 108 break; 109 printf("%s%s", 110 i == 0 ? " " : ",", 111 info->u.flags[i] & IPSET_SRC ? "src" : "dst"); 112 } 113 printf(" "); 114} 115 116/* Prints out the matchinfo. */ 117static void 118set_print_v0(const void *ip, const struct xt_entry_match *match, int numeric) 119{ 120 const struct xt_set_info_match_v0 *info = (const void *)match->data; 121 122 print_match_v0("match-set", &info->match_set); 123} 124 125static void 126set_save_v0(const void *ip, const struct xt_entry_match *match) 127{ 128 const struct xt_set_info_match_v0 *info = (const void *)match->data; 129 130 print_match_v0("--match-set", &info->match_set); 131} 132 133static int 134set_parse(int c, char **argv, int invert, unsigned int *flags, 135 const void *entry, struct xt_entry_match **match) 136{ 137 struct xt_set_info_match *myinfo = 138 (struct xt_set_info_match *) (*match)->data; 139 struct xt_set_info *info = &myinfo->match_set; 140 141 switch (c) { 142 case '2': 143 fprintf(stderr, 144 "--set option deprecated, please use --match-set\n"); 145 case '1': /* --match-set <set> <flag>[,<flag> */ 146 if (info->dim) 147 xtables_error(PARAMETER_PROBLEM, 148 "--match-set can be specified only once"); 149 150 xtables_check_inverse(optarg, &invert, &optind, 0, argv); 151 if (invert) 152 info->flags |= IPSET_INV_MATCH; 153 154 if (!argv[optind] 155 || argv[optind][0] == '-' 156 || argv[optind][0] == '!') 157 xtables_error(PARAMETER_PROBLEM, 158 "--match-set requires two args."); 159 160 if (strlen(optarg) > IPSET_MAXNAMELEN - 1) 161 xtables_error(PARAMETER_PROBLEM, 162 "setname `%s' too long, max %d characters.", 163 optarg, IPSET_MAXNAMELEN - 1); 164 165 get_set_byname(optarg, info); 166 parse_dirs(argv[optind], info); 167 DEBUGP("parse: set index %u\n", info->index); 168 optind++; 169 170 *flags = 1; 171 break; 172 173 default: 174 return 0; 175 } 176 177 return 1; 178} 179 180static void 181print_match(const char *prefix, const struct xt_set_info *info) 182{ 183 int i; 184 char setname[IPSET_MAXNAMELEN]; 185 186 get_set_byid(setname, info->index); 187 printf("%s%s %s", 188 (info->flags & IPSET_INV_MATCH) ? "! " : "", 189 prefix, 190 setname); 191 for (i = 1; i <= info->dim; i++) { 192 printf("%s%s", 193 i == 1 ? " " : ",", 194 info->flags & (1 << i) ? "src" : "dst"); 195 } 196 printf(" "); 197} 198 199/* Prints out the matchinfo. */ 200static void 201set_print(const void *ip, const struct xt_entry_match *match, int numeric) 202{ 203 const struct xt_set_info_match *info = (const void *)match->data; 204 205 print_match("match-set", &info->match_set); 206} 207 208static void 209set_save(const void *ip, const struct xt_entry_match *match) 210{ 211 const struct xt_set_info_match *info = (const void *)match->data; 212 213 print_match("--match-set", &info->match_set); 214} 215 216static struct xtables_match set_mt_reg[] = { 217 { 218 .name = "set", 219 .revision = 0, 220 .version = XTABLES_VERSION, 221 .family = NFPROTO_IPV4, 222 .size = XT_ALIGN(sizeof(struct xt_set_info_match_v0)), 223 .userspacesize = XT_ALIGN(sizeof(struct xt_set_info_match_v0)), 224 .help = set_help, 225 .parse = set_parse_v0, 226 .final_check = set_check, 227 .print = set_print_v0, 228 .save = set_save_v0, 229 .extra_opts = set_opts, 230 }, 231 { 232 .name = "set", 233 .revision = 1, 234 .version = XTABLES_VERSION, 235 .family = NFPROTO_UNSPEC, 236 .size = XT_ALIGN(sizeof(struct xt_set_info_match)), 237 .userspacesize = XT_ALIGN(sizeof(struct xt_set_info_match)), 238 .help = set_help, 239 .parse = set_parse, 240 .final_check = set_check, 241 .print = set_print, 242 .save = set_save, 243 .extra_opts = set_opts, 244 }, 245}; 246 247void _init(void) 248{ 249 xtables_register_matches(set_mt_reg, ARRAY_SIZE(set_mt_reg)); 250} 251