libxt_set.c revision e37d45ce390c2f5a7f1e64742b9100ecef0def54
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 68 xtables_check_inverse(optarg, &invert, &optind, 0, argv); 69 if (invert) 70 info->u.flags[0] |= IPSET_MATCH_INV; 71 72 if (!argv[optind] 73 || argv[optind][0] == '-' 74 || argv[optind][0] == '!') 75 xtables_error(PARAMETER_PROBLEM, 76 "--match-set requires two args."); 77 78 if (strlen(optarg) > IPSET_MAXNAMELEN - 1) 79 xtables_error(PARAMETER_PROBLEM, 80 "setname `%s' too long, max %d characters.", 81 optarg, IPSET_MAXNAMELEN - 1); 82 83 get_set_byname(optarg, (struct xt_set_info *)info); 84 parse_dirs_v0(argv[optind], info); 85 DEBUGP("parse: set index %u\n", info->index); 86 optind++; 87 88 *flags = 1; 89 break; 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} 114 115/* Prints out the matchinfo. */ 116static void 117set_print_v0(const void *ip, const struct xt_entry_match *match, int numeric) 118{ 119 const struct xt_set_info_match_v0 *info = (const void *)match->data; 120 121 print_match_v0("match-set", &info->match_set); 122} 123 124static void 125set_save_v0(const void *ip, const struct xt_entry_match *match) 126{ 127 const struct xt_set_info_match_v0 *info = (const void *)match->data; 128 129 print_match_v0("--match-set", &info->match_set); 130} 131 132/* Revision 1 */ 133 134#define set_help_v1 set_help_v0 135#define set_opts_v1 set_opts_v0 136#define set_check_v1 set_check_v0 137 138static int 139set_parse_v1(int c, char **argv, int invert, unsigned int *flags, 140 const void *entry, struct xt_entry_match **match) 141{ 142 struct xt_set_info_match_v1 *myinfo = 143 (struct xt_set_info_match_v1 *) (*match)->data; 144 struct xt_set_info *info = &myinfo->match_set; 145 146 switch (c) { 147 case '2': 148 fprintf(stderr, 149 "--set option deprecated, please use --match-set\n"); 150 case '1': /* --match-set <set> <flag>[,<flag> */ 151 if (info->dim) 152 xtables_error(PARAMETER_PROBLEM, 153 "--match-set can be specified only once"); 154 155 xtables_check_inverse(optarg, &invert, &optind, 0, argv); 156 if (invert) 157 info->flags |= IPSET_INV_MATCH; 158 159 if (!argv[optind] 160 || argv[optind][0] == '-' 161 || argv[optind][0] == '!') 162 xtables_error(PARAMETER_PROBLEM, 163 "--match-set requires two args."); 164 165 if (strlen(optarg) > IPSET_MAXNAMELEN - 1) 166 xtables_error(PARAMETER_PROBLEM, 167 "setname `%s' too long, max %d characters.", 168 optarg, IPSET_MAXNAMELEN - 1); 169 170 get_set_byname(optarg, info); 171 parse_dirs(argv[optind], info); 172 DEBUGP("parse: set index %u\n", info->index); 173 optind++; 174 175 *flags = 1; 176 break; 177 } 178 179 return 1; 180} 181 182static void 183print_match(const char *prefix, const struct xt_set_info *info) 184{ 185 int i; 186 char setname[IPSET_MAXNAMELEN]; 187 188 get_set_byid(setname, info->index); 189 printf("%s %s %s", 190 (info->flags & IPSET_INV_MATCH) ? " !" : "", 191 prefix, 192 setname); 193 for (i = 1; i <= info->dim; i++) { 194 printf("%s%s", 195 i == 1 ? " " : ",", 196 info->flags & (1 << i) ? "src" : "dst"); 197 } 198} 199 200/* Prints out the matchinfo. */ 201static void 202set_print_v1(const void *ip, const struct xt_entry_match *match, int numeric) 203{ 204 const struct xt_set_info_match_v1 *info = (const void *)match->data; 205 206 print_match("match-set", &info->match_set); 207} 208 209static void 210set_save_v1(const void *ip, const struct xt_entry_match *match) 211{ 212 const struct xt_set_info_match_v1 *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_v0, 226 .parse = set_parse_v0, 227 .final_check = set_check_v0, 228 .print = set_print_v0, 229 .save = set_save_v0, 230 .extra_opts = set_opts_v0, 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_v1)), 238 .userspacesize = XT_ALIGN(sizeof(struct xt_set_info_match_v1)), 239 .help = set_help_v1, 240 .parse = set_parse_v1, 241 .final_check = set_check_v1, 242 .print = set_print_v1, 243 .save = set_save_v1, 244 .extra_opts = set_opts_v1, 245 }, 246}; 247 248void _init(void) 249{ 250 xtables_register_matches(set_mt_reg, ARRAY_SIZE(set_mt_reg)); 251} 252