libxt_SET.c revision 73866357e4a7a0fdc1b293bf8863fee2bd56da9e
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 mangling target. */ 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 20#include <xtables.h> 21#include <linux/netfilter/xt_set.h> 22#include "libxt_set.h" 23 24static void 25set_target_help(void) 26{ 27 printf("SET target options:\n" 28 " --add-set name flags\n" 29 " --del-set name flags\n" 30 " add/del src/dst IP/port from/to named sets,\n" 31 " where flags are the comma separated list of\n" 32 " 'src' and 'dst' specifications.\n"); 33} 34 35static const struct option set_target_opts[] = { 36 {.name = "add-set", .has_arg = true, .val = '1'}, 37 {.name = "del-set", .has_arg = true, .val = '2'}, 38 XT_GETOPT_TABLEEND, 39}; 40 41static void 42set_target_check(unsigned int flags) 43{ 44 if (!flags) 45 xtables_error(PARAMETER_PROBLEM, 46 "You must specify either `--add-set' or `--del-set'"); 47} 48 49static void 50set_target_init_v0(struct xt_entry_target *target) 51{ 52 struct xt_set_info_target_v0 *info = 53 (struct xt_set_info_target_v0 *) target->data; 54 55 info->add_set.index = 56 info->del_set.index = IPSET_INVALID_ID; 57 58} 59 60static void 61parse_target_v0(char **argv, int invert, unsigned int *flags, 62 struct xt_set_info_v0 *info, const char *what) 63{ 64 if (info->u.flags[0]) 65 xtables_error(PARAMETER_PROBLEM, 66 "--%s can be specified only once", what); 67 68 if (xtables_check_inverse(optarg, &invert, NULL, 0, argv)) 69 xtables_error(PARAMETER_PROBLEM, 70 "Unexpected `!' after --%s", what); 71 72 if (!argv[optind] 73 || argv[optind][0] == '-' || argv[optind][0] == '!') 74 xtables_error(PARAMETER_PROBLEM, 75 "--%s requires two args.", what); 76 77 if (strlen(optarg) > IPSET_MAXNAMELEN - 1) 78 xtables_error(PARAMETER_PROBLEM, 79 "setname `%s' too long, max %d characters.", 80 optarg, IPSET_MAXNAMELEN - 1); 81 82 get_set_byname(optarg, (struct xt_set_info *)info); 83 parse_dirs_v0(argv[optind], info); 84 optind++; 85 86 *flags = 1; 87} 88 89static int 90set_target_parse_v0(int c, char **argv, int invert, unsigned int *flags, 91 const void *entry, struct xt_entry_target **target) 92{ 93 struct xt_set_info_target_v0 *myinfo = 94 (struct xt_set_info_target_v0 *) (*target)->data; 95 96 switch (c) { 97 case '1': /* --add-set <set> <flags> */ 98 parse_target_v0(argv, invert, flags, 99 &myinfo->add_set, "add-set"); 100 break; 101 case '2': /* --del-set <set>[:<flags>] <flags> */ 102 parse_target_v0(argv, invert, flags, 103 &myinfo->del_set, "del-set"); 104 break; 105 } 106 return 1; 107} 108 109static void 110print_target_v0(const char *prefix, const struct xt_set_info_v0 *info) 111{ 112 int i; 113 char setname[IPSET_MAXNAMELEN]; 114 115 if (info->index == IPSET_INVALID_ID) 116 return; 117 get_set_byid(setname, info->index); 118 printf(" %s %s", prefix, setname); 119 for (i = 0; i < IPSET_DIM_MAX; i++) { 120 if (!info->u.flags[i]) 121 break; 122 printf("%s%s", 123 i == 0 ? " " : ",", 124 info->u.flags[i] & IPSET_SRC ? "src" : "dst"); 125 } 126} 127 128static void 129set_target_print_v0(const void *ip, const struct xt_entry_target *target, 130 int numeric) 131{ 132 const struct xt_set_info_target_v0 *info = (const void *)target->data; 133 134 print_target_v0("add-set", &info->add_set); 135 print_target_v0("del-set", &info->del_set); 136} 137 138static void 139set_target_save_v0(const void *ip, const struct xt_entry_target *target) 140{ 141 const struct xt_set_info_target_v0 *info = (const void *)target->data; 142 143 print_target_v0("--add-set", &info->add_set); 144 print_target_v0("--del-set", &info->del_set); 145} 146 147static void 148set_target_init(struct xt_entry_target *target) 149{ 150 struct xt_set_info_target *info = 151 (struct xt_set_info_target *) target->data; 152 153 info->add_set.index = 154 info->del_set.index = IPSET_INVALID_ID; 155 156} 157 158static void 159parse_target(char **argv, int invert, unsigned int *flags, 160 struct xt_set_info *info, const char *what) 161{ 162 if (info->dim) 163 xtables_error(PARAMETER_PROBLEM, 164 "--%s can be specified only once", what); 165 166 if (xtables_check_inverse(optarg, &invert, NULL, 0, argv)) 167 xtables_error(PARAMETER_PROBLEM, 168 "Unexpected `!' after --%s", what); 169 170 if (!argv[optind] 171 || argv[optind][0] == '-' || argv[optind][0] == '!') 172 xtables_error(PARAMETER_PROBLEM, 173 "--%s requires two args.", what); 174 175 if (strlen(optarg) > IPSET_MAXNAMELEN - 1) 176 xtables_error(PARAMETER_PROBLEM, 177 "setname `%s' too long, max %d characters.", 178 optarg, IPSET_MAXNAMELEN - 1); 179 180 get_set_byname(optarg, info); 181 parse_dirs(argv[optind], info); 182 optind++; 183 184 *flags = 1; 185} 186 187static int 188set_target_parse(int c, char **argv, int invert, unsigned int *flags, 189 const void *entry, struct xt_entry_target **target) 190{ 191 struct xt_set_info_target *myinfo = 192 (struct xt_set_info_target *) (*target)->data; 193 194 switch (c) { 195 case '1': /* --add-set <set> <flags> */ 196 parse_target(argv, invert, flags, 197 &myinfo->add_set, "add-set"); 198 break; 199 case '2': /* --del-set <set>[:<flags>] <flags> */ 200 parse_target(argv, invert, flags, 201 &myinfo->del_set, "del-set"); 202 break; 203 } 204 return 1; 205} 206 207static void 208print_target(const char *prefix, const struct xt_set_info *info) 209{ 210 int i; 211 char setname[IPSET_MAXNAMELEN]; 212 213 if (info->index == IPSET_INVALID_ID) 214 return; 215 get_set_byid(setname, info->index); 216 printf(" %s %s", prefix, setname); 217 for (i = 1; i <= info->dim; i++) { 218 printf("%s%s", 219 i == 1 ? " " : ",", 220 info->flags & (1 << i) ? "src" : "dst"); 221 } 222} 223 224static void 225set_target_print(const void *ip, const struct xt_entry_target *target, 226 int numeric) 227{ 228 const struct xt_set_info_target *info = (const void *)target->data; 229 230 print_target("add-set", &info->add_set); 231 print_target("del-set", &info->del_set); 232} 233 234static void 235set_target_save(const void *ip, const struct xt_entry_target *target) 236{ 237 const struct xt_set_info_target *info = (const void *)target->data; 238 239 print_target("--add-set", &info->add_set); 240 print_target("--del-set", &info->del_set); 241} 242 243static struct xtables_target set_tg_reg[] = { 244 { 245 .name = "SET", 246 .revision = 0, 247 .version = XTABLES_VERSION, 248 .family = NFPROTO_IPV4, 249 .size = XT_ALIGN(sizeof(struct xt_set_info_target_v0)), 250 .userspacesize = XT_ALIGN(sizeof(struct xt_set_info_target_v0)), 251 .help = set_target_help, 252 .init = set_target_init_v0, 253 .parse = set_target_parse_v0, 254 .final_check = set_target_check, 255 .print = set_target_print_v0, 256 .save = set_target_save_v0, 257 .extra_opts = set_target_opts, 258 }, 259 { 260 .name = "SET", 261 .revision = 1, 262 .version = XTABLES_VERSION, 263 .family = NFPROTO_UNSPEC, 264 .size = XT_ALIGN(sizeof(struct xt_set_info_target)), 265 .userspacesize = XT_ALIGN(sizeof(struct xt_set_info_target)), 266 .help = set_target_help, 267 .init = set_target_init, 268 .parse = set_target_parse, 269 .final_check = set_target_check, 270 .print = set_target_print, 271 .save = set_target_save, 272 .extra_opts = set_target_opts, 273 }, 274}; 275 276void _init(void) 277{ 278 xtables_register_targets(set_tg_reg, ARRAY_SIZE(set_tg_reg)); 279} 280