blob: 8312d04268a923a617755ca73ed487fc17ada856 [file] [log] [blame]
Jan Engelhardta8ad34c2008-01-29 13:37:21 +00001/*
2 * libxt_conntrack
3 * Shared library add-on to iptables for conntrack matching support.
4 *
5 * GPL (C) 2001 Marc Boucher (marc@mbsi.ca).
6 * Copyright © CC Computer Consultants GmbH, 2007 - 2008
7 * Jan Engelhardt <jengelh@computergmbh.de>
Marc Boucher5054e852002-01-19 10:59:12 +00008 */
Jan Engelhardta8ad34c2008-01-29 13:37:21 +00009#include <sys/socket.h>
10#include <sys/types.h>
Marc Boucher5054e852002-01-19 10:59:12 +000011#include <ctype.h>
Jan Engelhardta80b6042008-01-20 13:34:07 +000012#include <getopt.h>
13#include <netdb.h>
Jan Engelhardta8ad34c2008-01-29 13:37:21 +000014#include <stdbool.h>
Jan Engelhardtb97b4212009-06-25 18:46:37 +020015#include <stddef.h>
Jan Engelhardta80b6042008-01-20 13:34:07 +000016#include <stdio.h>
17#include <stdlib.h>
18#include <string.h>
Jan Engelhardt08b16162008-01-20 13:36:08 +000019#include <xtables.h>
Jan Engelhardta80b6042008-01-20 13:34:07 +000020#include <linux/netfilter.h>
21#include <linux/netfilter/xt_conntrack.h>
Patrick McHardy40d54752007-04-18 07:00:36 +000022#include <linux/netfilter/nf_conntrack_common.h>
Jan Engelhardta8ad34c2008-01-29 13:37:21 +000023#include <arpa/inet.h>
Harald Welte4dc734c2003-10-07 18:55:13 +000024
Jan Engelhardt350661a2010-01-31 22:42:52 +010025struct ip_conntrack_old_tuple {
26 struct {
27 __be32 ip;
28 union {
29 __u16 all;
30 } u;
31 } src;
32
33 struct {
34 __be32 ip;
35 union {
36 __u16 all;
37 } u;
38
39 /* The protocol. */
40 __u16 protonum;
41 } dst;
42};
43
44struct xt_conntrack_info {
45 unsigned int statemask, statusmask;
46
47 struct ip_conntrack_old_tuple tuple[IP_CT_DIR_MAX];
48 struct in_addr sipmsk[IP_CT_DIR_MAX], dipmsk[IP_CT_DIR_MAX];
49
50 unsigned long expires_min, expires_max;
51
52 /* Flags word */
Jan Engelhardt7ac40522011-01-07 12:34:04 +010053 uint8_t flags;
Jan Engelhardt350661a2010-01-31 22:42:52 +010054 /* Inverse flags */
Jan Engelhardt7ac40522011-01-07 12:34:04 +010055 uint8_t invflags;
Jan Engelhardt350661a2010-01-31 22:42:52 +010056};
57
Jan Engelhardta80b6042008-01-20 13:34:07 +000058static void conntrack_mt_help(void)
Marc Boucher5054e852002-01-19 10:59:12 +000059{
60 printf(
Jan Engelhardta80b6042008-01-20 13:34:07 +000061"conntrack match options:\n"
62"[!] --ctstate {INVALID|ESTABLISHED|NEW|RELATED|UNTRACKED|SNAT|DNAT}[,...]\n"
63" State(s) to match\n"
64"[!] --ctproto proto Protocol to match; by number or name, e.g. \"tcp\"\n"
65"[!] --ctorigsrc address[/mask]\n"
66"[!] --ctorigdst address[/mask]\n"
67"[!] --ctreplsrc address[/mask]\n"
68"[!] --ctrepldst address[/mask]\n"
69" Original/Reply source/destination address\n"
Jan Engelhardta8ad34c2008-01-29 13:37:21 +000070"[!] --ctorigsrcport port\n"
71"[!] --ctorigdstport port\n"
72"[!] --ctreplsrcport port\n"
73"[!] --ctrepldstport port\n"
74" TCP/UDP/SCTP orig./reply source/destination port\n"
Jan Engelhardta80b6042008-01-20 13:34:07 +000075"[!] --ctstatus {NONE|EXPECTED|SEEN_REPLY|ASSURED|CONFIRMED}[,...]\n"
76" Status(es) to match\n"
77"[!] --ctexpire time[:time] Match remaining lifetime in seconds against\n"
78" value or range of values (inclusive)\n"
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +020079" --ctdir {ORIGINAL|REPLY} Flow direction of packet\n");
Marc Boucher5054e852002-01-19 10:59:12 +000080}
81
Jan Engelhardta8ad34c2008-01-29 13:37:21 +000082static const struct option conntrack_mt_opts_v0[] = {
Jan Engelhardta80b6042008-01-20 13:34:07 +000083 {.name = "ctstate", .has_arg = true, .val = '1'},
84 {.name = "ctproto", .has_arg = true, .val = '2'},
85 {.name = "ctorigsrc", .has_arg = true, .val = '3'},
86 {.name = "ctorigdst", .has_arg = true, .val = '4'},
87 {.name = "ctreplsrc", .has_arg = true, .val = '5'},
88 {.name = "ctrepldst", .has_arg = true, .val = '6'},
89 {.name = "ctstatus", .has_arg = true, .val = '7'},
90 {.name = "ctexpire", .has_arg = true, .val = '8'},
Jan Engelhardt32b8e612010-07-23 21:16:14 +020091 XT_GETOPT_TABLEEND,
Marc Boucher5054e852002-01-19 10:59:12 +000092};
93
Jan Engelhardta8ad34c2008-01-29 13:37:21 +000094static const struct option conntrack_mt_opts[] = {
95 {.name = "ctstate", .has_arg = true, .val = '1'},
96 {.name = "ctproto", .has_arg = true, .val = '2'},
97 {.name = "ctorigsrc", .has_arg = true, .val = '3'},
98 {.name = "ctorigdst", .has_arg = true, .val = '4'},
99 {.name = "ctreplsrc", .has_arg = true, .val = '5'},
100 {.name = "ctrepldst", .has_arg = true, .val = '6'},
101 {.name = "ctstatus", .has_arg = true, .val = '7'},
102 {.name = "ctexpire", .has_arg = true, .val = '8'},
103 {.name = "ctorigsrcport", .has_arg = true, .val = 'a'},
104 {.name = "ctorigdstport", .has_arg = true, .val = 'b'},
105 {.name = "ctreplsrcport", .has_arg = true, .val = 'c'},
106 {.name = "ctrepldstport", .has_arg = true, .val = 'd'},
107 {.name = "ctdir", .has_arg = true, .val = 'e'},
Max Kellermann9ee386a2008-01-29 13:48:05 +0000108 {.name = NULL},
Jan Engelhardta8ad34c2008-01-29 13:37:21 +0000109};
110
Marc Boucher5054e852002-01-19 10:59:12 +0000111static int
Jan Engelhardtdbb77542008-02-11 00:33:30 +0100112parse_state(const char *state, size_t len, struct xt_conntrack_info *sinfo)
Marc Boucher5054e852002-01-19 10:59:12 +0000113{
Jan Engelhardtdbb77542008-02-11 00:33:30 +0100114 if (strncasecmp(state, "INVALID", len) == 0)
Jan Engelhardta80b6042008-01-20 13:34:07 +0000115 sinfo->statemask |= XT_CONNTRACK_STATE_INVALID;
Jan Engelhardtdbb77542008-02-11 00:33:30 +0100116 else if (strncasecmp(state, "NEW", len) == 0)
Jan Engelhardta80b6042008-01-20 13:34:07 +0000117 sinfo->statemask |= XT_CONNTRACK_STATE_BIT(IP_CT_NEW);
Jan Engelhardtdbb77542008-02-11 00:33:30 +0100118 else if (strncasecmp(state, "ESTABLISHED", len) == 0)
Jan Engelhardta80b6042008-01-20 13:34:07 +0000119 sinfo->statemask |= XT_CONNTRACK_STATE_BIT(IP_CT_ESTABLISHED);
Jan Engelhardtdbb77542008-02-11 00:33:30 +0100120 else if (strncasecmp(state, "RELATED", len) == 0)
Jan Engelhardta80b6042008-01-20 13:34:07 +0000121 sinfo->statemask |= XT_CONNTRACK_STATE_BIT(IP_CT_RELATED);
Jan Engelhardtdbb77542008-02-11 00:33:30 +0100122 else if (strncasecmp(state, "UNTRACKED", len) == 0)
Jan Engelhardta80b6042008-01-20 13:34:07 +0000123 sinfo->statemask |= XT_CONNTRACK_STATE_UNTRACKED;
Jan Engelhardtdbb77542008-02-11 00:33:30 +0100124 else if (strncasecmp(state, "SNAT", len) == 0)
Jan Engelhardta80b6042008-01-20 13:34:07 +0000125 sinfo->statemask |= XT_CONNTRACK_STATE_SNAT;
Jan Engelhardtdbb77542008-02-11 00:33:30 +0100126 else if (strncasecmp(state, "DNAT", len) == 0)
Jan Engelhardta80b6042008-01-20 13:34:07 +0000127 sinfo->statemask |= XT_CONNTRACK_STATE_DNAT;
Marc Boucher5054e852002-01-19 10:59:12 +0000128 else
129 return 0;
130 return 1;
131}
132
133static void
Jan Engelhardta80b6042008-01-20 13:34:07 +0000134parse_states(const char *arg, struct xt_conntrack_info *sinfo)
Marc Boucher5054e852002-01-19 10:59:12 +0000135{
136 const char *comma;
137
138 while ((comma = strchr(arg, ',')) != NULL) {
139 if (comma == arg || !parse_state(arg, comma-arg, sinfo))
Jan Engelhardt1829ed42009-02-21 03:29:44 +0100140 xtables_error(PARAMETER_PROBLEM, "Bad ctstate \"%s\"", arg);
Marc Boucher5054e852002-01-19 10:59:12 +0000141 arg = comma+1;
142 }
Pablo Neira Ayuso0ec8c0f2008-11-19 19:01:26 +0100143 if (!*arg)
Jan Engelhardt1829ed42009-02-21 03:29:44 +0100144 xtables_error(PARAMETER_PROBLEM, "\"--ctstate\" requires a list of "
Pablo Neira Ayuso0ec8c0f2008-11-19 19:01:26 +0100145 "states with no spaces, e.g. "
146 "ESTABLISHED,RELATED");
Marc Boucher5054e852002-01-19 10:59:12 +0000147 if (strlen(arg) == 0 || !parse_state(arg, strlen(arg), sinfo))
Jan Engelhardt1829ed42009-02-21 03:29:44 +0100148 xtables_error(PARAMETER_PROBLEM, "Bad ctstate \"%s\"", arg);
Marc Boucher5054e852002-01-19 10:59:12 +0000149}
150
Jan Engelhardta8ad34c2008-01-29 13:37:21 +0000151static bool
Patrick McHardyc8f28cc2011-01-20 11:45:12 +0100152conntrack_ps_state(struct xt_conntrack_mtinfo3 *info, const char *state,
Jan Engelhardta8ad34c2008-01-29 13:37:21 +0000153 size_t z)
154{
155 if (strncasecmp(state, "INVALID", z) == 0)
156 info->state_mask |= XT_CONNTRACK_STATE_INVALID;
157 else if (strncasecmp(state, "NEW", z) == 0)
158 info->state_mask |= XT_CONNTRACK_STATE_BIT(IP_CT_NEW);
159 else if (strncasecmp(state, "ESTABLISHED", z) == 0)
160 info->state_mask |= XT_CONNTRACK_STATE_BIT(IP_CT_ESTABLISHED);
161 else if (strncasecmp(state, "RELATED", z) == 0)
162 info->state_mask |= XT_CONNTRACK_STATE_BIT(IP_CT_RELATED);
163 else if (strncasecmp(state, "UNTRACKED", z) == 0)
164 info->state_mask |= XT_CONNTRACK_STATE_UNTRACKED;
165 else if (strncasecmp(state, "SNAT", z) == 0)
166 info->state_mask |= XT_CONNTRACK_STATE_SNAT;
167 else if (strncasecmp(state, "DNAT", z) == 0)
168 info->state_mask |= XT_CONNTRACK_STATE_DNAT;
169 else
170 return false;
171 return true;
172}
173
174static void
Patrick McHardyc8f28cc2011-01-20 11:45:12 +0100175conntrack_ps_states(struct xt_conntrack_mtinfo3 *info, const char *arg)
Jan Engelhardta8ad34c2008-01-29 13:37:21 +0000176{
177 const char *comma;
178
179 while ((comma = strchr(arg, ',')) != NULL) {
180 if (comma == arg || !conntrack_ps_state(info, arg, comma - arg))
Jan Engelhardt1829ed42009-02-21 03:29:44 +0100181 xtables_error(PARAMETER_PROBLEM,
Jan Engelhardta8ad34c2008-01-29 13:37:21 +0000182 "Bad ctstate \"%s\"", arg);
183 arg = comma + 1;
184 }
185
186 if (strlen(arg) == 0 || !conntrack_ps_state(info, arg, strlen(arg)))
Jan Engelhardt1829ed42009-02-21 03:29:44 +0100187 xtables_error(PARAMETER_PROBLEM, "Bad ctstate \"%s\"", arg);
Jan Engelhardta8ad34c2008-01-29 13:37:21 +0000188}
189
Marc Boucher5054e852002-01-19 10:59:12 +0000190static int
Jan Engelhardtdbb77542008-02-11 00:33:30 +0100191parse_status(const char *status, size_t len, struct xt_conntrack_info *sinfo)
Marc Boucher5054e852002-01-19 10:59:12 +0000192{
Jan Engelhardtdbb77542008-02-11 00:33:30 +0100193 if (strncasecmp(status, "NONE", len) == 0)
Marc Boucher5054e852002-01-19 10:59:12 +0000194 sinfo->statusmask |= 0;
Jan Engelhardtdbb77542008-02-11 00:33:30 +0100195 else if (strncasecmp(status, "EXPECTED", len) == 0)
Marc Boucher5054e852002-01-19 10:59:12 +0000196 sinfo->statusmask |= IPS_EXPECTED;
Jan Engelhardtdbb77542008-02-11 00:33:30 +0100197 else if (strncasecmp(status, "SEEN_REPLY", len) == 0)
Marc Boucher5054e852002-01-19 10:59:12 +0000198 sinfo->statusmask |= IPS_SEEN_REPLY;
Jan Engelhardtdbb77542008-02-11 00:33:30 +0100199 else if (strncasecmp(status, "ASSURED", len) == 0)
Marc Boucher5054e852002-01-19 10:59:12 +0000200 sinfo->statusmask |= IPS_ASSURED;
Harald Weltea643c3e2003-08-25 11:08:52 +0000201#ifdef IPS_CONFIRMED
Jan Engelhardtdbb77542008-02-11 00:33:30 +0100202 else if (strncasecmp(status, "CONFIRMED", len) == 0)
Jan Engelhardta8ad34c2008-01-29 13:37:21 +0000203 sinfo->statusmask |= IPS_CONFIRMED;
Harald Weltea643c3e2003-08-25 11:08:52 +0000204#endif
Marc Boucher5054e852002-01-19 10:59:12 +0000205 else
206 return 0;
207 return 1;
208}
209
210static void
Jan Engelhardta80b6042008-01-20 13:34:07 +0000211parse_statuses(const char *arg, struct xt_conntrack_info *sinfo)
Marc Boucher5054e852002-01-19 10:59:12 +0000212{
213 const char *comma;
214
215 while ((comma = strchr(arg, ',')) != NULL) {
216 if (comma == arg || !parse_status(arg, comma-arg, sinfo))
Jan Engelhardt1829ed42009-02-21 03:29:44 +0100217 xtables_error(PARAMETER_PROBLEM, "Bad ctstatus \"%s\"", arg);
Marc Boucher5054e852002-01-19 10:59:12 +0000218 arg = comma+1;
219 }
220
221 if (strlen(arg) == 0 || !parse_status(arg, strlen(arg), sinfo))
Jan Engelhardt1829ed42009-02-21 03:29:44 +0100222 xtables_error(PARAMETER_PROBLEM, "Bad ctstatus \"%s\"", arg);
Marc Boucher5054e852002-01-19 10:59:12 +0000223}
224
Jan Engelhardta8ad34c2008-01-29 13:37:21 +0000225static bool
Patrick McHardyc8f28cc2011-01-20 11:45:12 +0100226conntrack_ps_status(struct xt_conntrack_mtinfo3 *info, const char *status,
Jan Engelhardta8ad34c2008-01-29 13:37:21 +0000227 size_t z)
228{
229 if (strncasecmp(status, "NONE", z) == 0)
230 info->status_mask |= 0;
231 else if (strncasecmp(status, "EXPECTED", z) == 0)
232 info->status_mask |= IPS_EXPECTED;
233 else if (strncasecmp(status, "SEEN_REPLY", z) == 0)
234 info->status_mask |= IPS_SEEN_REPLY;
235 else if (strncasecmp(status, "ASSURED", z) == 0)
236 info->status_mask |= IPS_ASSURED;
237 else if (strncasecmp(status, "CONFIRMED", z) == 0)
238 info->status_mask |= IPS_CONFIRMED;
239 else
240 return false;
241 return true;
242}
243
244static void
Patrick McHardyc8f28cc2011-01-20 11:45:12 +0100245conntrack_ps_statuses(struct xt_conntrack_mtinfo3 *info, const char *arg)
Jan Engelhardta8ad34c2008-01-29 13:37:21 +0000246{
247 const char *comma;
248
249 while ((comma = strchr(arg, ',')) != NULL) {
250 if (comma == arg || !conntrack_ps_status(info, arg, comma - arg))
Jan Engelhardt1829ed42009-02-21 03:29:44 +0100251 xtables_error(PARAMETER_PROBLEM,
Jan Engelhardta8ad34c2008-01-29 13:37:21 +0000252 "Bad ctstatus \"%s\"", arg);
253 arg = comma + 1;
254 }
255
256 if (strlen(arg) == 0 || !conntrack_ps_status(info, arg, strlen(arg)))
Jan Engelhardt1829ed42009-02-21 03:29:44 +0100257 xtables_error(PARAMETER_PROBLEM, "Bad ctstatus \"%s\"", arg);
Jan Engelhardta8ad34c2008-01-29 13:37:21 +0000258}
259
Marc Boucher5054e852002-01-19 10:59:12 +0000260static unsigned long
261parse_expire(const char *s)
262{
263 unsigned int len;
Jan Engelhardta80b6042008-01-20 13:34:07 +0000264
Jan Engelhardt5f2922c2009-01-27 18:43:01 +0100265 if (!xtables_strtoui(s, NULL, &len, 0, UINT32_MAX))
Jan Engelhardt1829ed42009-02-21 03:29:44 +0100266 xtables_error(PARAMETER_PROBLEM, "expire value invalid: \"%s\"\n", s);
Marc Boucher5054e852002-01-19 10:59:12 +0000267 else
268 return len;
269}
270
271/* If a single value is provided, min and max are both set to the value */
272static void
Jan Engelhardta80b6042008-01-20 13:34:07 +0000273parse_expires(const char *s, struct xt_conntrack_info *sinfo)
Marc Boucher5054e852002-01-19 10:59:12 +0000274{
275 char *buffer;
276 char *cp;
277
278 buffer = strdup(s);
279 if ((cp = strchr(buffer, ':')) == NULL)
Jan Engelhardta8ad34c2008-01-29 13:37:21 +0000280 sinfo->expires_min = sinfo->expires_max =
281 parse_expire(buffer);
Marc Boucher5054e852002-01-19 10:59:12 +0000282 else {
283 *cp = '\0';
284 cp++;
285
286 sinfo->expires_min = buffer[0] ? parse_expire(buffer) : 0;
Max Kellermann9ee386a2008-01-29 13:48:05 +0000287 sinfo->expires_max = cp[0]
288 ? parse_expire(cp)
289 : (unsigned long)-1;
Marc Boucher5054e852002-01-19 10:59:12 +0000290 }
291 free(buffer);
Jan Engelhardta80b6042008-01-20 13:34:07 +0000292
Marc Boucher5054e852002-01-19 10:59:12 +0000293 if (sinfo->expires_min > sinfo->expires_max)
Jan Engelhardt1829ed42009-02-21 03:29:44 +0100294 xtables_error(PARAMETER_PROBLEM,
Marc Boucher5054e852002-01-19 10:59:12 +0000295 "expire min. range value `%lu' greater than max. "
296 "range value `%lu'", sinfo->expires_min, sinfo->expires_max);
Marc Boucher5054e852002-01-19 10:59:12 +0000297}
298
Jan Engelhardta8ad34c2008-01-29 13:37:21 +0000299static void
Patrick McHardyc8f28cc2011-01-20 11:45:12 +0100300conntrack_ps_expires(struct xt_conntrack_mtinfo3 *info, const char *s)
Jan Engelhardta8ad34c2008-01-29 13:37:21 +0000301{
302 unsigned int min, max;
303 char *end;
304
Jan Engelhardt5f2922c2009-01-27 18:43:01 +0100305 if (!xtables_strtoui(s, &end, &min, 0, UINT32_MAX))
Jan Engelhardta41545c2009-01-27 21:27:19 +0100306 xtables_param_act(XTF_BAD_VALUE, "conntrack", "--expires", s);
Jan Engelhardta8ad34c2008-01-29 13:37:21 +0000307 max = min;
308 if (*end == ':')
Patrick McHardyf294f842009-11-20 14:58:11 +0100309 if (!xtables_strtoui(end + 1, &end, &max, 0, UINT32_MAX))
Jan Engelhardta41545c2009-01-27 21:27:19 +0100310 xtables_param_act(XTF_BAD_VALUE, "conntrack", "--expires", s);
Jan Engelhardta8ad34c2008-01-29 13:37:21 +0000311 if (*end != '\0')
Jan Engelhardta41545c2009-01-27 21:27:19 +0100312 xtables_param_act(XTF_BAD_VALUE, "conntrack", "--expires", s);
Jan Engelhardta8ad34c2008-01-29 13:37:21 +0000313
314 if (min > max)
Jan Engelhardt1829ed42009-02-21 03:29:44 +0100315 xtables_error(PARAMETER_PROBLEM,
Jan Engelhardta8ad34c2008-01-29 13:37:21 +0000316 "expire min. range value \"%u\" greater than max. "
317 "range value \"%u\"", min, max);
318
319 info->expires_min = min;
320 info->expires_max = max;
321}
322
Jan Engelhardt59d16402007-10-04 16:28:39 +0000323static int conntrack_parse(int c, char **argv, int invert, unsigned int *flags,
324 const void *entry, struct xt_entry_match **match)
Marc Boucher5054e852002-01-19 10:59:12 +0000325{
Jan Engelhardta80b6042008-01-20 13:34:07 +0000326 struct xt_conntrack_info *sinfo = (void *)(*match)->data;
Marc Boucher5054e852002-01-19 10:59:12 +0000327 char *protocol = NULL;
328 unsigned int naddrs = 0;
329 struct in_addr *addrs = NULL;
330
331
332 switch (c) {
333 case '1':
Jan Engelhardtbf971282009-11-03 19:55:11 +0100334 xtables_check_inverse(optarg, &invert, &optind, 0, argv);
Marc Boucher5054e852002-01-19 10:59:12 +0000335
Jan Engelhardtbbe83862009-10-24 00:45:33 +0200336 parse_states(optarg, sinfo);
Marc Boucher5054e852002-01-19 10:59:12 +0000337 if (invert) {
Jan Engelhardta80b6042008-01-20 13:34:07 +0000338 sinfo->invflags |= XT_CONNTRACK_STATE;
Marc Boucher5054e852002-01-19 10:59:12 +0000339 }
Jan Engelhardta80b6042008-01-20 13:34:07 +0000340 sinfo->flags |= XT_CONNTRACK_STATE;
Marc Boucher5054e852002-01-19 10:59:12 +0000341 break;
342
343 case '2':
Jan Engelhardtbf971282009-11-03 19:55:11 +0100344 xtables_check_inverse(optarg, &invert, &optind, 0, argv);
Marc Boucher5054e852002-01-19 10:59:12 +0000345
346 if(invert)
Jan Engelhardta80b6042008-01-20 13:34:07 +0000347 sinfo->invflags |= XT_CONNTRACK_PROTO;
Marc Boucher5054e852002-01-19 10:59:12 +0000348
349 /* Canonicalize into lower case */
Jan Engelhardtbbe83862009-10-24 00:45:33 +0200350 for (protocol = optarg; *protocol; protocol++)
Marc Boucher5054e852002-01-19 10:59:12 +0000351 *protocol = tolower(*protocol);
352
Jan Engelhardtbbe83862009-10-24 00:45:33 +0200353 protocol = optarg;
Jan Engelhardt1de7edf2009-01-30 05:38:11 +0100354 sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum =
355 xtables_parse_protocol(protocol);
Marc Boucher5054e852002-01-19 10:59:12 +0000356
357 if (sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum == 0
Jan Engelhardta80b6042008-01-20 13:34:07 +0000358 && (sinfo->invflags & XT_INV_PROTO))
Jan Engelhardt1829ed42009-02-21 03:29:44 +0100359 xtables_error(PARAMETER_PROBLEM,
Marc Boucher5054e852002-01-19 10:59:12 +0000360 "rule would never match protocol");
361
Jan Engelhardta80b6042008-01-20 13:34:07 +0000362 sinfo->flags |= XT_CONNTRACK_PROTO;
Marc Boucher5054e852002-01-19 10:59:12 +0000363 break;
364
365 case '3':
Jan Engelhardtbf971282009-11-03 19:55:11 +0100366 xtables_check_inverse(optarg, &invert, &optind, 0, argv);
Marc Boucher5054e852002-01-19 10:59:12 +0000367
368 if (invert)
Jan Engelhardta80b6042008-01-20 13:34:07 +0000369 sinfo->invflags |= XT_CONNTRACK_ORIGSRC;
Marc Boucher5054e852002-01-19 10:59:12 +0000370
Jan Engelhardtbbe83862009-10-24 00:45:33 +0200371 xtables_ipparse_any(optarg, &addrs,
Marc Boucher5054e852002-01-19 10:59:12 +0000372 &sinfo->sipmsk[IP_CT_DIR_ORIGINAL],
373 &naddrs);
374 if(naddrs > 1)
Jan Engelhardt1829ed42009-02-21 03:29:44 +0100375 xtables_error(PARAMETER_PROBLEM,
Marc Boucher5054e852002-01-19 10:59:12 +0000376 "multiple IP addresses not allowed");
377
378 if(naddrs == 1) {
379 sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip = addrs[0].s_addr;
380 }
381
Jan Engelhardta80b6042008-01-20 13:34:07 +0000382 sinfo->flags |= XT_CONNTRACK_ORIGSRC;
Marc Boucher5054e852002-01-19 10:59:12 +0000383 break;
384
385 case '4':
Jan Engelhardtbf971282009-11-03 19:55:11 +0100386 xtables_check_inverse(optarg, &invert, &optind, 0, argv);
Marc Boucher5054e852002-01-19 10:59:12 +0000387
388 if (invert)
Jan Engelhardta80b6042008-01-20 13:34:07 +0000389 sinfo->invflags |= XT_CONNTRACK_ORIGDST;
Marc Boucher5054e852002-01-19 10:59:12 +0000390
Jan Engelhardtbbe83862009-10-24 00:45:33 +0200391 xtables_ipparse_any(optarg, &addrs,
Marc Boucher5054e852002-01-19 10:59:12 +0000392 &sinfo->dipmsk[IP_CT_DIR_ORIGINAL],
393 &naddrs);
394 if(naddrs > 1)
Jan Engelhardt1829ed42009-02-21 03:29:44 +0100395 xtables_error(PARAMETER_PROBLEM,
Marc Boucher5054e852002-01-19 10:59:12 +0000396 "multiple IP addresses not allowed");
397
398 if(naddrs == 1) {
399 sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip = addrs[0].s_addr;
400 }
401
Jan Engelhardta80b6042008-01-20 13:34:07 +0000402 sinfo->flags |= XT_CONNTRACK_ORIGDST;
Marc Boucher5054e852002-01-19 10:59:12 +0000403 break;
404
405 case '5':
Jan Engelhardtbf971282009-11-03 19:55:11 +0100406 xtables_check_inverse(optarg, &invert, &optind, 0, argv);
Marc Boucher5054e852002-01-19 10:59:12 +0000407
408 if (invert)
Jan Engelhardta80b6042008-01-20 13:34:07 +0000409 sinfo->invflags |= XT_CONNTRACK_REPLSRC;
Marc Boucher5054e852002-01-19 10:59:12 +0000410
Jan Engelhardtbbe83862009-10-24 00:45:33 +0200411 xtables_ipparse_any(optarg, &addrs,
Marc Boucher5054e852002-01-19 10:59:12 +0000412 &sinfo->sipmsk[IP_CT_DIR_REPLY],
413 &naddrs);
414 if(naddrs > 1)
Jan Engelhardt1829ed42009-02-21 03:29:44 +0100415 xtables_error(PARAMETER_PROBLEM,
Marc Boucher5054e852002-01-19 10:59:12 +0000416 "multiple IP addresses not allowed");
417
418 if(naddrs == 1) {
419 sinfo->tuple[IP_CT_DIR_REPLY].src.ip = addrs[0].s_addr;
420 }
421
Jan Engelhardta80b6042008-01-20 13:34:07 +0000422 sinfo->flags |= XT_CONNTRACK_REPLSRC;
Marc Boucher5054e852002-01-19 10:59:12 +0000423 break;
424
425 case '6':
Jan Engelhardtbf971282009-11-03 19:55:11 +0100426 xtables_check_inverse(optarg, &invert, &optind, 0, argv);
Marc Boucher5054e852002-01-19 10:59:12 +0000427
428 if (invert)
Jan Engelhardta80b6042008-01-20 13:34:07 +0000429 sinfo->invflags |= XT_CONNTRACK_REPLDST;
Marc Boucher5054e852002-01-19 10:59:12 +0000430
Jan Engelhardtbbe83862009-10-24 00:45:33 +0200431 xtables_ipparse_any(optarg, &addrs,
Marc Boucher5054e852002-01-19 10:59:12 +0000432 &sinfo->dipmsk[IP_CT_DIR_REPLY],
433 &naddrs);
434 if(naddrs > 1)
Jan Engelhardt1829ed42009-02-21 03:29:44 +0100435 xtables_error(PARAMETER_PROBLEM,
Marc Boucher5054e852002-01-19 10:59:12 +0000436 "multiple IP addresses not allowed");
437
438 if(naddrs == 1) {
439 sinfo->tuple[IP_CT_DIR_REPLY].dst.ip = addrs[0].s_addr;
440 }
441
Jan Engelhardta80b6042008-01-20 13:34:07 +0000442 sinfo->flags |= XT_CONNTRACK_REPLDST;
Marc Boucher5054e852002-01-19 10:59:12 +0000443 break;
444
445 case '7':
Jan Engelhardtbf971282009-11-03 19:55:11 +0100446 xtables_check_inverse(optarg, &invert, &optind, 0, argv);
Marc Boucher5054e852002-01-19 10:59:12 +0000447
Jan Engelhardtbbe83862009-10-24 00:45:33 +0200448 parse_statuses(optarg, sinfo);
Marc Boucher5054e852002-01-19 10:59:12 +0000449 if (invert) {
Jan Engelhardta80b6042008-01-20 13:34:07 +0000450 sinfo->invflags |= XT_CONNTRACK_STATUS;
Marc Boucher5054e852002-01-19 10:59:12 +0000451 }
Jan Engelhardta80b6042008-01-20 13:34:07 +0000452 sinfo->flags |= XT_CONNTRACK_STATUS;
Marc Boucher5054e852002-01-19 10:59:12 +0000453 break;
454
455 case '8':
Jan Engelhardtbf971282009-11-03 19:55:11 +0100456 xtables_check_inverse(optarg, &invert, &optind, 0, argv);
Marc Boucher5054e852002-01-19 10:59:12 +0000457
Jan Engelhardtbbe83862009-10-24 00:45:33 +0200458 parse_expires(optarg, sinfo);
Marc Boucher5054e852002-01-19 10:59:12 +0000459 if (invert) {
Jan Engelhardta80b6042008-01-20 13:34:07 +0000460 sinfo->invflags |= XT_CONNTRACK_EXPIRES;
Marc Boucher5054e852002-01-19 10:59:12 +0000461 }
Jan Engelhardta80b6042008-01-20 13:34:07 +0000462 sinfo->flags |= XT_CONNTRACK_EXPIRES;
Marc Boucher5054e852002-01-19 10:59:12 +0000463 break;
Marc Boucher5054e852002-01-19 10:59:12 +0000464 }
465
466 *flags = sinfo->flags;
467 return 1;
468}
469
Patrick McHardyc8f28cc2011-01-20 11:45:12 +0100470static void
471ct_parse_ports(const char *param, const char *str,
472 u_int16_t *port_low, u_int16_t *port_high)
Jan Engelhardta8ad34c2008-01-29 13:37:21 +0000473{
Jan Engelhardta8ad34c2008-01-29 13:37:21 +0000474 unsigned int port;
Patrick McHardyc8f28cc2011-01-20 11:45:12 +0100475 char *buf, *cp;
476
477 buf = strdup(str);
478 cp = strchr(buf, ':');
479 if (cp != NULL)
480 *cp = '\0';
481
482 if (!xtables_strtoui(buf, NULL, &port, 0, UINT16_MAX))
483 xtables_param_act(XTF_BAD_VALUE, "conntrack", param, buf);
484
485 if (port_high == NULL) {
486 /* revision 0-2 do not support ranges */
487 if (cp != NULL)
488 xtables_error(PARAMETER_PROBLEM, "conntrack: "
489 "port ranges not supported");
490
491 *port_low = htons(port);
492 } else {
493 *port_low = port;
494
495 if (cp != NULL) {
496 if (!xtables_strtoui(cp + 1, NULL, &port, 0, UINT16_MAX))
497 xtables_param_act(XTF_BAD_VALUE, "conntrack", param, buf);
498
499 *port_high = port;
500 if (*port_low > *port_high)
501 xtables_error(PARAMETER_PROBLEM,
502 "invalid portrange (min > max)");
503 } else
504 *port_high = port;
505 }
506
507 free(buf);
508}
509
510
511static int
512conntrack_mt_parse(int c, bool invert, unsigned int *flags,
513 struct xt_conntrack_mtinfo3 *info, bool v3)
514{
Jan Engelhardta8ad34c2008-01-29 13:37:21 +0000515 char *p;
516
517 switch (c) {
518 case '1': /* --ctstate */
519 conntrack_ps_states(info, optarg);
520 info->match_flags |= XT_CONNTRACK_STATE;
521 if (invert)
522 info->invert_flags |= XT_CONNTRACK_STATE;
523 break;
524
525 case '2': /* --ctproto */
526 /* Canonicalize into lower case */
527 for (p = optarg; *p != '\0'; ++p)
528 *p = tolower(*p);
Jan Engelhardt1de7edf2009-01-30 05:38:11 +0100529 info->l4proto = xtables_parse_protocol(optarg);
Jan Engelhardta8ad34c2008-01-29 13:37:21 +0000530
531 if (info->l4proto == 0 && (info->invert_flags & XT_INV_PROTO))
Jan Engelhardt1829ed42009-02-21 03:29:44 +0100532 xtables_error(PARAMETER_PROBLEM, "conntrack: rule would "
Jan Engelhardta8ad34c2008-01-29 13:37:21 +0000533 "never match protocol");
534
535 info->match_flags |= XT_CONNTRACK_PROTO;
536 if (invert)
537 info->invert_flags |= XT_CONNTRACK_PROTO;
538 break;
539
540 case '7': /* --ctstatus */
541 conntrack_ps_statuses(info, optarg);
542 info->match_flags |= XT_CONNTRACK_STATUS;
543 if (invert)
544 info->invert_flags |= XT_CONNTRACK_STATUS;
545 break;
546
547 case '8': /* --ctexpire */
548 conntrack_ps_expires(info, optarg);
549 info->match_flags |= XT_CONNTRACK_EXPIRES;
550 if (invert)
551 info->invert_flags |= XT_CONNTRACK_EXPIRES;
552 break;
553
554 case 'a': /* --ctorigsrcport */
Patrick McHardyc8f28cc2011-01-20 11:45:12 +0100555 ct_parse_ports("--ctorigsrcport", optarg,
556 &info->origsrc_port,
557 v3 ? &info->origsrc_port_high : NULL);
558
Jan Engelhardta8ad34c2008-01-29 13:37:21 +0000559 info->match_flags |= XT_CONNTRACK_ORIGSRC_PORT;
Jan Engelhardta8ad34c2008-01-29 13:37:21 +0000560 if (invert)
561 info->invert_flags |= XT_CONNTRACK_ORIGSRC_PORT;
562 break;
563
564 case 'b': /* --ctorigdstport */
Patrick McHardyc8f28cc2011-01-20 11:45:12 +0100565 ct_parse_ports("--ctorigdstport", optarg,
566 &info->origdst_port,
567 v3 ? &info->origdst_port_high : NULL);
568
Jan Engelhardta8ad34c2008-01-29 13:37:21 +0000569 info->match_flags |= XT_CONNTRACK_ORIGDST_PORT;
Jan Engelhardta8ad34c2008-01-29 13:37:21 +0000570 if (invert)
571 info->invert_flags |= XT_CONNTRACK_ORIGDST_PORT;
572 break;
573
574 case 'c': /* --ctreplsrcport */
Patrick McHardyc8f28cc2011-01-20 11:45:12 +0100575 ct_parse_ports("--ctreplsrcport", optarg,
576 &info->replsrc_port,
577 v3 ? &info->replsrc_port_high : NULL);
578
Jan Engelhardta8ad34c2008-01-29 13:37:21 +0000579 info->match_flags |= XT_CONNTRACK_REPLSRC_PORT;
Jan Engelhardta8ad34c2008-01-29 13:37:21 +0000580 if (invert)
581 info->invert_flags |= XT_CONNTRACK_REPLSRC_PORT;
582 break;
583
584 case 'd': /* --ctrepldstport */
Patrick McHardyc8f28cc2011-01-20 11:45:12 +0100585 ct_parse_ports("--ctrepldstport", optarg,
586 &info->repldst_port,
587 v3 ? &info->repldst_port_high : NULL);
588
Jan Engelhardta8ad34c2008-01-29 13:37:21 +0000589 info->match_flags |= XT_CONNTRACK_REPLDST_PORT;
Jan Engelhardta8ad34c2008-01-29 13:37:21 +0000590 if (invert)
591 info->invert_flags |= XT_CONNTRACK_REPLDST_PORT;
592 break;
593
594 case 'e': /* --ctdir */
Jan Engelhardta41545c2009-01-27 21:27:19 +0100595 xtables_param_act(XTF_NO_INVERT, "conntrack", "--ctdir", invert);
Jan Engelhardta8ad34c2008-01-29 13:37:21 +0000596 if (strcasecmp(optarg, "ORIGINAL") == 0) {
597 info->match_flags |= XT_CONNTRACK_DIRECTION;
598 info->invert_flags &= ~XT_CONNTRACK_DIRECTION;
599 } else if (strcasecmp(optarg, "REPLY") == 0) {
600 info->match_flags |= XT_CONNTRACK_DIRECTION;
601 info->invert_flags |= XT_CONNTRACK_DIRECTION;
602 } else {
Jan Engelhardta41545c2009-01-27 21:27:19 +0100603 xtables_param_act(XTF_BAD_VALUE, "conntrack", "--ctdir", optarg);
Jan Engelhardta8ad34c2008-01-29 13:37:21 +0000604 }
605 break;
Jan Engelhardta8ad34c2008-01-29 13:37:21 +0000606 }
607
608 *flags = info->match_flags;
609 return true;
610}
611
612static int
Jan Engelhardtb97b4212009-06-25 18:46:37 +0200613conntrack_mt4_parse(int c, bool invert, unsigned int *flags,
Patrick McHardyc8f28cc2011-01-20 11:45:12 +0100614 struct xt_conntrack_mtinfo3 *info, bool v3)
Jan Engelhardta8ad34c2008-01-29 13:37:21 +0000615{
Jan Engelhardta8ad34c2008-01-29 13:37:21 +0000616 struct in_addr *addr = NULL;
617 unsigned int naddrs = 0;
618
619 switch (c) {
620 case '3': /* --ctorigsrc */
Jan Engelhardta0baae82009-01-30 04:32:50 +0100621 xtables_ipparse_any(optarg, &addr, &info->origsrc_mask.in,
Jan Engelhardta8ad34c2008-01-29 13:37:21 +0000622 &naddrs);
623 if (naddrs > 1)
Jan Engelhardt1829ed42009-02-21 03:29:44 +0100624 xtables_error(PARAMETER_PROBLEM,
Jan Engelhardta8ad34c2008-01-29 13:37:21 +0000625 "multiple IP addresses not allowed");
626 if (naddrs == 1)
627 memcpy(&info->origsrc_addr.in, addr, sizeof(*addr));
628 info->match_flags |= XT_CONNTRACK_ORIGSRC;
629 if (invert)
630 info->invert_flags |= XT_CONNTRACK_ORIGSRC;
631 break;
632
633 case '4': /* --ctorigdst */
Jan Engelhardta0baae82009-01-30 04:32:50 +0100634 xtables_ipparse_any(optarg, &addr, &info->origdst_mask.in,
Jan Engelhardta8ad34c2008-01-29 13:37:21 +0000635 &naddrs);
636 if (naddrs > 1)
Jan Engelhardt1829ed42009-02-21 03:29:44 +0100637 xtables_error(PARAMETER_PROBLEM,
Jan Engelhardta8ad34c2008-01-29 13:37:21 +0000638 "multiple IP addresses not allowed");
639 if (naddrs == 1)
640 memcpy(&info->origdst_addr.in, addr, sizeof(*addr));
641 info->match_flags |= XT_CONNTRACK_ORIGDST;
642 if (invert)
643 info->invert_flags |= XT_CONNTRACK_ORIGDST;
644 break;
645
646 case '5': /* --ctreplsrc */
Jan Engelhardta0baae82009-01-30 04:32:50 +0100647 xtables_ipparse_any(optarg, &addr, &info->replsrc_mask.in,
Jan Engelhardta8ad34c2008-01-29 13:37:21 +0000648 &naddrs);
649 if (naddrs > 1)
Jan Engelhardt1829ed42009-02-21 03:29:44 +0100650 xtables_error(PARAMETER_PROBLEM,
Jan Engelhardta8ad34c2008-01-29 13:37:21 +0000651 "multiple IP addresses not allowed");
652 if (naddrs == 1)
653 memcpy(&info->replsrc_addr.in, addr, sizeof(*addr));
654 info->match_flags |= XT_CONNTRACK_REPLSRC;
655 if (invert)
656 info->invert_flags |= XT_CONNTRACK_REPLSRC;
657 break;
658
659 case '6': /* --ctrepldst */
Jan Engelhardta0baae82009-01-30 04:32:50 +0100660 xtables_ipparse_any(optarg, &addr, &info->repldst_mask.in,
Jan Engelhardta8ad34c2008-01-29 13:37:21 +0000661 &naddrs);
662 if (naddrs > 1)
Jan Engelhardt1829ed42009-02-21 03:29:44 +0100663 xtables_error(PARAMETER_PROBLEM,
Jan Engelhardta8ad34c2008-01-29 13:37:21 +0000664 "multiple IP addresses not allowed");
665 if (naddrs == 1)
666 memcpy(&info->repldst_addr.in, addr, sizeof(*addr));
667 info->match_flags |= XT_CONNTRACK_REPLDST;
668 if (invert)
669 info->invert_flags |= XT_CONNTRACK_REPLDST;
670 break;
671
672
673 default:
Patrick McHardyc8f28cc2011-01-20 11:45:12 +0100674 return conntrack_mt_parse(c, invert, flags, info, v3);
Jan Engelhardta8ad34c2008-01-29 13:37:21 +0000675 }
676
677 *flags = info->match_flags;
678 return true;
679}
680
681static int
Jan Engelhardtb97b4212009-06-25 18:46:37 +0200682conntrack_mt6_parse(int c, bool invert, unsigned int *flags,
Patrick McHardyc8f28cc2011-01-20 11:45:12 +0100683 struct xt_conntrack_mtinfo3 *info, bool v3)
Jan Engelhardta8ad34c2008-01-29 13:37:21 +0000684{
Jan Engelhardta8ad34c2008-01-29 13:37:21 +0000685 struct in6_addr *addr = NULL;
686 unsigned int naddrs = 0;
687
688 switch (c) {
689 case '3': /* --ctorigsrc */
Jan Engelhardta0baae82009-01-30 04:32:50 +0100690 xtables_ip6parse_any(optarg, &addr,
Jan Engelhardta8ad34c2008-01-29 13:37:21 +0000691 &info->origsrc_mask.in6, &naddrs);
692 if (naddrs > 1)
Jan Engelhardt1829ed42009-02-21 03:29:44 +0100693 xtables_error(PARAMETER_PROBLEM,
Jan Engelhardta8ad34c2008-01-29 13:37:21 +0000694 "multiple IP addresses not allowed");
695 if (naddrs == 1)
696 memcpy(&info->origsrc_addr.in6, addr, sizeof(*addr));
697 info->match_flags |= XT_CONNTRACK_ORIGSRC;
698 if (invert)
699 info->invert_flags |= XT_CONNTRACK_ORIGSRC;
700 break;
701
702 case '4': /* --ctorigdst */
Jan Engelhardta0baae82009-01-30 04:32:50 +0100703 xtables_ip6parse_any(optarg, &addr,
Jan Engelhardta8ad34c2008-01-29 13:37:21 +0000704 &info->origdst_mask.in6, &naddrs);
705 if (naddrs > 1)
Jan Engelhardt1829ed42009-02-21 03:29:44 +0100706 xtables_error(PARAMETER_PROBLEM,
Jan Engelhardta8ad34c2008-01-29 13:37:21 +0000707 "multiple IP addresses not allowed");
708 if (naddrs == 1)
709 memcpy(&info->origdst_addr.in, addr, sizeof(*addr));
710 info->match_flags |= XT_CONNTRACK_ORIGDST;
711 if (invert)
712 info->invert_flags |= XT_CONNTRACK_ORIGDST;
713 break;
714
715 case '5': /* --ctreplsrc */
Jan Engelhardta0baae82009-01-30 04:32:50 +0100716 xtables_ip6parse_any(optarg, &addr,
Jan Engelhardta8ad34c2008-01-29 13:37:21 +0000717 &info->replsrc_mask.in6, &naddrs);
718 if (naddrs > 1)
Jan Engelhardt1829ed42009-02-21 03:29:44 +0100719 xtables_error(PARAMETER_PROBLEM,
Jan Engelhardta8ad34c2008-01-29 13:37:21 +0000720 "multiple IP addresses not allowed");
721 if (naddrs == 1)
722 memcpy(&info->replsrc_addr.in, addr, sizeof(*addr));
723 info->match_flags |= XT_CONNTRACK_REPLSRC;
724 if (invert)
725 info->invert_flags |= XT_CONNTRACK_REPLSRC;
726 break;
727
728 case '6': /* --ctrepldst */
Jan Engelhardta0baae82009-01-30 04:32:50 +0100729 xtables_ip6parse_any(optarg, &addr,
Jan Engelhardta8ad34c2008-01-29 13:37:21 +0000730 &info->repldst_mask.in6, &naddrs);
731 if (naddrs > 1)
Jan Engelhardt1829ed42009-02-21 03:29:44 +0100732 xtables_error(PARAMETER_PROBLEM,
Jan Engelhardta8ad34c2008-01-29 13:37:21 +0000733 "multiple IP addresses not allowed");
734 if (naddrs == 1)
735 memcpy(&info->repldst_addr.in, addr, sizeof(*addr));
736 info->match_flags |= XT_CONNTRACK_REPLDST;
737 if (invert)
738 info->invert_flags |= XT_CONNTRACK_REPLDST;
739 break;
740
741
742 default:
Patrick McHardyc8f28cc2011-01-20 11:45:12 +0100743 return conntrack_mt_parse(c, invert, flags, info, v3);
Jan Engelhardta8ad34c2008-01-29 13:37:21 +0000744 }
745
746 *flags = info->match_flags;
747 return true;
748}
749
Jan Engelhardtb97b4212009-06-25 18:46:37 +0200750#define cinfo_transform(r, l) \
751 do { \
752 memcpy((r), (l), offsetof(typeof(*(l)), state_mask)); \
753 (r)->state_mask = (l)->state_mask; \
754 (r)->status_mask = (l)->status_mask; \
755 } while (false);
756
757static int
758conntrack1_mt4_parse(int c, char **argv, int invert, unsigned int *flags,
759 const void *entry, struct xt_entry_match **match)
760{
761 struct xt_conntrack_mtinfo1 *info = (void *)(*match)->data;
Patrick McHardyc8f28cc2011-01-20 11:45:12 +0100762 struct xt_conntrack_mtinfo3 up;
Jan Engelhardtb97b4212009-06-25 18:46:37 +0200763
764 cinfo_transform(&up, info);
Patrick McHardyc8f28cc2011-01-20 11:45:12 +0100765 if (!conntrack_mt4_parse(c, invert, flags, &up, false))
Jan Engelhardtb97b4212009-06-25 18:46:37 +0200766 return false;
767 cinfo_transform(info, &up);
768 return true;
769}
770
771static int
772conntrack1_mt6_parse(int c, char **argv, int invert, unsigned int *flags,
773 const void *entry, struct xt_entry_match **match)
774{
775 struct xt_conntrack_mtinfo1 *info = (void *)(*match)->data;
Patrick McHardyc8f28cc2011-01-20 11:45:12 +0100776 struct xt_conntrack_mtinfo3 up;
Jan Engelhardtb97b4212009-06-25 18:46:37 +0200777
778 cinfo_transform(&up, info);
Patrick McHardyc8f28cc2011-01-20 11:45:12 +0100779 if (!conntrack_mt6_parse(c, invert, flags, &up, false))
Jan Engelhardtb97b4212009-06-25 18:46:37 +0200780 return false;
781 cinfo_transform(info, &up);
782 return true;
783}
784
785static int
786conntrack2_mt4_parse(int c, char **argv, int invert, unsigned int *flags,
787 const void *entry, struct xt_entry_match **match)
788{
Patrick McHardyc8f28cc2011-01-20 11:45:12 +0100789 return conntrack_mt4_parse(c, invert, flags, (void *)(*match)->data, false);
Jan Engelhardtb97b4212009-06-25 18:46:37 +0200790}
791
792static int
793conntrack2_mt6_parse(int c, char **argv, int invert, unsigned int *flags,
794 const void *entry, struct xt_entry_match **match)
795{
Patrick McHardyc8f28cc2011-01-20 11:45:12 +0100796 return conntrack_mt6_parse(c, invert, flags, (void *)(*match)->data, false);
797}
798
799static int
800conntrack3_mt4_parse(int c, char **argv, int invert, unsigned int *flags,
801 const void *entry, struct xt_entry_match **match)
802{
803 return conntrack_mt4_parse(c, invert, flags, (void *)(*match)->data, true);
804}
805
806static int
807conntrack3_mt6_parse(int c, char **argv, int invert, unsigned int *flags,
808 const void *entry, struct xt_entry_match **match)
809{
810 return conntrack_mt6_parse(c, invert, flags, (void *)(*match)->data, true);
Jan Engelhardtb97b4212009-06-25 18:46:37 +0200811}
812
Jan Engelhardta80b6042008-01-20 13:34:07 +0000813static void conntrack_mt_check(unsigned int flags)
Marc Boucher5054e852002-01-19 10:59:12 +0000814{
Jan Engelhardta80b6042008-01-20 13:34:07 +0000815 if (flags == 0)
Jan Engelhardt1829ed42009-02-21 03:29:44 +0100816 xtables_error(PARAMETER_PROBLEM, "conntrack: At least one option "
Jan Engelhardta8ad34c2008-01-29 13:37:21 +0000817 "is required");
Marc Boucher5054e852002-01-19 10:59:12 +0000818}
819
820static void
821print_state(unsigned int statemask)
822{
Jan Engelhardt73866352010-12-18 02:04:59 +0100823 const char *sep = " ";
Marc Boucher5054e852002-01-19 10:59:12 +0000824
Jan Engelhardta80b6042008-01-20 13:34:07 +0000825 if (statemask & XT_CONNTRACK_STATE_INVALID) {
Marc Boucher5054e852002-01-19 10:59:12 +0000826 printf("%sINVALID", sep);
827 sep = ",";
828 }
Jan Engelhardta80b6042008-01-20 13:34:07 +0000829 if (statemask & XT_CONNTRACK_STATE_BIT(IP_CT_NEW)) {
Marc Boucher5054e852002-01-19 10:59:12 +0000830 printf("%sNEW", sep);
831 sep = ",";
832 }
Jan Engelhardta80b6042008-01-20 13:34:07 +0000833 if (statemask & XT_CONNTRACK_STATE_BIT(IP_CT_RELATED)) {
Marc Boucher5054e852002-01-19 10:59:12 +0000834 printf("%sRELATED", sep);
835 sep = ",";
836 }
Jan Engelhardta80b6042008-01-20 13:34:07 +0000837 if (statemask & XT_CONNTRACK_STATE_BIT(IP_CT_ESTABLISHED)) {
Marc Boucher5054e852002-01-19 10:59:12 +0000838 printf("%sESTABLISHED", sep);
839 sep = ",";
840 }
Jan Engelhardta80b6042008-01-20 13:34:07 +0000841 if (statemask & XT_CONNTRACK_STATE_UNTRACKED) {
Harald Welte4dc734c2003-10-07 18:55:13 +0000842 printf("%sUNTRACKED", sep);
843 sep = ",";
844 }
Jan Engelhardta80b6042008-01-20 13:34:07 +0000845 if (statemask & XT_CONNTRACK_STATE_SNAT) {
Marc Boucher5054e852002-01-19 10:59:12 +0000846 printf("%sSNAT", sep);
847 sep = ",";
848 }
Jan Engelhardta80b6042008-01-20 13:34:07 +0000849 if (statemask & XT_CONNTRACK_STATE_DNAT) {
Marc Boucher5054e852002-01-19 10:59:12 +0000850 printf("%sDNAT", sep);
851 sep = ",";
852 }
Marc Boucher5054e852002-01-19 10:59:12 +0000853}
854
855static void
856print_status(unsigned int statusmask)
857{
Jan Engelhardt73866352010-12-18 02:04:59 +0100858 const char *sep = " ";
Marc Boucher5054e852002-01-19 10:59:12 +0000859
860 if (statusmask & IPS_EXPECTED) {
861 printf("%sEXPECTED", sep);
862 sep = ",";
863 }
864 if (statusmask & IPS_SEEN_REPLY) {
865 printf("%sSEEN_REPLY", sep);
866 sep = ",";
867 }
868 if (statusmask & IPS_ASSURED) {
869 printf("%sASSURED", sep);
870 sep = ",";
871 }
Harald Weltea643c3e2003-08-25 11:08:52 +0000872 if (statusmask & IPS_CONFIRMED) {
873 printf("%sCONFIRMED", sep);
Marc Boucher5054e852002-01-19 10:59:12 +0000874 sep = ",";
875 }
Jan Engelhardta8ad34c2008-01-29 13:37:21 +0000876 if (statusmask == 0)
877 printf("%sNONE", sep);
Marc Boucher5054e852002-01-19 10:59:12 +0000878}
879
880static void
Jan Engelhardta8ad34c2008-01-29 13:37:21 +0000881conntrack_dump_addr(const union nf_inet_addr *addr,
882 const union nf_inet_addr *mask,
883 unsigned int family, bool numeric)
884{
Jan Engelhardt03d99482008-11-18 12:27:54 +0100885 if (family == NFPROTO_IPV4) {
Jan Engelhardta8ad34c2008-01-29 13:37:21 +0000886 if (!numeric && addr->ip == 0) {
Jan Engelhardt73866352010-12-18 02:04:59 +0100887 printf(" anywhere");
Jan Engelhardta8ad34c2008-01-29 13:37:21 +0000888 return;
889 }
Jan Engelhardt6b6c0962008-11-10 17:08:07 +0100890 if (numeric)
Jan Engelhardt73866352010-12-18 02:04:59 +0100891 printf(" %s%s",
Jan Engelhardt76f7a232010-06-24 21:23:44 +0200892 xtables_ipaddr_to_numeric(&addr->in),
893 xtables_ipmask_to_numeric(&mask->in));
Jan Engelhardt6b6c0962008-11-10 17:08:07 +0100894 else
Jan Engelhardt73866352010-12-18 02:04:59 +0100895 printf(" %s%s",
Jan Engelhardt76f7a232010-06-24 21:23:44 +0200896 xtables_ipaddr_to_anyname(&addr->in),
897 xtables_ipmask_to_numeric(&mask->in));
Jan Engelhardt03d99482008-11-18 12:27:54 +0100898 } else if (family == NFPROTO_IPV6) {
Jan Engelhardta8ad34c2008-01-29 13:37:21 +0000899 if (!numeric && addr->ip6[0] == 0 && addr->ip6[1] == 0 &&
900 addr->ip6[2] == 0 && addr->ip6[3] == 0) {
Jan Engelhardt73866352010-12-18 02:04:59 +0100901 printf(" anywhere");
Jan Engelhardta8ad34c2008-01-29 13:37:21 +0000902 return;
903 }
Jan Engelhardt6b6c0962008-11-10 17:08:07 +0100904 if (numeric)
Jan Engelhardt73866352010-12-18 02:04:59 +0100905 printf(" %s%s",
Jan Engelhardt76f7a232010-06-24 21:23:44 +0200906 xtables_ip6addr_to_numeric(&addr->in6),
907 xtables_ip6mask_to_numeric(&mask->in6));
Jan Engelhardt6b6c0962008-11-10 17:08:07 +0100908 else
Jan Engelhardt73866352010-12-18 02:04:59 +0100909 printf(" %s%s",
Jan Engelhardt76f7a232010-06-24 21:23:44 +0200910 xtables_ip6addr_to_anyname(&addr->in6),
911 xtables_ip6mask_to_numeric(&mask->in6));
Jan Engelhardta8ad34c2008-01-29 13:37:21 +0000912 }
913}
914
915static void
Jan Engelhardt69f564e2009-05-26 13:14:06 +0200916print_addr(const struct in_addr *addr, const struct in_addr *mask,
917 int inv, int numeric)
Marc Boucher5054e852002-01-19 10:59:12 +0000918{
919 char buf[BUFSIZ];
920
Jan Engelhardta80b6042008-01-20 13:34:07 +0000921 if (inv)
Jan Engelhardt73866352010-12-18 02:04:59 +0100922 printf(" !");
Marc Boucher5054e852002-01-19 10:59:12 +0000923
924 if (mask->s_addr == 0L && !numeric)
Jan Engelhardt73866352010-12-18 02:04:59 +0100925 printf(" %s", "anywhere");
Marc Boucher5054e852002-01-19 10:59:12 +0000926 else {
927 if (numeric)
Jan Engelhardte44ea7f2009-01-30 03:55:09 +0100928 strcpy(buf, xtables_ipaddr_to_numeric(addr));
Marc Boucher5054e852002-01-19 10:59:12 +0000929 else
Jan Engelhardte44ea7f2009-01-30 03:55:09 +0100930 strcpy(buf, xtables_ipaddr_to_anyname(addr));
931 strcat(buf, xtables_ipmask_to_numeric(mask));
Jan Engelhardt73866352010-12-18 02:04:59 +0100932 printf(" %s", buf);
Marc Boucher5054e852002-01-19 10:59:12 +0000933 }
934}
935
Marc Boucher5054e852002-01-19 10:59:12 +0000936static void
Yasuyuki KOZAKAIc0a9ab92007-07-24 06:02:05 +0000937matchinfo_print(const void *ip, const struct xt_entry_match *match, int numeric, const char *optpfx)
Marc Boucher5054e852002-01-19 10:59:12 +0000938{
Jan Engelhardt69f564e2009-05-26 13:14:06 +0200939 const struct xt_conntrack_info *sinfo = (const void *)match->data;
Marc Boucher5054e852002-01-19 10:59:12 +0000940
Jan Engelhardta80b6042008-01-20 13:34:07 +0000941 if(sinfo->flags & XT_CONNTRACK_STATE) {
942 if (sinfo->invflags & XT_CONNTRACK_STATE)
Jan Engelhardt73866352010-12-18 02:04:59 +0100943 printf(" !");
944 printf(" %sctstate", optpfx);
Marc Boucher5054e852002-01-19 10:59:12 +0000945 print_state(sinfo->statemask);
946 }
947
Jan Engelhardta80b6042008-01-20 13:34:07 +0000948 if(sinfo->flags & XT_CONNTRACK_PROTO) {
949 if (sinfo->invflags & XT_CONNTRACK_PROTO)
Jan Engelhardt73866352010-12-18 02:04:59 +0100950 printf(" !");
951 printf(" %sctproto", optpfx);
952 printf(" %u", sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum);
Phil Oester5a4892b2005-11-17 13:34:51 +0000953 }
954
Jan Engelhardta80b6042008-01-20 13:34:07 +0000955 if(sinfo->flags & XT_CONNTRACK_ORIGSRC) {
956 if (sinfo->invflags & XT_CONNTRACK_ORIGSRC)
Jan Engelhardt73866352010-12-18 02:04:59 +0100957 printf(" !");
958 printf(" %sctorigsrc", optpfx);
Marc Boucher5054e852002-01-19 10:59:12 +0000959
960 print_addr(
961 (struct in_addr *)&sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip,
962 &sinfo->sipmsk[IP_CT_DIR_ORIGINAL],
Jan Engelhardta80b6042008-01-20 13:34:07 +0000963 false,
Marc Boucher5054e852002-01-19 10:59:12 +0000964 numeric);
965 }
966
Jan Engelhardta80b6042008-01-20 13:34:07 +0000967 if(sinfo->flags & XT_CONNTRACK_ORIGDST) {
968 if (sinfo->invflags & XT_CONNTRACK_ORIGDST)
Jan Engelhardt73866352010-12-18 02:04:59 +0100969 printf(" !");
970 printf(" %sctorigdst", optpfx);
Marc Boucher5054e852002-01-19 10:59:12 +0000971
972 print_addr(
973 (struct in_addr *)&sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip,
974 &sinfo->dipmsk[IP_CT_DIR_ORIGINAL],
Jan Engelhardta80b6042008-01-20 13:34:07 +0000975 false,
Marc Boucher5054e852002-01-19 10:59:12 +0000976 numeric);
977 }
978
Jan Engelhardta80b6042008-01-20 13:34:07 +0000979 if(sinfo->flags & XT_CONNTRACK_REPLSRC) {
980 if (sinfo->invflags & XT_CONNTRACK_REPLSRC)
Jan Engelhardt73866352010-12-18 02:04:59 +0100981 printf(" !");
982 printf(" %sctreplsrc", optpfx);
Marc Boucher5054e852002-01-19 10:59:12 +0000983
984 print_addr(
985 (struct in_addr *)&sinfo->tuple[IP_CT_DIR_REPLY].src.ip,
986 &sinfo->sipmsk[IP_CT_DIR_REPLY],
Jan Engelhardta80b6042008-01-20 13:34:07 +0000987 false,
Marc Boucher5054e852002-01-19 10:59:12 +0000988 numeric);
989 }
990
Jan Engelhardta80b6042008-01-20 13:34:07 +0000991 if(sinfo->flags & XT_CONNTRACK_REPLDST) {
992 if (sinfo->invflags & XT_CONNTRACK_REPLDST)
Jan Engelhardt73866352010-12-18 02:04:59 +0100993 printf(" !");
994 printf(" %sctrepldst", optpfx);
Marc Boucher5054e852002-01-19 10:59:12 +0000995
996 print_addr(
997 (struct in_addr *)&sinfo->tuple[IP_CT_DIR_REPLY].dst.ip,
998 &sinfo->dipmsk[IP_CT_DIR_REPLY],
Jan Engelhardta80b6042008-01-20 13:34:07 +0000999 false,
Marc Boucher5054e852002-01-19 10:59:12 +00001000 numeric);
1001 }
1002
Jan Engelhardta80b6042008-01-20 13:34:07 +00001003 if(sinfo->flags & XT_CONNTRACK_STATUS) {
1004 if (sinfo->invflags & XT_CONNTRACK_STATUS)
Jan Engelhardt73866352010-12-18 02:04:59 +01001005 printf(" !");
1006 printf(" %sctstatus", optpfx);
Marc Boucher5054e852002-01-19 10:59:12 +00001007 print_status(sinfo->statusmask);
1008 }
1009
Jan Engelhardta80b6042008-01-20 13:34:07 +00001010 if(sinfo->flags & XT_CONNTRACK_EXPIRES) {
1011 if (sinfo->invflags & XT_CONNTRACK_EXPIRES)
Jan Engelhardt73866352010-12-18 02:04:59 +01001012 printf(" !");
1013 printf(" %sctexpire ", optpfx);
Marc Boucher5054e852002-01-19 10:59:12 +00001014
1015 if (sinfo->expires_max == sinfo->expires_min)
Jan Engelhardt73866352010-12-18 02:04:59 +01001016 printf("%lu", sinfo->expires_min);
Marc Boucher5054e852002-01-19 10:59:12 +00001017 else
Jan Engelhardt73866352010-12-18 02:04:59 +01001018 printf("%lu:%lu", sinfo->expires_min, sinfo->expires_max);
Marc Boucher5054e852002-01-19 10:59:12 +00001019 }
Jan Engelhardtc7fc1da2008-11-12 12:03:25 +01001020
1021 if (sinfo->flags & XT_CONNTRACK_DIRECTION) {
1022 if (sinfo->invflags & XT_CONNTRACK_DIRECTION)
Jan Engelhardt73866352010-12-18 02:04:59 +01001023 printf(" %sctdir REPLY", optpfx);
Jan Engelhardtc7fc1da2008-11-12 12:03:25 +01001024 else
Jan Engelhardt73866352010-12-18 02:04:59 +01001025 printf(" %sctdir ORIGINAL", optpfx);
Jan Engelhardtc7fc1da2008-11-12 12:03:25 +01001026 }
1027
Marc Boucher5054e852002-01-19 10:59:12 +00001028}
1029
Jan Engelhardta8ad34c2008-01-29 13:37:21 +00001030static void
Patrick McHardyc8f28cc2011-01-20 11:45:12 +01001031conntrack_dump_ports(const char *prefix, const char *opt,
1032 u_int16_t port_low, u_int16_t port_high)
1033{
1034 if (port_high == 0 || port_low == port_high)
Jan Engelhardt73866352010-12-18 02:04:59 +01001035 printf(" %s%s %u", prefix, opt, port_low);
Patrick McHardyc8f28cc2011-01-20 11:45:12 +01001036 else
Jan Engelhardt73866352010-12-18 02:04:59 +01001037 printf(" %s%s %u:%u", prefix, opt, port_low, port_high);
Patrick McHardyc8f28cc2011-01-20 11:45:12 +01001038}
1039
1040static void
1041conntrack_dump(const struct xt_conntrack_mtinfo3 *info, const char *prefix,
1042 unsigned int family, bool numeric, bool v3)
Jan Engelhardta8ad34c2008-01-29 13:37:21 +00001043{
1044 if (info->match_flags & XT_CONNTRACK_STATE) {
1045 if (info->invert_flags & XT_CONNTRACK_STATE)
Jan Engelhardt73866352010-12-18 02:04:59 +01001046 printf(" !");
1047 printf(" %sctstate", prefix);
Jan Engelhardta8ad34c2008-01-29 13:37:21 +00001048 print_state(info->state_mask);
1049 }
1050
1051 if (info->match_flags & XT_CONNTRACK_PROTO) {
1052 if (info->invert_flags & XT_CONNTRACK_PROTO)
Jan Engelhardt73866352010-12-18 02:04:59 +01001053 printf(" !");
1054 printf(" %sctproto %u", prefix, info->l4proto);
Jan Engelhardta8ad34c2008-01-29 13:37:21 +00001055 }
1056
1057 if (info->match_flags & XT_CONNTRACK_ORIGSRC) {
Jan Engelhardt093d5fc2009-04-05 00:05:30 +02001058 if (info->invert_flags & XT_CONNTRACK_ORIGSRC)
Jan Engelhardt73866352010-12-18 02:04:59 +01001059 printf(" !");
1060 printf(" %sctorigsrc", prefix);
Jan Engelhardta8ad34c2008-01-29 13:37:21 +00001061 conntrack_dump_addr(&info->origsrc_addr, &info->origsrc_mask,
1062 family, numeric);
1063 }
1064
1065 if (info->match_flags & XT_CONNTRACK_ORIGDST) {
Jan Engelhardt093d5fc2009-04-05 00:05:30 +02001066 if (info->invert_flags & XT_CONNTRACK_ORIGDST)
Jan Engelhardt73866352010-12-18 02:04:59 +01001067 printf(" !");
1068 printf(" %sctorigdst", prefix);
Jan Engelhardta8ad34c2008-01-29 13:37:21 +00001069 conntrack_dump_addr(&info->origdst_addr, &info->origdst_mask,
1070 family, numeric);
1071 }
1072
1073 if (info->match_flags & XT_CONNTRACK_REPLSRC) {
Jan Engelhardt093d5fc2009-04-05 00:05:30 +02001074 if (info->invert_flags & XT_CONNTRACK_REPLSRC)
Jan Engelhardt73866352010-12-18 02:04:59 +01001075 printf(" !");
1076 printf(" %sctreplsrc", prefix);
Jan Engelhardta8ad34c2008-01-29 13:37:21 +00001077 conntrack_dump_addr(&info->replsrc_addr, &info->replsrc_mask,
1078 family, numeric);
1079 }
1080
1081 if (info->match_flags & XT_CONNTRACK_REPLDST) {
Jan Engelhardt093d5fc2009-04-05 00:05:30 +02001082 if (info->invert_flags & XT_CONNTRACK_REPLDST)
Jan Engelhardt73866352010-12-18 02:04:59 +01001083 printf(" !");
1084 printf(" %sctrepldst", prefix);
Jan Engelhardta8ad34c2008-01-29 13:37:21 +00001085 conntrack_dump_addr(&info->repldst_addr, &info->repldst_mask,
1086 family, numeric);
1087 }
1088
1089 if (info->match_flags & XT_CONNTRACK_ORIGSRC_PORT) {
1090 if (info->invert_flags & XT_CONNTRACK_ORIGSRC_PORT)
Jan Engelhardt73866352010-12-18 02:04:59 +01001091 printf(" !");
Patrick McHardyc8f28cc2011-01-20 11:45:12 +01001092 conntrack_dump_ports(prefix, "ctorigsrcport",
1093 v3 ? info->origsrc_port : ntohs(info->origsrc_port),
1094 v3 ? info->origsrc_port_high : 0);
Jan Engelhardta8ad34c2008-01-29 13:37:21 +00001095 }
1096
1097 if (info->match_flags & XT_CONNTRACK_ORIGDST_PORT) {
1098 if (info->invert_flags & XT_CONNTRACK_ORIGDST_PORT)
Jan Engelhardt73866352010-12-18 02:04:59 +01001099 printf(" !");
Patrick McHardyc8f28cc2011-01-20 11:45:12 +01001100 conntrack_dump_ports(prefix, "ctorigdstport",
1101 v3 ? info->origdst_port : ntohs(info->origdst_port),
1102 v3 ? info->origdst_port_high : 0);
Jan Engelhardta8ad34c2008-01-29 13:37:21 +00001103 }
1104
1105 if (info->match_flags & XT_CONNTRACK_REPLSRC_PORT) {
1106 if (info->invert_flags & XT_CONNTRACK_REPLSRC_PORT)
Jan Engelhardt73866352010-12-18 02:04:59 +01001107 printf(" !");
Patrick McHardyc8f28cc2011-01-20 11:45:12 +01001108 conntrack_dump_ports(prefix, "ctreplsrcport",
1109 v3 ? info->replsrc_port : ntohs(info->replsrc_port),
1110 v3 ? info->replsrc_port_high : 0);
Jan Engelhardta8ad34c2008-01-29 13:37:21 +00001111 }
1112
1113 if (info->match_flags & XT_CONNTRACK_REPLDST_PORT) {
1114 if (info->invert_flags & XT_CONNTRACK_REPLDST_PORT)
Jan Engelhardt73866352010-12-18 02:04:59 +01001115 printf(" !");
Patrick McHardyc8f28cc2011-01-20 11:45:12 +01001116 conntrack_dump_ports(prefix, "ctrepldstport",
1117 v3 ? info->repldst_port : ntohs(info->repldst_port),
1118 v3 ? info->repldst_port_high : 0);
Jan Engelhardta8ad34c2008-01-29 13:37:21 +00001119 }
1120
1121 if (info->match_flags & XT_CONNTRACK_STATUS) {
1122 if (info->invert_flags & XT_CONNTRACK_STATUS)
Jan Engelhardt73866352010-12-18 02:04:59 +01001123 printf(" !");
1124 printf(" %sctstatus", prefix);
Jan Engelhardta8ad34c2008-01-29 13:37:21 +00001125 print_status(info->status_mask);
1126 }
1127
1128 if (info->match_flags & XT_CONNTRACK_EXPIRES) {
1129 if (info->invert_flags & XT_CONNTRACK_EXPIRES)
Jan Engelhardt73866352010-12-18 02:04:59 +01001130 printf(" !");
1131 printf(" %sctexpire ", prefix);
Jan Engelhardta8ad34c2008-01-29 13:37:21 +00001132
1133 if (info->expires_max == info->expires_min)
Jan Engelhardt73866352010-12-18 02:04:59 +01001134 printf("%u", (unsigned int)info->expires_min);
Jan Engelhardta8ad34c2008-01-29 13:37:21 +00001135 else
Jan Engelhardt73866352010-12-18 02:04:59 +01001136 printf("%u:%u", (unsigned int)info->expires_min,
Jan Engelhardta8ad34c2008-01-29 13:37:21 +00001137 (unsigned int)info->expires_max);
1138 }
Jan Engelhardtc7fc1da2008-11-12 12:03:25 +01001139
1140 if (info->match_flags & XT_CONNTRACK_DIRECTION) {
1141 if (info->invert_flags & XT_CONNTRACK_DIRECTION)
Jan Engelhardt73866352010-12-18 02:04:59 +01001142 printf(" %sctdir REPLY", prefix);
Jan Engelhardtc7fc1da2008-11-12 12:03:25 +01001143 else
Jan Engelhardt73866352010-12-18 02:04:59 +01001144 printf(" %sctdir ORIGINAL", prefix);
Jan Engelhardtc7fc1da2008-11-12 12:03:25 +01001145 }
Jan Engelhardta8ad34c2008-01-29 13:37:21 +00001146}
1147
Jan Engelhardt59d16402007-10-04 16:28:39 +00001148static void conntrack_print(const void *ip, const struct xt_entry_match *match,
1149 int numeric)
Marc Boucher5054e852002-01-19 10:59:12 +00001150{
1151 matchinfo_print(ip, match, numeric, "");
1152}
1153
Jan Engelhardta8ad34c2008-01-29 13:37:21 +00001154static void
Jan Engelhardtb97b4212009-06-25 18:46:37 +02001155conntrack1_mt4_print(const void *ip, const struct xt_entry_match *match,
1156 int numeric)
1157{
1158 const struct xt_conntrack_mtinfo1 *info = (void *)match->data;
Patrick McHardyc8f28cc2011-01-20 11:45:12 +01001159 struct xt_conntrack_mtinfo3 up;
Jan Engelhardtb97b4212009-06-25 18:46:37 +02001160
1161 cinfo_transform(&up, info);
Patrick McHardyc8f28cc2011-01-20 11:45:12 +01001162 conntrack_dump(&up, "", NFPROTO_IPV4, numeric, false);
Jan Engelhardtb97b4212009-06-25 18:46:37 +02001163}
1164
1165static void
1166conntrack1_mt6_print(const void *ip, const struct xt_entry_match *match,
1167 int numeric)
1168{
1169 const struct xt_conntrack_mtinfo1 *info = (void *)match->data;
Patrick McHardyc8f28cc2011-01-20 11:45:12 +01001170 struct xt_conntrack_mtinfo3 up;
Jan Engelhardtb97b4212009-06-25 18:46:37 +02001171
1172 cinfo_transform(&up, info);
Patrick McHardyc8f28cc2011-01-20 11:45:12 +01001173 conntrack_dump(&up, "", NFPROTO_IPV6, numeric, false);
Jan Engelhardtb97b4212009-06-25 18:46:37 +02001174}
1175
1176static void
Patrick McHardyc8f28cc2011-01-20 11:45:12 +01001177conntrack2_mt_print(const void *ip, const struct xt_entry_match *match,
Jan Engelhardta8ad34c2008-01-29 13:37:21 +00001178 int numeric)
1179{
Patrick McHardyc8f28cc2011-01-20 11:45:12 +01001180 conntrack_dump((const void *)match->data, "", NFPROTO_IPV4, numeric, false);
1181}
1182
1183static void
1184conntrack2_mt6_print(const void *ip, const struct xt_entry_match *match,
1185 int numeric)
1186{
1187 conntrack_dump((const void *)match->data, "", NFPROTO_IPV6, numeric, false);
1188}
1189
1190static void
1191conntrack3_mt_print(const void *ip, const struct xt_entry_match *match,
1192 int numeric)
1193{
1194 conntrack_dump((const void *)match->data, "", NFPROTO_IPV4, numeric, true);
1195}
1196
1197static void
1198conntrack3_mt6_print(const void *ip, const struct xt_entry_match *match,
1199 int numeric)
1200{
1201 conntrack_dump((const void *)match->data, "", NFPROTO_IPV6, numeric, true);
Jan Engelhardta8ad34c2008-01-29 13:37:21 +00001202}
1203
Jan Engelhardt59d16402007-10-04 16:28:39 +00001204static void conntrack_save(const void *ip, const struct xt_entry_match *match)
Marc Boucher5054e852002-01-19 10:59:12 +00001205{
Joszef Kadlecsikdb503f92004-05-05 10:10:33 +00001206 matchinfo_print(ip, match, 1, "--");
Marc Boucher5054e852002-01-19 10:59:12 +00001207}
1208
Patrick McHardyc8f28cc2011-01-20 11:45:12 +01001209static void conntrack3_mt_save(const void *ip,
Jan Engelhardta8ad34c2008-01-29 13:37:21 +00001210 const struct xt_entry_match *match)
1211{
Patrick McHardyc8f28cc2011-01-20 11:45:12 +01001212 conntrack_dump((const void *)match->data, "--", NFPROTO_IPV4, true, true);
1213}
1214
1215static void conntrack3_mt6_save(const void *ip,
1216 const struct xt_entry_match *match)
1217{
1218 conntrack_dump((const void *)match->data, "--", NFPROTO_IPV6, true, true);
1219}
1220
1221static void conntrack2_mt_save(const void *ip,
1222 const struct xt_entry_match *match)
1223{
1224 conntrack_dump((const void *)match->data, "--", NFPROTO_IPV4, true, false);
1225}
1226
1227static void conntrack2_mt6_save(const void *ip,
1228 const struct xt_entry_match *match)
1229{
1230 conntrack_dump((const void *)match->data, "--", NFPROTO_IPV6, true, false);
Jan Engelhardta8ad34c2008-01-29 13:37:21 +00001231}
1232
Jan Engelhardtb97b4212009-06-25 18:46:37 +02001233static void
1234conntrack1_mt4_save(const void *ip, const struct xt_entry_match *match)
1235{
1236 const struct xt_conntrack_mtinfo1 *info = (void *)match->data;
Patrick McHardyc8f28cc2011-01-20 11:45:12 +01001237 struct xt_conntrack_mtinfo3 up;
Jan Engelhardtb97b4212009-06-25 18:46:37 +02001238
1239 cinfo_transform(&up, info);
Patrick McHardyc8f28cc2011-01-20 11:45:12 +01001240 conntrack_dump(&up, "--", NFPROTO_IPV4, true, false);
Jan Engelhardtb97b4212009-06-25 18:46:37 +02001241}
1242
1243static void
1244conntrack1_mt6_save(const void *ip, const struct xt_entry_match *match)
1245{
1246 const struct xt_conntrack_mtinfo1 *info = (void *)match->data;
Patrick McHardyc8f28cc2011-01-20 11:45:12 +01001247 struct xt_conntrack_mtinfo3 up;
Jan Engelhardtb97b4212009-06-25 18:46:37 +02001248
1249 cinfo_transform(&up, info);
Patrick McHardyc8f28cc2011-01-20 11:45:12 +01001250 conntrack_dump(&up, "--", NFPROTO_IPV6, true, false);
Jan Engelhardtb97b4212009-06-25 18:46:37 +02001251}
1252
Jan Engelhardtf2a77522009-06-25 20:12:12 +02001253static struct xtables_match conntrack_mt_reg[] = {
1254 {
1255 .version = XTABLES_VERSION,
1256 .name = "conntrack",
1257 .revision = 0,
1258 .family = NFPROTO_IPV4,
1259 .size = XT_ALIGN(sizeof(struct xt_conntrack_info)),
1260 .userspacesize = XT_ALIGN(sizeof(struct xt_conntrack_info)),
1261 .help = conntrack_mt_help,
1262 .parse = conntrack_parse,
1263 .final_check = conntrack_mt_check,
1264 .print = conntrack_print,
1265 .save = conntrack_save,
1266 .extra_opts = conntrack_mt_opts_v0,
1267 },
1268 {
1269 .version = XTABLES_VERSION,
1270 .name = "conntrack",
1271 .revision = 1,
1272 .family = NFPROTO_IPV4,
1273 .size = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo1)),
1274 .userspacesize = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo1)),
1275 .help = conntrack_mt_help,
Jan Engelhardt8e4daca2009-08-05 18:13:11 +02001276 .parse = conntrack1_mt4_parse,
Jan Engelhardtf2a77522009-06-25 20:12:12 +02001277 .final_check = conntrack_mt_check,
Jan Engelhardt8e4daca2009-08-05 18:13:11 +02001278 .print = conntrack1_mt4_print,
1279 .save = conntrack1_mt4_save,
Jan Engelhardtf2a77522009-06-25 20:12:12 +02001280 .extra_opts = conntrack_mt_opts,
1281 },
1282 {
1283 .version = XTABLES_VERSION,
1284 .name = "conntrack",
1285 .revision = 1,
1286 .family = NFPROTO_IPV6,
1287 .size = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo1)),
1288 .userspacesize = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo1)),
1289 .help = conntrack_mt_help,
Jan Engelhardt8e4daca2009-08-05 18:13:11 +02001290 .parse = conntrack1_mt6_parse,
1291 .final_check = conntrack_mt_check,
1292 .print = conntrack1_mt6_print,
1293 .save = conntrack1_mt6_save,
1294 .extra_opts = conntrack_mt_opts,
1295 },
1296 {
1297 .version = XTABLES_VERSION,
1298 .name = "conntrack",
1299 .revision = 2,
1300 .family = NFPROTO_IPV4,
1301 .size = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo2)),
1302 .userspacesize = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo2)),
1303 .help = conntrack_mt_help,
1304 .parse = conntrack2_mt4_parse,
1305 .final_check = conntrack_mt_check,
Patrick McHardyc8f28cc2011-01-20 11:45:12 +01001306 .print = conntrack2_mt_print,
1307 .save = conntrack2_mt_save,
Jan Engelhardt8e4daca2009-08-05 18:13:11 +02001308 .extra_opts = conntrack_mt_opts,
1309 },
1310 {
1311 .version = XTABLES_VERSION,
1312 .name = "conntrack",
1313 .revision = 2,
1314 .family = NFPROTO_IPV6,
1315 .size = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo2)),
1316 .userspacesize = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo2)),
1317 .help = conntrack_mt_help,
1318 .parse = conntrack2_mt6_parse,
Jan Engelhardtf2a77522009-06-25 20:12:12 +02001319 .final_check = conntrack_mt_check,
Patrick McHardyc8f28cc2011-01-20 11:45:12 +01001320 .print = conntrack2_mt6_print,
1321 .save = conntrack2_mt6_save,
1322 .extra_opts = conntrack_mt_opts,
1323 },
1324 {
1325 .version = XTABLES_VERSION,
1326 .name = "conntrack",
1327 .revision = 3,
1328 .family = NFPROTO_IPV4,
1329 .size = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo3)),
1330 .userspacesize = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo3)),
1331 .help = conntrack_mt_help,
1332 .parse = conntrack3_mt4_parse,
1333 .final_check = conntrack_mt_check,
1334 .print = conntrack3_mt_print,
1335 .save = conntrack3_mt_save,
1336 .extra_opts = conntrack_mt_opts,
1337 },
1338 {
1339 .version = XTABLES_VERSION,
1340 .name = "conntrack",
1341 .revision = 3,
1342 .family = NFPROTO_IPV6,
1343 .size = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo3)),
1344 .userspacesize = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo3)),
1345 .help = conntrack_mt_help,
1346 .parse = conntrack3_mt6_parse,
1347 .final_check = conntrack_mt_check,
1348 .print = conntrack3_mt6_print,
1349 .save = conntrack3_mt6_save,
Jan Engelhardtf2a77522009-06-25 20:12:12 +02001350 .extra_opts = conntrack_mt_opts,
1351 },
Marc Boucher5054e852002-01-19 10:59:12 +00001352};
1353
1354void _init(void)
1355{
Jan Engelhardtf2a77522009-06-25 20:12:12 +02001356 xtables_register_matches(conntrack_mt_reg, ARRAY_SIZE(conntrack_mt_reg));
Marc Boucher5054e852002-01-19 10:59:12 +00001357}