blob: 390a7d91d63ec045e61b2b9bc33401954d7a28ca [file] [log] [blame]
lh9ed821d2023-04-07 01:36:19 -07001/* 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
11/* 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
19#include <xtables.h>
20#include <linux/netfilter_ipv4/ip_set.h>
21#include <linux/netfilter_ipv4/ipt_set.h>
22#include "libipt_set.h"
23
24static void SET_help(void)
25{
26 printf("SET target options:\n"
27 " --add-set name flags\n"
28 " --del-set name flags\n"
29 " add/del src/dst IP/port from/to named sets,\n"
30 " where flags are the comma separated list of\n"
31 " 'src' and 'dst'.\n");
32}
33
34static const struct option SET_opts[] = {
35 {"add-set", 1, NULL, '1'},
36 {"del-set", 1, NULL, '2'},
37 { }
38};
39
40static void SET_init(struct xt_entry_target *target)
41{
42 struct ipt_set_info_target *info =
43 (struct ipt_set_info_target *) target->data;
44
45 memset(info, 0, sizeof(struct ipt_set_info_target));
46 info->add_set.index =
47 info->del_set.index = IP_SET_INVALID_ID;
48
49}
50
51static void
52parse_target(char **argv, int invert, unsigned int *flags,
53 struct ipt_set_info *info, const char *what)
54{
55 if (info->flags[0])
56 xtables_error(PARAMETER_PROBLEM,
57 "--%s can be specified only once", what);
58
59 if (xtables_check_inverse(optarg, &invert, NULL, 0))
60 xtables_error(PARAMETER_PROBLEM,
61 "Unexpected `!' after --%s", what);
62
63 if (!argv[optind]
64 || argv[optind][0] == '-' || argv[optind][0] == '!')
65 xtables_error(PARAMETER_PROBLEM,
66 "--%s requires two args.", what);
67
68 if (strlen(argv[optind-1]) > IP_SET_MAXNAMELEN - 1)
69 xtables_error(PARAMETER_PROBLEM,
70 "setname `%s' too long, max %d characters.",
71 argv[optind-1], IP_SET_MAXNAMELEN - 1);
72
73 strcpy(info->setname, argv[optind - 1]);
74 parse_bindings(argv[optind], info);
75 optind++;
76
77 *flags = 1;
78}
79
80static int SET_parse(int c, char **argv, int invert, unsigned int *flags,
81 const void *entry, struct xt_entry_target **target)
82{
83 struct ipt_set_info_target *myinfo =
84 (struct ipt_set_info_target *) (*target)->data;
85
86 switch (c) {
87 case '1': /* --add-set <set> <flags> */
88 parse_target(argv, invert, flags,
89 &myinfo->add_set, "add-set");
90 break;
91 case '2': /* --del-set <set>[:<flags>] <flags> */
92 parse_target(argv, invert, flags,
93 &myinfo->del_set, "del-set");
94 break;
95
96 default:
97 return 0;
98 }
99 return 1;
100}
101
102static void SET_check(unsigned int flags)
103{
104 if (!flags)
105 xtables_error(PARAMETER_PROBLEM,
106 "You must specify either `--add-set' or `--del-set'");
107}
108
109static void
110print_target(const char *prefix, const struct ipt_set_info *info)
111{
112 int i;
113
114 printf("%s %s", prefix, info->setname);
115 for (i = 0; i < IP_SET_MAX_BINDINGS; i++) {
116 if (!info->flags[i])
117 break;
118 printf("%s%s",
119 i == 0 ? " " : ",",
120 info->flags[i] & IPSET_SRC ? "src" : "dst");
121 }
122 printf(" ");
123}
124
125static void SET_print(const void *ip, const struct xt_entry_target *target,
126 int numeric)
127{
128 struct ipt_set_info_target *info =
129 (struct ipt_set_info_target *) target->data;
130
131 print_target("add-set", &info->add_set);
132 print_target("del-set", &info->del_set);
133}
134
135static void SET_save(const void *ip, const struct xt_entry_target *target)
136{
137 struct ipt_set_info_target *info =
138 (struct ipt_set_info_target *) target->data;
139
140 print_target("--add-set", &info->add_set);
141 print_target("--del-set", &info->del_set);
142}
143
144static struct xtables_target set_tg_reg = {
145 .name = "SET",
146 .version = XTABLES_VERSION,
147 .family = NFPROTO_IPV4,
148 .size = XT_ALIGN(sizeof(struct ipt_set_info_target)),
149 .userspacesize = XT_ALIGN(sizeof(struct ipt_set_info_target)),
150 .help = SET_help,
151 .init = SET_init,
152 .parse = SET_parse,
153 .final_check = SET_check,
154 .print = SET_print,
155 .save = SET_save,
156 .extra_opts = SET_opts,
157};
158
159void _init(void)
160{
161 xtables_register_target(&set_tg_reg);
162}