blob: 7ec0c31cf596fd090212d71d4b7e5178e5aaca13 [file] [log] [blame]
Joszef Kadlecsikb9a49382004-12-01 09:11:33 +00001/* 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-2004 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
Joszef Kadlecsik9c50ebe2004-02-09 13:47:01 +000011/* Shared library add-on to iptables to add IP set mangling target. */
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
Jan Engelhardt5d9678a2008-11-20 10:15:35 +010019#include <xtables.h>
Joszef Kadlecsik9c50ebe2004-02-09 13:47:01 +000020#include <linux/netfilter_ipv4/ip_tables.h>
Joszef Kadlecsik9c50ebe2004-02-09 13:47:01 +000021#include <linux/netfilter_ipv4/ip_set.h>
22#include <linux/netfilter_ipv4/ipt_set.h>
Joszef Kadlecsikb9a49382004-12-01 09:11:33 +000023#include "libipt_set.h"
Joszef Kadlecsik9c50ebe2004-02-09 13:47:01 +000024
Jan Engelhardt1d5b63d2007-10-04 16:29:00 +000025static void SET_help(void)
Joszef Kadlecsik9c50ebe2004-02-09 13:47:01 +000026{
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +020027 printf("SET target options:\n"
Joszef Kadlecsikb9a49382004-12-01 09:11:33 +000028 " --add-set name flags\n"
29 " --del-set name flags\n"
Joszef Kadlecsik9c50ebe2004-02-09 13:47:01 +000030 " add/del src/dst IP/port from/to named sets,\n"
31 " where flags are the comma separated list of\n"
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +020032 " 'src' and 'dst'.\n");
Joszef Kadlecsik9c50ebe2004-02-09 13:47:01 +000033}
34
Jan Engelhardt1d5b63d2007-10-04 16:29:00 +000035static const struct option SET_opts[] = {
Patrick McHardy0ea82bc2008-06-07 15:15:29 +020036 {"add-set", 1, NULL, '1'},
37 {"del-set", 1, NULL, '2'},
38 { }
Joszef Kadlecsik9c50ebe2004-02-09 13:47:01 +000039};
40
Jan Engelhardt1d5b63d2007-10-04 16:29:00 +000041static void SET_init(struct xt_entry_target *target)
Joszef Kadlecsik9c50ebe2004-02-09 13:47:01 +000042{
43 struct ipt_set_info_target *info =
44 (struct ipt_set_info_target *) target->data;
45
46 memset(info, 0, sizeof(struct ipt_set_info_target));
Joszef Kadlecsikb9a49382004-12-01 09:11:33 +000047 info->add_set.index =
48 info->del_set.index = IP_SET_INVALID_ID;
Joszef Kadlecsik9c50ebe2004-02-09 13:47:01 +000049
Joszef Kadlecsik9c50ebe2004-02-09 13:47:01 +000050}
51
Joszef Kadlecsikb9a49382004-12-01 09:11:33 +000052static void
53parse_target(char **argv, int invert, unsigned int *flags,
54 struct ipt_set_info *info, const char *what)
55{
56 if (info->flags[0])
57 exit_error(PARAMETER_PROBLEM,
58 "--%s can be specified only once", what);
59
60 if (check_inverse(optarg, &invert, NULL, 0))
61 exit_error(PARAMETER_PROBLEM,
62 "Unexpected `!' after --%s", what);
63
64 if (!argv[optind]
65 || argv[optind][0] == '-' || argv[optind][0] == '!')
66 exit_error(PARAMETER_PROBLEM,
67 "--%s requires two args.", what);
68
69 if (strlen(argv[optind-1]) > IP_SET_MAXNAMELEN - 1)
70 exit_error(PARAMETER_PROBLEM,
71 "setname `%s' too long, max %d characters.",
72 argv[optind-1], IP_SET_MAXNAMELEN - 1);
73
74 get_set_byname(argv[optind - 1], info);
75 parse_bindings(argv[optind], info);
76 optind++;
77
78 *flags = 1;
79}
80
Jan Engelhardt1d5b63d2007-10-04 16:29:00 +000081static int SET_parse(int c, char **argv, int invert, unsigned int *flags,
82 const void *entry, struct xt_entry_target **target)
Joszef Kadlecsik9c50ebe2004-02-09 13:47:01 +000083{
84 struct ipt_set_info_target *myinfo =
85 (struct ipt_set_info_target *) (*target)->data;
Joszef Kadlecsik9c50ebe2004-02-09 13:47:01 +000086
87 switch (c) {
Joszef Kadlecsikb9a49382004-12-01 09:11:33 +000088 case '1': /* --add-set <set> <flags> */
89 parse_target(argv, invert, flags,
90 &myinfo->add_set, "add-set");
Joszef Kadlecsik9c50ebe2004-02-09 13:47:01 +000091 break;
92 case '2': /* --del-set <set>[:<flags>] <flags> */
Joszef Kadlecsikb9a49382004-12-01 09:11:33 +000093 parse_target(argv, invert, flags,
94 &myinfo->del_set, "del-set");
Joszef Kadlecsik9c50ebe2004-02-09 13:47:01 +000095 break;
96
97 default:
98 return 0;
99 }
100 return 1;
101}
102
Jan Engelhardt1d5b63d2007-10-04 16:29:00 +0000103static void SET_check(unsigned int flags)
Joszef Kadlecsik9c50ebe2004-02-09 13:47:01 +0000104{
105 if (!flags)
106 exit_error(PARAMETER_PROBLEM,
107 "You must specify either `--add-set' or `--del-set'");
108}
109
110static void
111print_target(const char *prefix, const struct ipt_set_info *info)
112{
113 int i;
114 char setname[IP_SET_MAXNAMELEN];
Michal Pokrywkab9e814c2005-03-18 08:05:10 +0000115
116 if (info->index == IP_SET_INVALID_ID)
117 return;
Joszef Kadlecsikb9a49382004-12-01 09:11:33 +0000118 get_set_byid(setname, info->index);
119 printf("%s %s", prefix, setname);
120 for (i = 0; i < IP_SET_MAX_BINDINGS; i++) {
121 if (!info->flags[i])
122 break;
123 printf("%s%s",
124 i == 0 ? " " : ",",
125 info->flags[i] & IPSET_SRC ? "src" : "dst");
Joszef Kadlecsik9c50ebe2004-02-09 13:47:01 +0000126 }
Joszef Kadlecsikb9a49382004-12-01 09:11:33 +0000127 printf(" ");
Joszef Kadlecsik9c50ebe2004-02-09 13:47:01 +0000128}
129
Jan Engelhardt1d5b63d2007-10-04 16:29:00 +0000130static void SET_print(const void *ip, const struct xt_entry_target *target,
131 int numeric)
Joszef Kadlecsik9c50ebe2004-02-09 13:47:01 +0000132{
133 struct ipt_set_info_target *info =
134 (struct ipt_set_info_target *) target->data;
135
136 print_target("add-set", &info->add_set);
137 print_target("del-set", &info->del_set);
138}
139
Jan Engelhardt1d5b63d2007-10-04 16:29:00 +0000140static void SET_save(const void *ip, const struct xt_entry_target *target)
Joszef Kadlecsik9c50ebe2004-02-09 13:47:01 +0000141{
142 struct ipt_set_info_target *info =
143 (struct ipt_set_info_target *) target->data;
144
145 print_target("--add-set", &info->add_set);
146 print_target("--del-set", &info->del_set);
147}
148
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +0200149static struct xtables_target set_tg_reg = {
Joszef Kadlecsik9c50ebe2004-02-09 13:47:01 +0000150 .name = "SET",
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +0200151 .version = XTABLES_VERSION,
Jan Engelhardt03d99482008-11-18 12:27:54 +0100152 .family = NFPROTO_IPV4,
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +0200153 .size = XT_ALIGN(sizeof(struct ipt_set_info_target)),
154 .userspacesize = XT_ALIGN(sizeof(struct ipt_set_info_target)),
Jan Engelhardt1d5b63d2007-10-04 16:29:00 +0000155 .help = SET_help,
156 .init = SET_init,
157 .parse = SET_parse,
158 .final_check = SET_check,
159 .print = SET_print,
160 .save = SET_save,
161 .extra_opts = SET_opts,
Joszef Kadlecsik9c50ebe2004-02-09 13:47:01 +0000162};
163
164void _init(void)
165{
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +0200166 xtables_register_target(&set_tg_reg);
Joszef Kadlecsik9c50ebe2004-02-09 13:47:01 +0000167}