Fork for IVI and add .changes file
[profile/ivi/iptables.git] / extensions / libxt_set.c
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 <stdio.h>
13 #include <netdb.h>
14 #include <string.h>
15 #include <stdlib.h>
16 #include <getopt.h>
17 #include <ctype.h>
18 #include <errno.h>
19
20 #include <xtables.h>
21 #include <linux/netfilter/xt_set.h>
22 #include "libxt_set.h"
23
24 static void
25 set_help(void)
26 {
27         printf("set match options:\n"
28                " [!] --match-set name flags\n"
29                "                 'name' is the set name from to match,\n" 
30                "                 'flags' are the comma separated list of\n"
31                "                 'src' and 'dst' specifications.\n");
32 }
33
34 static const struct option set_opts[] = {
35         { .name = "match-set", .has_arg = true, .val = '1'},
36         { .name = "set",       .has_arg = true, .val = '2'},
37         { .name = NULL }
38 };
39
40 static void
41 set_check(unsigned int flags)
42 {
43         if (!flags)
44                 xtables_error(PARAMETER_PROBLEM,
45                         "You must specify `--match-set' with proper arguments");
46 }
47
48 static int
49 set_parse_v0(int c, char **argv, int invert, unsigned int *flags,
50              const void *entry, struct xt_entry_match **match)
51 {
52         struct xt_set_info_match_v0 *myinfo = 
53                 (struct xt_set_info_match_v0 *) (*match)->data;
54         struct xt_set_info_v0 *info = &myinfo->match_set;
55
56         switch (c) {
57         case '2':
58                 fprintf(stderr,
59                         "--set option deprecated, please use --match-set\n");
60         case '1':               /* --match-set <set> <flag>[,<flag> */
61                 if (info->u.flags[0])
62                         xtables_error(PARAMETER_PROBLEM,
63                                       "--match-set can be specified only once");
64
65                 xtables_check_inverse(optarg, &invert, &optind, 0, argv);
66                 if (invert)
67                         info->u.flags[0] |= IPSET_MATCH_INV;
68
69                 if (!argv[optind]
70                     || argv[optind][0] == '-'
71                     || argv[optind][0] == '!')
72                         xtables_error(PARAMETER_PROBLEM,
73                                       "--match-set requires two args.");
74
75                 if (strlen(optarg) > IPSET_MAXNAMELEN - 1)
76                         xtables_error(PARAMETER_PROBLEM,
77                                       "setname `%s' too long, max %d characters.",
78                                       optarg, IPSET_MAXNAMELEN - 1);
79
80                 get_set_byname(optarg, (struct xt_set_info *)info);
81                 parse_dirs_v0(argv[optind], info);
82                 DEBUGP("parse: set index %u\n", info->index);
83                 optind++;
84                 
85                 *flags = 1;
86                 break;
87
88         default:
89                 return 0;
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         printf(" ");
114 }
115
116 /* Prints out the matchinfo. */
117 static void
118 set_print_v0(const void *ip, const struct xt_entry_match *match, int numeric)
119 {
120         const struct xt_set_info_match_v0 *info = (const void *)match->data;
121
122         print_match_v0("match-set", &info->match_set);
123 }
124
125 static void
126 set_save_v0(const void *ip, const struct xt_entry_match *match)
127 {
128         const struct xt_set_info_match_v0 *info = (const void *)match->data;
129
130         print_match_v0("--match-set", &info->match_set);
131 }
132
133 static int
134 set_parse(int c, char **argv, int invert, unsigned int *flags,
135           const void *entry, struct xt_entry_match **match)
136 {
137         struct xt_set_info_match *myinfo = 
138                 (struct xt_set_info_match *) (*match)->data;
139         struct xt_set_info *info = &myinfo->match_set;
140
141         switch (c) {
142         case '2':
143                 fprintf(stderr,
144                         "--set option deprecated, please use --match-set\n");
145         case '1':               /* --match-set <set> <flag>[,<flag> */
146                 if (info->dim)
147                         xtables_error(PARAMETER_PROBLEM,
148                                       "--match-set can be specified only once");
149
150                 xtables_check_inverse(optarg, &invert, &optind, 0, argv);
151                 if (invert)
152                         info->flags |= IPSET_INV_MATCH;
153
154                 if (!argv[optind]
155                     || argv[optind][0] == '-'
156                     || argv[optind][0] == '!')
157                         xtables_error(PARAMETER_PROBLEM,
158                                       "--match-set requires two args.");
159
160                 if (strlen(optarg) > IPSET_MAXNAMELEN - 1)
161                         xtables_error(PARAMETER_PROBLEM,
162                                       "setname `%s' too long, max %d characters.",
163                                       optarg, IPSET_MAXNAMELEN - 1);
164
165                 get_set_byname(optarg, info);
166                 parse_dirs(argv[optind], info);
167                 DEBUGP("parse: set index %u\n", info->index);
168                 optind++;
169                 
170                 *flags = 1;
171                 break;
172
173         default:
174                 return 0;
175         }
176
177         return 1;
178 }
179
180 static void
181 print_match(const char *prefix, const struct xt_set_info *info)
182 {
183         int i;
184         char setname[IPSET_MAXNAMELEN];
185
186         get_set_byid(setname, info->index);
187         printf("%s%s %s", 
188                (info->flags & IPSET_INV_MATCH) ? "! " : "",
189                prefix,
190                setname); 
191         for (i = 1; i <= info->dim; i++) {              
192                 printf("%s%s",
193                        i == 1 ? " " : ",",
194                        info->flags & (1 << i) ? "src" : "dst");
195         }
196         printf(" ");
197 }
198
199 /* Prints out the matchinfo. */
200 static void
201 set_print(const void *ip, const struct xt_entry_match *match, int numeric)
202 {
203         const struct xt_set_info_match *info = (const void *)match->data;
204
205         print_match("match-set", &info->match_set);
206 }
207
208 static void
209 set_save(const void *ip, const struct xt_entry_match *match)
210 {
211         const struct xt_set_info_match *info = (const void *)match->data;
212
213         print_match("--match-set", &info->match_set);
214 }
215
216 static struct xtables_match set_mt_reg[] = {
217         {
218                 .name           = "set",
219                 .revision       = 0,
220                 .version        = XTABLES_VERSION,
221                 .family         = NFPROTO_IPV4,
222                 .size           = XT_ALIGN(sizeof(struct xt_set_info_match_v0)),
223                 .userspacesize  = XT_ALIGN(sizeof(struct xt_set_info_match_v0)),
224                 .help           = set_help,
225                 .parse          = set_parse_v0,
226                 .final_check    = set_check,
227                 .print          = set_print_v0,
228                 .save           = set_save_v0,
229                 .extra_opts     = set_opts,
230         },
231         {
232                 .name           = "set",
233                 .revision       = 1,
234                 .version        = XTABLES_VERSION,
235                 .family         = NFPROTO_UNSPEC,
236                 .size           = XT_ALIGN(sizeof(struct xt_set_info_match)),
237                 .userspacesize  = XT_ALIGN(sizeof(struct xt_set_info_match)),
238                 .help           = set_help,
239                 .parse          = set_parse,
240                 .final_check    = set_check,
241                 .print          = set_print,
242                 .save           = set_save,
243                 .extra_opts     = set_opts,
244         },
245 };
246
247 void _init(void)
248 {
249         xtables_register_matches(set_mt_reg, ARRAY_SIZE(set_mt_reg));
250 }