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 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 default: 107 return 0; 108 } 109 return 1; 110} 111 112static void 113print_target_v0(const char *prefix, const struct xt_set_info_v0 *info) 114{ 115 int i; 116 char setname[IPSET_MAXNAMELEN]; 117 118 if (info->index == IPSET_INVALID_ID) 119 return; 120 get_set_byid(setname, info->index); 121 printf("%s %s", prefix, setname); 122 for (i = 0; i < IPSET_DIM_MAX; i++) { 123 if (!info->u.flags[i]) 124 break; 125 printf("%s%s", 126 i == 0 ? " " : ",", 127 info->u.flags[i] & IPSET_SRC ? "src" : "dst"); 128 } 129 printf(" "); 130} 131 132static void 133set_target_print_v0(const void *ip, const struct xt_entry_target *target, 134 int numeric) 135{ 136 const struct xt_set_info_target_v0 *info = (const void *)target->data; 137 138 print_target_v0("add-set", &info->add_set); 139 print_target_v0("del-set", &info->del_set); 140} 141 142static void 143set_target_save_v0(const void *ip, const struct xt_entry_target *target) 144{ 145 const struct xt_set_info_target_v0 *info = (const void *)target->data; 146 147 print_target_v0("--add-set", &info->add_set); 148 print_target_v0("--del-set", &info->del_set); 149} 150 151static void 152set_target_init(struct xt_entry_target *target) 153{ 154 struct xt_set_info_target *info = 155 (struct xt_set_info_target *) target->data; 156 157 info->add_set.index = 158 info->del_set.index = IPSET_INVALID_ID; 159 160} 161 162static void 163parse_target(char **argv, int invert, unsigned int *flags, 164 struct xt_set_info *info, const char *what) 165{ 166 if (info->dim) 167 xtables_error(PARAMETER_PROBLEM, 168 "--%s can be specified only once", what); 169 170 if (xtables_check_inverse(optarg, &invert, NULL, 0, argv)) 171 xtables_error(PARAMETER_PROBLEM, 172 "Unexpected `!' after --%s", what); 173 174 if (!argv[optind] 175 || argv[optind][0] == '-' || argv[optind][0] == '!') 176 xtables_error(PARAMETER_PROBLEM, 177 "--%s requires two args.", what); 178 179 if (strlen(optarg) > IPSET_MAXNAMELEN - 1) 180 xtables_error(PARAMETER_PROBLEM, 181 "setname `%s' too long, max %d characters.", 182 optarg, IPSET_MAXNAMELEN - 1); 183 184 get_set_byname(optarg, info); 185 parse_dirs(argv[optind], info); 186 optind++; 187 188 *flags = 1; 189} 190 191static int 192set_target_parse(int c, char **argv, int invert, unsigned int *flags, 193 const void *entry, struct xt_entry_target **target) 194{ 195 struct xt_set_info_target *myinfo = 196 (struct xt_set_info_target *) (*target)->data; 197 198 switch (c) { 199 case '1': /* --add-set <set> <flags> */ 200 parse_target(argv, invert, flags, 201 &myinfo->add_set, "add-set"); 202 break; 203 case '2': /* --del-set <set>[:<flags>] <flags> */ 204 parse_target(argv, invert, flags, 205 &myinfo->del_set, "del-set"); 206 break; 207 208 default: 209 return 0; 210 } 211 return 1; 212} 213 214static void 215print_target(const char *prefix, const struct xt_set_info *info) 216{ 217 int i; 218 char setname[IPSET_MAXNAMELEN]; 219 220 if (info->index == IPSET_INVALID_ID) 221 return; 222 get_set_byid(setname, info->index); 223 printf("%s %s", prefix, setname); 224 for (i = 1; i <= IPSET_DIM_MAX; i++) { 225 printf("%s%s", 226 i == 1 ? " " : ",", 227 info->flags & (1 << i) ? "src" : "dst"); 228 } 229 printf(" "); 230} 231 232static void 233set_target_print(const void *ip, const struct xt_entry_target *target, 234 int numeric) 235{ 236 const struct xt_set_info_target *info = (const void *)target->data; 237 238 print_target("add-set", &info->add_set); 239 print_target("del-set", &info->del_set); 240} 241 242static void 243set_target_save(const void *ip, const struct xt_entry_target *target) 244{ 245 const struct xt_set_info_target *info = (const void *)target->data; 246 247 print_target("--add-set", &info->add_set); 248 print_target("--del-set", &info->del_set); 249} 250 251static struct xtables_target set_tg_reg[] = { 252 { 253 .name = "SET", 254 .revision = 0, 255 .version = XTABLES_VERSION, 256 .family = NFPROTO_IPV4, 257 .size = XT_ALIGN(sizeof(struct xt_set_info_target_v0)), 258 .userspacesize = XT_ALIGN(sizeof(struct xt_set_info_target_v0)), 259 .help = set_target_help, 260 .init = set_target_init_v0, 261 .parse = set_target_parse_v0, 262 .final_check = set_target_check, 263 .print = set_target_print_v0, 264 .save = set_target_save_v0, 265 .extra_opts = set_target_opts, 266 }, 267 { 268 .name = "SET", 269 .revision = 1, 270 .version = XTABLES_VERSION, 271 .family = NFPROTO_UNSPEC, 272 .size = XT_ALIGN(sizeof(struct xt_set_info_target)), 273 .userspacesize = XT_ALIGN(sizeof(struct xt_set_info_target)), 274 .help = set_target_help, 275 .init = set_target_init, 276 .parse = set_target_parse, 277 .final_check = set_target_check, 278 .print = set_target_print, 279 .save = set_target_save, 280 .extra_opts = set_target_opts, 281 }, 282}; 283 284void _init(void) 285{ 286 xtables_register_targets(set_tg_reg, ARRAY_SIZE(set_tg_reg)); 287} 288