Home | History | Annotate | Download | only in extensions
      1 /* Copyright (C) 2000-2002 Joakim Axelsson <gozem (at) linux.nu>
      2  *                         Patrick Schaaf <bof (at) bof.de>
      3  *                         Martin Josefsson <gandalf (at) wlug.westbo.se>
      4  * Copyright (C) 2003-2010 Jozsef Kadlecsik <kadlec (at) 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 
     27 static void
     28 set_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 
     37 static 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 
     43 static void
     44 set_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 
     51 static int
     52 set_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 
     95 static void
     96 print_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. */
    116 static void
    117 set_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 
    124 static void
    125 set_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 
    138 static int
    139 set_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 
    182 static void
    183 print_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. */
    201 static void
    202 set_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 
    209 static void
    210 set_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 
    217 static 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 
    248 void _init(void)
    249 {
    250 	xtables_register_matches(set_mt_reg, ARRAY_SIZE(set_mt_reg));
    251 }
    252