1 /* Copyright 2000, 2001, 2002 Joakim Axelsson (gozem@linux.nu)
2 * Patrick Schaaf (bof@bof.de)
3 * Martin Josefsson (gandalf@wlug.westbo.se)
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include <sys/socket.h>
25 #include <netinet/in.h>
26 #include <arpa/inet.h>
27 #ifndef __always_inline
28 #define __always_inline inline
30 #include <asm/bitops.h>
31 #include <linux/if_ether.h>
33 #include <linux/netfilter_ipv4/ip_set_macipmap.h>
38 #define OPT_CREATE_FROM 0x01U
39 #define OPT_CREATE_TO 0x02U
40 #define OPT_CREATE_NETWORK 0x04U
41 #define OPT_CREATE_MATCHUNSET 0x08U
43 #define OPT_ADDDEL_IP 0x01U
44 #define OPT_ADDDEL_MAC 0x02U
46 /* Initialize the create. */
47 void create_init(void *data)
53 /* Function which parses command options; returns true if it ate an option */
54 int create_parse(int c, char *argv[], void *data, unsigned *flags)
56 struct ip_set_req_macipmap_create *mydata =
57 (struct ip_set_req_macipmap_create *) data;
63 parse_ip(optarg, &mydata->from);
65 *flags |= OPT_CREATE_FROM;
67 DP("--from %x (%s)", mydata->from,
68 ip_tostring_numeric(mydata->from));
73 parse_ip(optarg, &mydata->to);
75 *flags |= OPT_CREATE_TO;
77 DP("--to %x (%s)", mydata->to,
78 ip_tostring_numeric(mydata->to));
83 parse_ipandmask(optarg, &mydata->from, &mydata->to);
85 /* Make to the last of from + mask */
86 mydata->to = mydata->from | (~mydata->to);
88 *flags |= OPT_CREATE_NETWORK;
90 DP("--network from %x (%s)",
91 mydata->from, ip_tostring_numeric(mydata->from));
92 DP("--network to %x (%s)",
93 mydata->to, ip_tostring_numeric(mydata->to));
98 mydata->flags |= IPSET_MACIP_MATCHUNSET;
100 *flags |= OPT_CREATE_MATCHUNSET;
113 /* Final check; exit if not ok. */
114 void create_final(void *data, unsigned int flags)
116 struct ip_set_req_macipmap_create *mydata =
117 (struct ip_set_req_macipmap_create *) data;
120 exit_error(PARAMETER_PROBLEM,
121 "Need to specify --from and --to, or --network\n");
123 if (flags & OPT_CREATE_NETWORK) {
125 if ((flags & OPT_CREATE_FROM) || (flags & OPT_CREATE_TO))
126 exit_error(PARAMETER_PROBLEM,
127 "Can't specify --from or --to with --network\n");
130 if ((flags & OPT_CREATE_FROM) == 0
131 || (flags & OPT_CREATE_TO) == 0)
132 exit_error(PARAMETER_PROBLEM,
133 "Need to specify both --from and --to\n");
137 DP("from : %x to: %x diff: %d match unset: %d", mydata->from,
138 mydata->to, mydata->to - mydata->from,
139 flags & OPT_CREATE_MATCHUNSET);
141 if (mydata->from > mydata->to)
142 exit_error(PARAMETER_PROBLEM,
143 "From can't be lower than to.\n");
145 if (mydata->to - mydata->from > MAX_RANGE)
146 exit_error(PARAMETER_PROBLEM,
147 "Range too large. Max is %d IPs in range\n",
151 /* Create commandline options */
152 static struct option create_opts[] = {
155 {"network", 1, 0, '3'},
156 {"matchunset", 0, 0, '4'},
160 static void parse_mac(const char *mac, unsigned char *ethernet)
164 if (strlen(mac) != ETH_ALEN * 3 - 1)
165 exit_error(PARAMETER_PROBLEM, "Bad mac address `%s'", mac);
167 for (i = 0; i < ETH_ALEN; i++) {
171 number = strtol(mac + i * 3, &end, 16);
173 if (end == mac + i * 3 + 2 && number >= 0 && number <= 255)
174 ethernet[i] = number;
176 exit_error(PARAMETER_PROBLEM,
177 "Bad mac address `%s'", mac);
181 /* Add, del, test parser */
182 ip_set_ip_t adt_parser(unsigned cmd, const char *optarg, void *data)
184 struct ip_set_req_macipmap *mydata =
185 (struct ip_set_req_macipmap *) data;
186 char *saved = ipset_strdup(optarg);
187 char *ptr, *tmp = saved;
189 DP("macipmap: %p %p", optarg, data);
191 ptr = strsep(&tmp, "%");
192 parse_ip(ptr, &mydata->ip);
195 parse_mac(tmp, mydata->ethernet);
197 memset(mydata->ethernet, 0, ETH_ALEN);
207 void initheader(struct set *set, const void *data)
209 struct ip_set_req_macipmap_create *header =
210 (struct ip_set_req_macipmap_create *) data;
211 struct ip_set_macipmap *map =
212 (struct ip_set_macipmap *) set->settype->header;
214 memset(map, 0, sizeof(struct ip_set_macipmap));
215 map->first_ip = header->from;
216 map->last_ip = header->to;
217 map->flags = header->flags;
220 void printheader(struct set *set, unsigned options)
222 struct ip_set_macipmap *mysetdata =
223 (struct ip_set_macipmap *) set->settype->header;
225 printf(" from: %s", ip_tostring(mysetdata->first_ip, options));
226 printf(" to: %s", ip_tostring(mysetdata->last_ip, options));
228 if (mysetdata->flags & IPSET_MACIP_MATCHUNSET)
229 printf(" matchunset");
233 static void print_mac(unsigned char macaddress[ETH_ALEN])
237 printf("%02X", macaddress[0]);
238 for (i = 1; i < ETH_ALEN; i++)
239 printf(":%02X", macaddress[i]);
242 void printips_sorted(struct set *set, void *data, size_t len, unsigned options)
244 struct ip_set_macipmap *mysetdata =
245 (struct ip_set_macipmap *) set->settype->header;
246 struct ip_set_macip *table =
247 (struct ip_set_macip *) data;
248 u_int32_t addr = mysetdata->first_ip;
250 while (addr <= mysetdata->last_ip) {
251 if (test_bit(IPSET_MACIP_ISSET,
252 (void *)&table[addr - mysetdata->first_ip].flags)) {
253 printf("%s%%", ip_tostring(addr, options));
254 print_mac(table[addr - mysetdata->first_ip].
262 void saveheader(struct set *set, unsigned options)
264 struct ip_set_macipmap *mysetdata =
265 (struct ip_set_macipmap *) set->settype->header;
267 printf("-N %s %s --from %s",
268 set->name, set->settype->typename,
269 ip_tostring(mysetdata->first_ip, options));
270 printf(" --to %s", ip_tostring(mysetdata->last_ip, options));
272 if (mysetdata->flags & IPSET_MACIP_MATCHUNSET)
273 printf(" --matchunset");
277 void saveips(struct set *set, void *data, size_t len, unsigned options)
279 struct ip_set_macipmap *mysetdata =
280 (struct ip_set_macipmap *) set->settype->header;
281 struct ip_set_macip *table =
282 (struct ip_set_macip *) data;
283 u_int32_t addr = mysetdata->first_ip;
285 while (addr <= mysetdata->last_ip) {
286 if (test_bit(IPSET_MACIP_ISSET,
287 (void *)&table[addr - mysetdata->first_ip].flags)) {
289 set->name, ip_tostring(addr, options));
290 print_mac(table[addr - mysetdata->first_ip].
301 ("-N set macipmap --from IP --to IP [--matchunset]\n"
302 "-N set macipmap --network IP/mask [--matchunset]\n"
305 "-T set IP[%%MAC]\n");
308 static struct settype settype_macipmap = {
309 .typename = SETTYPE_NAME,
310 .protocol_version = IP_SET_PROTOCOL_VERSION,
313 .create_size = sizeof(struct ip_set_req_macipmap_create),
314 .create_init = &create_init,
315 .create_parse = &create_parse,
316 .create_final = &create_final,
317 .create_opts = create_opts,
320 .adt_size = sizeof(struct ip_set_req_macipmap),
321 .adt_parser = &adt_parser,
324 .header_size = sizeof(struct ip_set_macipmap),
325 .initheader = &initheader,
326 .printheader = &printheader,
327 .printips = &printips_sorted, /* We only have sorted version */
328 .printips_sorted = &printips_sorted,
329 .saveheader = &saveheader,
333 .bindip_tostring = &binding_ip_tostring,
334 .bindip_parse = &parse_ip,
341 settype_register(&settype_macipmap);