libxt_set.c revision 32b8e61e4e5bd405d9ad07bf9468498dfbb19f9e
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 default: 90 return 0; 91 } 92 93 return 1; 94} 95 96static void 97print_match_v0(const char *prefix, const struct xt_set_info_v0 *info) 98{ 99 int i; 100 char setname[IPSET_MAXNAMELEN]; 101 102 get_set_byid(setname, info->index); 103 printf("%s%s %s", 104 (info->u.flags[0] & IPSET_MATCH_INV) ? "! " : "", 105 prefix, 106 setname); 107 for (i = 0; i < IPSET_DIM_MAX; i++) { 108 if (!info->u.flags[i]) 109 break; 110 printf("%s%s", 111 i == 0 ? " " : ",", 112 info->u.flags[i] & IPSET_SRC ? "src" : "dst"); 113 } 114 printf(" "); 115} 116 117/* Prints out the matchinfo. */ 118static void 119set_print_v0(const void *ip, const struct xt_entry_match *match, int numeric) 120{ 121 const struct xt_set_info_match_v0 *info = (const void *)match->data; 122 123 print_match_v0("match-set", &info->match_set); 124} 125 126static void 127set_save_v0(const void *ip, const struct xt_entry_match *match) 128{ 129 const struct xt_set_info_match_v0 *info = (const void *)match->data; 130 131 print_match_v0("--match-set", &info->match_set); 132} 133 134static int 135set_parse(int c, char **argv, int invert, unsigned int *flags, 136 const void *entry, struct xt_entry_match **match) 137{ 138 struct xt_set_info_match *myinfo = 139 (struct xt_set_info_match *) (*match)->data; 140 struct xt_set_info *info = &myinfo->match_set; 141 142 switch (c) { 143 case '2': 144 fprintf(stderr, 145 "--set option deprecated, please use --match-set\n"); 146 case '1': /* --match-set <set> <flag>[,<flag> */ 147 if (info->dim) 148 xtables_error(PARAMETER_PROBLEM, 149 "--match-set can be specified only once"); 150 151 xtables_check_inverse(optarg, &invert, &optind, 0, argv); 152 if (invert) 153 info->flags |= IPSET_INV_MATCH; 154 155 if (!argv[optind] 156 || argv[optind][0] == '-' 157 || argv[optind][0] == '!') 158 xtables_error(PARAMETER_PROBLEM, 159 "--match-set requires two args."); 160 161 if (strlen(optarg) > IPSET_MAXNAMELEN - 1) 162 xtables_error(PARAMETER_PROBLEM, 163 "setname `%s' too long, max %d characters.", 164 optarg, IPSET_MAXNAMELEN - 1); 165 166 get_set_byname(optarg, info); 167 parse_dirs(argv[optind], info); 168 DEBUGP("parse: set index %u\n", info->index); 169 optind++; 170 171 *flags = 1; 172 break; 173 174 default: 175 return 0; 176 } 177 178 return 1; 179} 180 181static void 182print_match(const char *prefix, const struct xt_set_info *info) 183{ 184 int i; 185 char setname[IPSET_MAXNAMELEN]; 186 187 get_set_byid(setname, info->index); 188 printf("%s%s %s", 189 (info->flags & IPSET_INV_MATCH) ? "! " : "", 190 prefix, 191 setname); 192 for (i = 1; i <= info->dim; i++) { 193 printf("%s%s", 194 i == 1 ? " " : ",", 195 info->flags & (1 << i) ? "src" : "dst"); 196 } 197 printf(" "); 198} 199 200/* Prints out the matchinfo. */ 201static void 202set_print(const void *ip, const struct xt_entry_match *match, int numeric) 203{ 204 const struct xt_set_info_match *info = (const void *)match->data; 205 206 print_match("match-set", &info->match_set); 207} 208 209static void 210set_save(const void *ip, const struct xt_entry_match *match) 211{ 212 const struct xt_set_info_match *info = (const void *)match->data; 213 214 print_match("--match-set", &info->match_set); 215} 216 217static struct xtables_match set_mt_reg[] = { 218 { 219 .name = "set", 220 .revision = 0, 221 .version = XTABLES_VERSION, 222 .family = NFPROTO_IPV4, 223 .size = XT_ALIGN(sizeof(struct xt_set_info_match_v0)), 224 .userspacesize = XT_ALIGN(sizeof(struct xt_set_info_match_v0)), 225 .help = set_help, 226 .parse = set_parse_v0, 227 .final_check = set_check, 228 .print = set_print_v0, 229 .save = set_save_v0, 230 .extra_opts = set_opts, 231 }, 232 { 233 .name = "set", 234 .revision = 1, 235 .version = XTABLES_VERSION, 236 .family = NFPROTO_UNSPEC, 237 .size = XT_ALIGN(sizeof(struct xt_set_info_match)), 238 .userspacesize = XT_ALIGN(sizeof(struct xt_set_info_match)), 239 .help = set_help, 240 .parse = set_parse, 241 .final_check = set_check, 242 .print = set_print, 243 .save = set_save, 244 .extra_opts = set_opts, 245 }, 246}; 247 248void _init(void) 249{ 250 xtables_register_matches(set_mt_reg, ARRAY_SIZE(set_mt_reg)); 251} 252