~ubuntu-branches/ubuntu/lucid/iptables/lucid

« back to all changes in this revision

Viewing changes to extensions/libxt_conntrack.c

  • Committer: Bazaar Package Importer
  • Author(s): Soren Hansen, Iain Lane, Soren Hansen
  • Date: 2008-11-15 01:27:37 UTC
  • mfrom: (5.1.5 upstream)
  • Revision ID: james.westby@ubuntu.com-20081115012737-o3kdn2z1o9ercq10
Tags: 1.4.1.1-4ubuntu1
[ Iain Lane ]
* Merge from debian unstable (LP: #294220), remaining changes:
  - debian/patches/0901-build-libipq_pic.a.patch - Build libipq_pic.a with
    -fPIC. Upstream changed build system and patch modified accordingly.

[ Soren Hansen ]
* Revert changes between 1.4.1.1-3 and 1.4.1.1-4, thus bringing back
  the howtos.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
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>
 
8
 */
 
9
#include <sys/socket.h>
 
10
#include <sys/types.h>
 
11
#include <ctype.h>
 
12
#include <getopt.h>
 
13
#include <netdb.h>
 
14
#include <stdbool.h>
 
15
#include <stdio.h>
 
16
#include <stdlib.h>
 
17
#include <string.h>
 
18
#include <iptables.h>
 
19
#include <xtables.h>
 
20
#include <linux/netfilter.h>
 
21
#include <linux/netfilter/xt_conntrack.h>
 
22
#include <linux/netfilter/nf_conntrack_common.h>
 
23
#include <arpa/inet.h>
 
24
 
 
25
/* Function which prints out usage message. */
 
26
static void conntrack_mt_help(void)
 
27
{
 
28
        printf(
 
29
"conntrack match options:\n"
 
30
"[!] --ctstate {INVALID|ESTABLISHED|NEW|RELATED|UNTRACKED|SNAT|DNAT}[,...]\n"
 
31
"                               State(s) to match\n"
 
32
"[!] --ctproto proto            Protocol to match; by number or name, e.g. \"tcp\"\n"
 
33
"[!] --ctorigsrc address[/mask]\n"
 
34
"[!] --ctorigdst address[/mask]\n"
 
35
"[!] --ctreplsrc address[/mask]\n"
 
36
"[!] --ctrepldst address[/mask]\n"
 
37
"                               Original/Reply source/destination address\n"
 
38
"[!] --ctorigsrcport port\n"
 
39
"[!] --ctorigdstport port\n"
 
40
"[!] --ctreplsrcport port\n"
 
41
"[!] --ctrepldstport port\n"
 
42
"                               TCP/UDP/SCTP orig./reply source/destination port\n"
 
43
"[!] --ctstatus {NONE|EXPECTED|SEEN_REPLY|ASSURED|CONFIRMED}[,...]\n"
 
44
"                               Status(es) to match\n"
 
45
"[!] --ctexpire time[:time]     Match remaining lifetime in seconds against\n"
 
46
"                               value or range of values (inclusive)\n"
 
47
"    --ctdir {ORIGINAL|REPLY}   Flow direction of packet\n");
 
48
}
 
49
 
 
50
static const struct option conntrack_mt_opts_v0[] = {
 
51
        {.name = "ctstate",   .has_arg = true, .val = '1'},
 
52
        {.name = "ctproto",   .has_arg = true, .val = '2'},
 
53
        {.name = "ctorigsrc", .has_arg = true, .val = '3'},
 
54
        {.name = "ctorigdst", .has_arg = true, .val = '4'},
 
55
        {.name = "ctreplsrc", .has_arg = true, .val = '5'},
 
56
        {.name = "ctrepldst", .has_arg = true, .val = '6'},
 
57
        {.name = "ctstatus",  .has_arg = true, .val = '7'},
 
58
        {.name = "ctexpire",  .has_arg = true, .val = '8'},
 
59
        { .name = NULL }
 
60
};
 
61
 
 
62
static const struct option conntrack_mt_opts[] = {
 
63
        {.name = "ctstate",       .has_arg = true, .val = '1'},
 
64
        {.name = "ctproto",       .has_arg = true, .val = '2'},
 
65
        {.name = "ctorigsrc",     .has_arg = true, .val = '3'},
 
66
        {.name = "ctorigdst",     .has_arg = true, .val = '4'},
 
67
        {.name = "ctreplsrc",     .has_arg = true, .val = '5'},
 
68
        {.name = "ctrepldst",     .has_arg = true, .val = '6'},
 
69
        {.name = "ctstatus",      .has_arg = true, .val = '7'},
 
70
        {.name = "ctexpire",      .has_arg = true, .val = '8'},
 
71
        {.name = "ctorigsrcport", .has_arg = true, .val = 'a'},
 
72
        {.name = "ctorigdstport", .has_arg = true, .val = 'b'},
 
73
        {.name = "ctreplsrcport", .has_arg = true, .val = 'c'},
 
74
        {.name = "ctrepldstport", .has_arg = true, .val = 'd'},
 
75
        {.name = "ctdir",         .has_arg = true, .val = 'e'},
 
76
        {.name = NULL},
 
77
};
 
78
 
 
79
static int
 
80
parse_state(const char *state, size_t len, struct xt_conntrack_info *sinfo)
 
81
{
 
82
        if (strncasecmp(state, "INVALID", len) == 0)
 
83
                sinfo->statemask |= XT_CONNTRACK_STATE_INVALID;
 
84
        else if (strncasecmp(state, "NEW", len) == 0)
 
85
                sinfo->statemask |= XT_CONNTRACK_STATE_BIT(IP_CT_NEW);
 
86
        else if (strncasecmp(state, "ESTABLISHED", len) == 0)
 
87
                sinfo->statemask |= XT_CONNTRACK_STATE_BIT(IP_CT_ESTABLISHED);
 
88
        else if (strncasecmp(state, "RELATED", len) == 0)
 
89
                sinfo->statemask |= XT_CONNTRACK_STATE_BIT(IP_CT_RELATED);
 
90
        else if (strncasecmp(state, "UNTRACKED", len) == 0)
 
91
                sinfo->statemask |= XT_CONNTRACK_STATE_UNTRACKED;
 
92
        else if (strncasecmp(state, "SNAT", len) == 0)
 
93
                sinfo->statemask |= XT_CONNTRACK_STATE_SNAT;
 
94
        else if (strncasecmp(state, "DNAT", len) == 0)
 
95
                sinfo->statemask |= XT_CONNTRACK_STATE_DNAT;
 
96
        else
 
97
                return 0;
 
98
        return 1;
 
99
}
 
100
 
 
101
static void
 
102
parse_states(const char *arg, struct xt_conntrack_info *sinfo)
 
103
{
 
104
        const char *comma;
 
105
 
 
106
        while ((comma = strchr(arg, ',')) != NULL) {
 
107
                if (comma == arg || !parse_state(arg, comma-arg, sinfo))
 
108
                        exit_error(PARAMETER_PROBLEM, "Bad ctstate `%s'", arg);
 
109
                arg = comma+1;
 
110
        }
 
111
 
 
112
        if (strlen(arg) == 0 || !parse_state(arg, strlen(arg), sinfo))
 
113
                exit_error(PARAMETER_PROBLEM, "Bad ctstate `%s'", arg);
 
114
}
 
115
 
 
116
static bool
 
117
conntrack_ps_state(struct xt_conntrack_mtinfo1 *info, const char *state,
 
118
                   size_t z)
 
119
{
 
120
        if (strncasecmp(state, "INVALID", z) == 0)
 
121
                info->state_mask |= XT_CONNTRACK_STATE_INVALID;
 
122
        else if (strncasecmp(state, "NEW", z) == 0)
 
123
                info->state_mask |= XT_CONNTRACK_STATE_BIT(IP_CT_NEW);
 
124
        else if (strncasecmp(state, "ESTABLISHED", z) == 0)
 
125
                info->state_mask |= XT_CONNTRACK_STATE_BIT(IP_CT_ESTABLISHED);
 
126
        else if (strncasecmp(state, "RELATED", z) == 0)
 
127
                info->state_mask |= XT_CONNTRACK_STATE_BIT(IP_CT_RELATED);
 
128
        else if (strncasecmp(state, "UNTRACKED", z) == 0)
 
129
                info->state_mask |= XT_CONNTRACK_STATE_UNTRACKED;
 
130
        else if (strncasecmp(state, "SNAT", z) == 0)
 
131
                info->state_mask |= XT_CONNTRACK_STATE_SNAT;
 
132
        else if (strncasecmp(state, "DNAT", z) == 0)
 
133
                info->state_mask |= XT_CONNTRACK_STATE_DNAT;
 
134
        else
 
135
                return false;
 
136
        return true;
 
137
}
 
138
 
 
139
static void
 
140
conntrack_ps_states(struct xt_conntrack_mtinfo1 *info, const char *arg)
 
141
{
 
142
        const char *comma;
 
143
 
 
144
        while ((comma = strchr(arg, ',')) != NULL) {
 
145
                if (comma == arg || !conntrack_ps_state(info, arg, comma - arg))
 
146
                        exit_error(PARAMETER_PROBLEM,
 
147
                                   "Bad ctstate \"%s\"", arg);
 
148
                arg = comma + 1;
 
149
        }
 
150
 
 
151
        if (strlen(arg) == 0 || !conntrack_ps_state(info, arg, strlen(arg)))
 
152
                exit_error(PARAMETER_PROBLEM, "Bad ctstate \"%s\"", arg);
 
153
}
 
154
 
 
155
static int
 
156
parse_status(const char *status, size_t len, struct xt_conntrack_info *sinfo)
 
157
{
 
158
        if (strncasecmp(status, "NONE", len) == 0)
 
159
                sinfo->statusmask |= 0;
 
160
        else if (strncasecmp(status, "EXPECTED", len) == 0)
 
161
                sinfo->statusmask |= IPS_EXPECTED;
 
162
        else if (strncasecmp(status, "SEEN_REPLY", len) == 0)
 
163
                sinfo->statusmask |= IPS_SEEN_REPLY;
 
164
        else if (strncasecmp(status, "ASSURED", len) == 0)
 
165
                sinfo->statusmask |= IPS_ASSURED;
 
166
#ifdef IPS_CONFIRMED
 
167
        else if (strncasecmp(status, "CONFIRMED", len) == 0)
 
168
                sinfo->statusmask |= IPS_CONFIRMED;
 
169
#endif
 
170
        else
 
171
                return 0;
 
172
        return 1;
 
173
}
 
174
 
 
175
static void
 
176
parse_statuses(const char *arg, struct xt_conntrack_info *sinfo)
 
177
{
 
178
        const char *comma;
 
179
 
 
180
        while ((comma = strchr(arg, ',')) != NULL) {
 
181
                if (comma == arg || !parse_status(arg, comma-arg, sinfo))
 
182
                        exit_error(PARAMETER_PROBLEM, "Bad ctstatus `%s'", arg);
 
183
                arg = comma+1;
 
184
        }
 
185
 
 
186
        if (strlen(arg) == 0 || !parse_status(arg, strlen(arg), sinfo))
 
187
                exit_error(PARAMETER_PROBLEM, "Bad ctstatus `%s'", arg);
 
188
}
 
189
 
 
190
static bool
 
191
conntrack_ps_status(struct xt_conntrack_mtinfo1 *info, const char *status,
 
192
                    size_t z)
 
193
{
 
194
        if (strncasecmp(status, "NONE", z) == 0)
 
195
                info->status_mask |= 0;
 
196
        else if (strncasecmp(status, "EXPECTED", z) == 0)
 
197
                info->status_mask |= IPS_EXPECTED;
 
198
        else if (strncasecmp(status, "SEEN_REPLY", z) == 0)
 
199
                info->status_mask |= IPS_SEEN_REPLY;
 
200
        else if (strncasecmp(status, "ASSURED", z) == 0)
 
201
                info->status_mask |= IPS_ASSURED;
 
202
        else if (strncasecmp(status, "CONFIRMED", z) == 0)
 
203
                info->status_mask |= IPS_CONFIRMED;
 
204
        else
 
205
                return false;
 
206
        return true;
 
207
}
 
208
 
 
209
static void
 
210
conntrack_ps_statuses(struct xt_conntrack_mtinfo1 *info, const char *arg)
 
211
{
 
212
        const char *comma;
 
213
 
 
214
        while ((comma = strchr(arg, ',')) != NULL) {
 
215
                if (comma == arg || !conntrack_ps_status(info, arg, comma - arg))
 
216
                        exit_error(PARAMETER_PROBLEM,
 
217
                                   "Bad ctstatus \"%s\"", arg);
 
218
                arg = comma + 1;
 
219
        }
 
220
 
 
221
        if (strlen(arg) == 0 || !conntrack_ps_status(info, arg, strlen(arg)))
 
222
                exit_error(PARAMETER_PROBLEM, "Bad ctstatus \"%s\"", arg);
 
223
}
 
224
 
 
225
static unsigned long
 
226
parse_expire(const char *s)
 
227
{
 
228
        unsigned int len;
 
229
 
 
230
        if (string_to_number(s, 0, 0, &len) == -1)
 
231
                exit_error(PARAMETER_PROBLEM, "expire value invalid: `%s'\n", s);
 
232
        else
 
233
                return len;
 
234
}
 
235
 
 
236
/* If a single value is provided, min and max are both set to the value */
 
237
static void
 
238
parse_expires(const char *s, struct xt_conntrack_info *sinfo)
 
239
{
 
240
        char *buffer;
 
241
        char *cp;
 
242
 
 
243
        buffer = strdup(s);
 
244
        if ((cp = strchr(buffer, ':')) == NULL)
 
245
                sinfo->expires_min = sinfo->expires_max =
 
246
                        parse_expire(buffer);
 
247
        else {
 
248
                *cp = '\0';
 
249
                cp++;
 
250
 
 
251
                sinfo->expires_min = buffer[0] ? parse_expire(buffer) : 0;
 
252
                sinfo->expires_max = cp[0]
 
253
                        ? parse_expire(cp)
 
254
                        : (unsigned long)-1;
 
255
        }
 
256
        free(buffer);
 
257
 
 
258
        if (sinfo->expires_min > sinfo->expires_max)
 
259
                exit_error(PARAMETER_PROBLEM,
 
260
                           "expire min. range value `%lu' greater than max. "
 
261
                           "range value `%lu'", sinfo->expires_min, sinfo->expires_max);
 
262
}
 
263
 
 
264
static void
 
265
conntrack_ps_expires(struct xt_conntrack_mtinfo1 *info, const char *s)
 
266
{
 
267
        unsigned int min, max;
 
268
        char *end;
 
269
 
 
270
        if (!strtonum(s, &end, &min, 0, ~0))
 
271
                param_act(P_BAD_VALUE, "conntrack", "--expires", s);
 
272
        max = min;
 
273
        if (*end == ':')
 
274
                if (!strtonum(s, &end, &max, 0, ~0U))
 
275
                        param_act(P_BAD_VALUE, "conntrack", "--expires", s);
 
276
        if (*end != '\0')
 
277
                param_act(P_BAD_VALUE, "conntrack", "--expires", s);
 
278
 
 
279
        if (min > max)
 
280
                exit_error(PARAMETER_PROBLEM,
 
281
                           "expire min. range value \"%u\" greater than max. "
 
282
                           "range value \"%u\"", min, max);
 
283
 
 
284
        info->expires_min = min;
 
285
        info->expires_max = max;
 
286
}
 
287
 
 
288
/* Function which parses command options; returns true if it
 
289
   ate an option */
 
290
static int conntrack_parse(int c, char **argv, int invert, unsigned int *flags,
 
291
                           const void *entry, struct xt_entry_match **match)
 
292
{
 
293
        struct xt_conntrack_info *sinfo = (void *)(*match)->data;
 
294
        char *protocol = NULL;
 
295
        unsigned int naddrs = 0;
 
296
        struct in_addr *addrs = NULL;
 
297
 
 
298
 
 
299
        switch (c) {
 
300
        case '1':
 
301
                check_inverse(optarg, &invert, &optind, 0);
 
302
 
 
303
                parse_states(argv[optind-1], sinfo);
 
304
                if (invert) {
 
305
                        sinfo->invflags |= XT_CONNTRACK_STATE;
 
306
                }
 
307
                sinfo->flags |= XT_CONNTRACK_STATE;
 
308
                break;
 
309
 
 
310
        case '2':
 
311
                check_inverse(optarg, &invert, &optind, 0);
 
312
 
 
313
                if(invert)
 
314
                        sinfo->invflags |= XT_CONNTRACK_PROTO;
 
315
 
 
316
                /* Canonicalize into lower case */
 
317
                for (protocol = argv[optind-1]; *protocol; protocol++)
 
318
                        *protocol = tolower(*protocol);
 
319
 
 
320
                protocol = argv[optind-1];
 
321
                sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum = parse_protocol(protocol);
 
322
 
 
323
                if (sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum == 0
 
324
                    && (sinfo->invflags & XT_INV_PROTO))
 
325
                        exit_error(PARAMETER_PROBLEM,
 
326
                                   "rule would never match protocol");
 
327
 
 
328
                sinfo->flags |= XT_CONNTRACK_PROTO;
 
329
                break;
 
330
 
 
331
        case '3':
 
332
                check_inverse(optarg, &invert, &optind, 0);
 
333
 
 
334
                if (invert)
 
335
                        sinfo->invflags |= XT_CONNTRACK_ORIGSRC;
 
336
 
 
337
                ipparse_hostnetworkmask(argv[optind-1], &addrs,
 
338
                                        &sinfo->sipmsk[IP_CT_DIR_ORIGINAL],
 
339
                                        &naddrs);
 
340
                if(naddrs > 1)
 
341
                        exit_error(PARAMETER_PROBLEM,
 
342
                                "multiple IP addresses not allowed");
 
343
 
 
344
                if(naddrs == 1) {
 
345
                        sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip = addrs[0].s_addr;
 
346
                }
 
347
 
 
348
                sinfo->flags |= XT_CONNTRACK_ORIGSRC;
 
349
                break;
 
350
 
 
351
        case '4':
 
352
                check_inverse(optarg, &invert, &optind, 0);
 
353
 
 
354
                if (invert)
 
355
                        sinfo->invflags |= XT_CONNTRACK_ORIGDST;
 
356
 
 
357
                ipparse_hostnetworkmask(argv[optind-1], &addrs,
 
358
                                        &sinfo->dipmsk[IP_CT_DIR_ORIGINAL],
 
359
                                        &naddrs);
 
360
                if(naddrs > 1)
 
361
                        exit_error(PARAMETER_PROBLEM,
 
362
                                "multiple IP addresses not allowed");
 
363
 
 
364
                if(naddrs == 1) {
 
365
                        sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip = addrs[0].s_addr;
 
366
                }
 
367
 
 
368
                sinfo->flags |= XT_CONNTRACK_ORIGDST;
 
369
                break;
 
370
 
 
371
        case '5':
 
372
                check_inverse(optarg, &invert, &optind, 0);
 
373
 
 
374
                if (invert)
 
375
                        sinfo->invflags |= XT_CONNTRACK_REPLSRC;
 
376
 
 
377
                ipparse_hostnetworkmask(argv[optind-1], &addrs,
 
378
                                        &sinfo->sipmsk[IP_CT_DIR_REPLY],
 
379
                                        &naddrs);
 
380
                if(naddrs > 1)
 
381
                        exit_error(PARAMETER_PROBLEM,
 
382
                                "multiple IP addresses not allowed");
 
383
 
 
384
                if(naddrs == 1) {
 
385
                        sinfo->tuple[IP_CT_DIR_REPLY].src.ip = addrs[0].s_addr;
 
386
                }
 
387
 
 
388
                sinfo->flags |= XT_CONNTRACK_REPLSRC;
 
389
                break;
 
390
 
 
391
        case '6':
 
392
                check_inverse(optarg, &invert, &optind, 0);
 
393
 
 
394
                if (invert)
 
395
                        sinfo->invflags |= XT_CONNTRACK_REPLDST;
 
396
 
 
397
                ipparse_hostnetworkmask(argv[optind-1], &addrs,
 
398
                                        &sinfo->dipmsk[IP_CT_DIR_REPLY],
 
399
                                        &naddrs);
 
400
                if(naddrs > 1)
 
401
                        exit_error(PARAMETER_PROBLEM,
 
402
                                "multiple IP addresses not allowed");
 
403
 
 
404
                if(naddrs == 1) {
 
405
                        sinfo->tuple[IP_CT_DIR_REPLY].dst.ip = addrs[0].s_addr;
 
406
                }
 
407
 
 
408
                sinfo->flags |= XT_CONNTRACK_REPLDST;
 
409
                break;
 
410
 
 
411
        case '7':
 
412
                check_inverse(optarg, &invert, &optind, 0);
 
413
 
 
414
                parse_statuses(argv[optind-1], sinfo);
 
415
                if (invert) {
 
416
                        sinfo->invflags |= XT_CONNTRACK_STATUS;
 
417
                }
 
418
                sinfo->flags |= XT_CONNTRACK_STATUS;
 
419
                break;
 
420
 
 
421
        case '8':
 
422
                check_inverse(optarg, &invert, &optind, 0);
 
423
 
 
424
                parse_expires(argv[optind-1], sinfo);
 
425
                if (invert) {
 
426
                        sinfo->invflags |= XT_CONNTRACK_EXPIRES;
 
427
                }
 
428
                sinfo->flags |= XT_CONNTRACK_EXPIRES;
 
429
                break;
 
430
 
 
431
        default:
 
432
                return 0;
 
433
        }
 
434
 
 
435
        *flags = sinfo->flags;
 
436
        return 1;
 
437
}
 
438
 
 
439
static int
 
440
conntrack_mt_parse(int c, char **argv, int invert, unsigned int *flags,
 
441
                   struct xt_entry_match **match)
 
442
{
 
443
        struct xt_conntrack_mtinfo1 *info = (void *)(*match)->data;
 
444
        unsigned int port;
 
445
        char *p;
 
446
 
 
447
        switch (c) {
 
448
        case '1': /* --ctstate */
 
449
                conntrack_ps_states(info, optarg);
 
450
                info->match_flags |= XT_CONNTRACK_STATE;
 
451
                if (invert)
 
452
                        info->invert_flags |= XT_CONNTRACK_STATE;
 
453
                break;
 
454
 
 
455
        case '2': /* --ctproto */
 
456
                /* Canonicalize into lower case */
 
457
                for (p = optarg; *p != '\0'; ++p)
 
458
                        *p = tolower(*p);
 
459
                info->l4proto = parse_protocol(optarg);
 
460
 
 
461
                if (info->l4proto == 0 && (info->invert_flags & XT_INV_PROTO))
 
462
                        exit_error(PARAMETER_PROBLEM, "conntrack: rule would "
 
463
                                   "never match protocol");
 
464
 
 
465
                info->match_flags |= XT_CONNTRACK_PROTO;
 
466
                if (invert)
 
467
                        info->invert_flags |= XT_CONNTRACK_PROTO;
 
468
                break;
 
469
 
 
470
        case '7': /* --ctstatus */
 
471
                conntrack_ps_statuses(info, optarg);
 
472
                info->match_flags |= XT_CONNTRACK_STATUS;
 
473
                if (invert)
 
474
                        info->invert_flags |= XT_CONNTRACK_STATUS;
 
475
                break;
 
476
 
 
477
        case '8': /* --ctexpire */
 
478
                conntrack_ps_expires(info, optarg);
 
479
                info->match_flags |= XT_CONNTRACK_EXPIRES;
 
480
                if (invert)
 
481
                        info->invert_flags |= XT_CONNTRACK_EXPIRES;
 
482
                break;
 
483
 
 
484
        case 'a': /* --ctorigsrcport */
 
485
                if (!strtonum(optarg, NULL, &port, 0, ~(u_int16_t)0))
 
486
                        param_act(P_BAD_VALUE, "conntrack",
 
487
                                  "--ctorigsrcport", optarg);
 
488
                info->match_flags |= XT_CONNTRACK_ORIGSRC_PORT;
 
489
                info->origsrc_port = htons(port);
 
490
                if (invert)
 
491
                        info->invert_flags |= XT_CONNTRACK_ORIGSRC_PORT;
 
492
                break;
 
493
 
 
494
        case 'b': /* --ctorigdstport */
 
495
                if (!strtonum(optarg, NULL, &port, 0, ~(u_int16_t)0))
 
496
                        param_act(P_BAD_VALUE, "conntrack",
 
497
                                  "--ctorigdstport", optarg);
 
498
                info->match_flags |= XT_CONNTRACK_ORIGDST_PORT;
 
499
                info->origdst_port = htons(port);
 
500
                if (invert)
 
501
                        info->invert_flags |= XT_CONNTRACK_ORIGDST_PORT;
 
502
                break;
 
503
 
 
504
        case 'c': /* --ctreplsrcport */
 
505
                if (!strtonum(optarg, NULL, &port, 0, ~(u_int16_t)0))
 
506
                        param_act(P_BAD_VALUE, "conntrack",
 
507
                                  "--ctreplsrcport", optarg);
 
508
                info->match_flags |= XT_CONNTRACK_REPLSRC_PORT;
 
509
                info->replsrc_port = htons(port);
 
510
                if (invert)
 
511
                        info->invert_flags |= XT_CONNTRACK_REPLSRC_PORT;
 
512
                break;
 
513
 
 
514
        case 'd': /* --ctrepldstport */
 
515
                if (!strtonum(optarg, NULL, &port, 0, ~(u_int16_t)0))
 
516
                        param_act(P_BAD_VALUE, "conntrack",
 
517
                                  "--ctrepldstport", optarg);
 
518
                info->match_flags |= XT_CONNTRACK_REPLDST_PORT;
 
519
                info->repldst_port = htons(port);
 
520
                if (invert)
 
521
                        info->invert_flags |= XT_CONNTRACK_REPLDST_PORT;
 
522
                break;
 
523
 
 
524
        case 'e': /* --ctdir */
 
525
                param_act(P_NO_INVERT, "conntrack", "--ctdir", invert);
 
526
                if (strcasecmp(optarg, "ORIGINAL") == 0) {
 
527
                        info->match_flags  |= XT_CONNTRACK_DIRECTION;
 
528
                        info->invert_flags &= ~XT_CONNTRACK_DIRECTION;
 
529
                } else if (strcasecmp(optarg, "REPLY") == 0) {
 
530
                        info->match_flags  |= XT_CONNTRACK_DIRECTION;
 
531
                        info->invert_flags |= XT_CONNTRACK_DIRECTION;
 
532
                } else {
 
533
                        param_act(P_BAD_VALUE, "conntrack", "--ctdir", optarg);
 
534
                }
 
535
                break;
 
536
 
 
537
        default:
 
538
                return false;
 
539
        }
 
540
 
 
541
        *flags = info->match_flags;
 
542
        return true;
 
543
}
 
544
 
 
545
static int
 
546
conntrack_mt4_parse(int c, char **argv, int invert, unsigned int *flags,
 
547
                    const void *entry, struct xt_entry_match **match)
 
548
{
 
549
        struct xt_conntrack_mtinfo1 *info = (void *)(*match)->data;
 
550
        struct in_addr *addr = NULL;
 
551
        unsigned int naddrs = 0;
 
552
 
 
553
        switch (c) {
 
554
        case '3': /* --ctorigsrc */
 
555
                ipparse_hostnetworkmask(optarg, &addr, &info->origsrc_mask.in,
 
556
                                        &naddrs);
 
557
                if (naddrs > 1)
 
558
                        exit_error(PARAMETER_PROBLEM,
 
559
                                   "multiple IP addresses not allowed");
 
560
                if (naddrs == 1)
 
561
                        memcpy(&info->origsrc_addr.in, addr, sizeof(*addr));
 
562
                info->match_flags |= XT_CONNTRACK_ORIGSRC;
 
563
                if (invert)
 
564
                        info->invert_flags |= XT_CONNTRACK_ORIGSRC;
 
565
                break;
 
566
 
 
567
        case '4': /* --ctorigdst */
 
568
                ipparse_hostnetworkmask(optarg, &addr, &info->origdst_mask.in,
 
569
                                        &naddrs);
 
570
                if (naddrs > 1)
 
571
                        exit_error(PARAMETER_PROBLEM,
 
572
                                   "multiple IP addresses not allowed");
 
573
                if (naddrs == 1)
 
574
                        memcpy(&info->origdst_addr.in, addr, sizeof(*addr));
 
575
                info->match_flags |= XT_CONNTRACK_ORIGDST;
 
576
                if (invert)
 
577
                        info->invert_flags |= XT_CONNTRACK_ORIGDST;
 
578
                break;
 
579
 
 
580
        case '5': /* --ctreplsrc */
 
581
                ipparse_hostnetworkmask(optarg, &addr, &info->replsrc_mask.in,
 
582
                                        &naddrs);
 
583
                if (naddrs > 1)
 
584
                        exit_error(PARAMETER_PROBLEM,
 
585
                                   "multiple IP addresses not allowed");
 
586
                if (naddrs == 1)
 
587
                        memcpy(&info->replsrc_addr.in, addr, sizeof(*addr));
 
588
                info->match_flags |= XT_CONNTRACK_REPLSRC;
 
589
                if (invert)
 
590
                        info->invert_flags |= XT_CONNTRACK_REPLSRC;
 
591
                break;
 
592
 
 
593
        case '6': /* --ctrepldst */
 
594
                ipparse_hostnetworkmask(optarg, &addr, &info->repldst_mask.in,
 
595
                                        &naddrs);
 
596
                if (naddrs > 1)
 
597
                        exit_error(PARAMETER_PROBLEM,
 
598
                                   "multiple IP addresses not allowed");
 
599
                if (naddrs == 1)
 
600
                        memcpy(&info->repldst_addr.in, addr, sizeof(*addr));
 
601
                info->match_flags |= XT_CONNTRACK_REPLDST;
 
602
                if (invert)
 
603
                        info->invert_flags |= XT_CONNTRACK_REPLDST;
 
604
                break;
 
605
 
 
606
 
 
607
        default:
 
608
                return conntrack_mt_parse(c, argv, invert, flags, match);
 
609
        }
 
610
 
 
611
        *flags = info->match_flags;
 
612
        return true;
 
613
}
 
614
 
 
615
static int
 
616
conntrack_mt6_parse(int c, char **argv, int invert, unsigned int *flags,
 
617
                    const void *entry, struct xt_entry_match **match)
 
618
{
 
619
        struct xt_conntrack_mtinfo1 *info = (void *)(*match)->data;
 
620
        struct in6_addr *addr = NULL;
 
621
        unsigned int naddrs = 0;
 
622
 
 
623
        switch (c) {
 
624
        case '3': /* --ctorigsrc */
 
625
                ip6parse_hostnetworkmask(optarg, &addr,
 
626
                                         &info->origsrc_mask.in6, &naddrs);
 
627
                if (naddrs > 1)
 
628
                        exit_error(PARAMETER_PROBLEM,
 
629
                                   "multiple IP addresses not allowed");
 
630
                if (naddrs == 1)
 
631
                        memcpy(&info->origsrc_addr.in6, addr, sizeof(*addr));
 
632
                info->match_flags |= XT_CONNTRACK_ORIGSRC;
 
633
                if (invert)
 
634
                        info->invert_flags |= XT_CONNTRACK_ORIGSRC;
 
635
                break;
 
636
 
 
637
        case '4': /* --ctorigdst */
 
638
                ip6parse_hostnetworkmask(optarg, &addr,
 
639
                                         &info->origdst_mask.in6, &naddrs);
 
640
                if (naddrs > 1)
 
641
                        exit_error(PARAMETER_PROBLEM,
 
642
                                   "multiple IP addresses not allowed");
 
643
                if (naddrs == 1)
 
644
                        memcpy(&info->origdst_addr.in, addr, sizeof(*addr));
 
645
                info->match_flags |= XT_CONNTRACK_ORIGDST;
 
646
                if (invert)
 
647
                        info->invert_flags |= XT_CONNTRACK_ORIGDST;
 
648
                break;
 
649
 
 
650
        case '5': /* --ctreplsrc */
 
651
                ip6parse_hostnetworkmask(optarg, &addr,
 
652
                                         &info->replsrc_mask.in6, &naddrs);
 
653
                if (naddrs > 1)
 
654
                        exit_error(PARAMETER_PROBLEM,
 
655
                                   "multiple IP addresses not allowed");
 
656
                if (naddrs == 1)
 
657
                        memcpy(&info->replsrc_addr.in, addr, sizeof(*addr));
 
658
                info->match_flags |= XT_CONNTRACK_REPLSRC;
 
659
                if (invert)
 
660
                        info->invert_flags |= XT_CONNTRACK_REPLSRC;
 
661
                break;
 
662
 
 
663
        case '6': /* --ctrepldst */
 
664
                ip6parse_hostnetworkmask(optarg, &addr,
 
665
                                         &info->repldst_mask.in6, &naddrs);
 
666
                if (naddrs > 1)
 
667
                        exit_error(PARAMETER_PROBLEM,
 
668
                                   "multiple IP addresses not allowed");
 
669
                if (naddrs == 1)
 
670
                        memcpy(&info->repldst_addr.in, addr, sizeof(*addr));
 
671
                info->match_flags |= XT_CONNTRACK_REPLDST;
 
672
                if (invert)
 
673
                        info->invert_flags |= XT_CONNTRACK_REPLDST;
 
674
                break;
 
675
 
 
676
 
 
677
        default:
 
678
                return conntrack_mt_parse(c, argv, invert, flags, match);
 
679
        }
 
680
 
 
681
        *flags = info->match_flags;
 
682
        return true;
 
683
}
 
684
 
 
685
static void conntrack_mt_check(unsigned int flags)
 
686
{
 
687
        if (flags == 0)
 
688
                exit_error(PARAMETER_PROBLEM, "conntrack: At least one option "
 
689
                           "is required");
 
690
}
 
691
 
 
692
static void
 
693
print_state(unsigned int statemask)
 
694
{
 
695
        const char *sep = "";
 
696
 
 
697
        if (statemask & XT_CONNTRACK_STATE_INVALID) {
 
698
                printf("%sINVALID", sep);
 
699
                sep = ",";
 
700
        }
 
701
        if (statemask & XT_CONNTRACK_STATE_BIT(IP_CT_NEW)) {
 
702
                printf("%sNEW", sep);
 
703
                sep = ",";
 
704
        }
 
705
        if (statemask & XT_CONNTRACK_STATE_BIT(IP_CT_RELATED)) {
 
706
                printf("%sRELATED", sep);
 
707
                sep = ",";
 
708
        }
 
709
        if (statemask & XT_CONNTRACK_STATE_BIT(IP_CT_ESTABLISHED)) {
 
710
                printf("%sESTABLISHED", sep);
 
711
                sep = ",";
 
712
        }
 
713
        if (statemask & XT_CONNTRACK_STATE_UNTRACKED) {
 
714
                printf("%sUNTRACKED", sep);
 
715
                sep = ",";
 
716
        }
 
717
        if (statemask & XT_CONNTRACK_STATE_SNAT) {
 
718
                printf("%sSNAT", sep);
 
719
                sep = ",";
 
720
        }
 
721
        if (statemask & XT_CONNTRACK_STATE_DNAT) {
 
722
                printf("%sDNAT", sep);
 
723
                sep = ",";
 
724
        }
 
725
        printf(" ");
 
726
}
 
727
 
 
728
static void
 
729
print_status(unsigned int statusmask)
 
730
{
 
731
        const char *sep = "";
 
732
 
 
733
        if (statusmask & IPS_EXPECTED) {
 
734
                printf("%sEXPECTED", sep);
 
735
                sep = ",";
 
736
        }
 
737
        if (statusmask & IPS_SEEN_REPLY) {
 
738
                printf("%sSEEN_REPLY", sep);
 
739
                sep = ",";
 
740
        }
 
741
        if (statusmask & IPS_ASSURED) {
 
742
                printf("%sASSURED", sep);
 
743
                sep = ",";
 
744
        }
 
745
        if (statusmask & IPS_CONFIRMED) {
 
746
                printf("%sCONFIRMED", sep);
 
747
                sep = ",";
 
748
        }
 
749
        if (statusmask == 0)
 
750
                printf("%sNONE", sep);
 
751
        printf(" ");
 
752
}
 
753
 
 
754
static void
 
755
conntrack_dump_addr(const union nf_inet_addr *addr,
 
756
                    const union nf_inet_addr *mask,
 
757
                    unsigned int family, bool numeric)
 
758
{
 
759
        if (family == AF_INET) {
 
760
                if (!numeric && addr->ip == 0) {
 
761
                        printf("anywhere ");
 
762
                        return;
 
763
                }
 
764
                printf("%s ", ipaddr_to_anyname(&addr->in));
 
765
        } else if (family == AF_INET6) {
 
766
                if (!numeric && addr->ip6[0] == 0 && addr->ip6[1] == 0 &&
 
767
                    addr->ip6[2] == 0 && addr->ip6[3] == 0) {
 
768
                        printf("anywhere ");
 
769
                        return;
 
770
                }
 
771
                printf("%s ", ip6addr_to_anyname(&addr->in6));
 
772
        }
 
773
}
 
774
 
 
775
static void
 
776
print_addr(struct in_addr *addr, struct in_addr *mask, int inv, int numeric)
 
777
{
 
778
        char buf[BUFSIZ];
 
779
 
 
780
        if (inv)
 
781
                printf("! ");
 
782
 
 
783
        if (mask->s_addr == 0L && !numeric)
 
784
                printf("%s ", "anywhere");
 
785
        else {
 
786
                if (numeric)
 
787
                        sprintf(buf, "%s", ipaddr_to_numeric(addr));
 
788
                else
 
789
                        sprintf(buf, "%s", ipaddr_to_anyname(addr));
 
790
                strcat(buf, ipmask_to_numeric(mask));
 
791
                printf("%s ", buf);
 
792
        }
 
793
}
 
794
 
 
795
/* Saves the matchinfo in parsable form to stdout. */
 
796
static void
 
797
matchinfo_print(const void *ip, const struct xt_entry_match *match, int numeric, const char *optpfx)
 
798
{
 
799
        struct xt_conntrack_info *sinfo = (void *)match->data;
 
800
 
 
801
        if(sinfo->flags & XT_CONNTRACK_STATE) {
 
802
                if (sinfo->invflags & XT_CONNTRACK_STATE)
 
803
                        printf("! ");
 
804
                printf("%sctstate ", optpfx);
 
805
                print_state(sinfo->statemask);
 
806
        }
 
807
 
 
808
        if(sinfo->flags & XT_CONNTRACK_PROTO) {
 
809
                if (sinfo->invflags & XT_CONNTRACK_PROTO)
 
810
                        printf("! ");
 
811
                printf("%sctproto ", optpfx);
 
812
                printf("%u ", sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum);
 
813
        }
 
814
 
 
815
        if(sinfo->flags & XT_CONNTRACK_ORIGSRC) {
 
816
                if (sinfo->invflags & XT_CONNTRACK_ORIGSRC)
 
817
                        printf("! ");
 
818
                printf("%sctorigsrc ", optpfx);
 
819
 
 
820
                print_addr(
 
821
                    (struct in_addr *)&sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip,
 
822
                    &sinfo->sipmsk[IP_CT_DIR_ORIGINAL],
 
823
                    false,
 
824
                    numeric);
 
825
        }
 
826
 
 
827
        if(sinfo->flags & XT_CONNTRACK_ORIGDST) {
 
828
                if (sinfo->invflags & XT_CONNTRACK_ORIGDST)
 
829
                        printf("! ");
 
830
                printf("%sctorigdst ", optpfx);
 
831
 
 
832
                print_addr(
 
833
                    (struct in_addr *)&sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip,
 
834
                    &sinfo->dipmsk[IP_CT_DIR_ORIGINAL],
 
835
                    false,
 
836
                    numeric);
 
837
        }
 
838
 
 
839
        if(sinfo->flags & XT_CONNTRACK_REPLSRC) {
 
840
                if (sinfo->invflags & XT_CONNTRACK_REPLSRC)
 
841
                        printf("! ");
 
842
                printf("%sctreplsrc ", optpfx);
 
843
 
 
844
                print_addr(
 
845
                    (struct in_addr *)&sinfo->tuple[IP_CT_DIR_REPLY].src.ip,
 
846
                    &sinfo->sipmsk[IP_CT_DIR_REPLY],
 
847
                    false,
 
848
                    numeric);
 
849
        }
 
850
 
 
851
        if(sinfo->flags & XT_CONNTRACK_REPLDST) {
 
852
                if (sinfo->invflags & XT_CONNTRACK_REPLDST)
 
853
                        printf("! ");
 
854
                printf("%sctrepldst ", optpfx);
 
855
 
 
856
                print_addr(
 
857
                    (struct in_addr *)&sinfo->tuple[IP_CT_DIR_REPLY].dst.ip,
 
858
                    &sinfo->dipmsk[IP_CT_DIR_REPLY],
 
859
                    false,
 
860
                    numeric);
 
861
        }
 
862
 
 
863
        if(sinfo->flags & XT_CONNTRACK_STATUS) {
 
864
                if (sinfo->invflags & XT_CONNTRACK_STATUS)
 
865
                        printf("! ");
 
866
                printf("%sctstatus ", optpfx);
 
867
                print_status(sinfo->statusmask);
 
868
        }
 
869
 
 
870
        if(sinfo->flags & XT_CONNTRACK_EXPIRES) {
 
871
                if (sinfo->invflags & XT_CONNTRACK_EXPIRES)
 
872
                        printf("! ");
 
873
                printf("%sctexpire ", optpfx);
 
874
 
 
875
                if (sinfo->expires_max == sinfo->expires_min)
 
876
                        printf("%lu ", sinfo->expires_min);
 
877
                else
 
878
                        printf("%lu:%lu ", sinfo->expires_min, sinfo->expires_max);
 
879
        }
 
880
}
 
881
 
 
882
static void
 
883
conntrack_dump(const struct xt_conntrack_mtinfo1 *info, const char *prefix,
 
884
               unsigned int family, bool numeric)
 
885
{
 
886
        if (info->match_flags & XT_CONNTRACK_STATE) {
 
887
                if (info->invert_flags & XT_CONNTRACK_STATE)
 
888
                        printf("! ");
 
889
                printf("%sctstate ", prefix);
 
890
                print_state(info->state_mask);
 
891
        }
 
892
 
 
893
        if (info->match_flags & XT_CONNTRACK_PROTO) {
 
894
                if (info->invert_flags & XT_CONNTRACK_PROTO)
 
895
                        printf("! ");
 
896
                printf("%sctproto %u ", prefix, info->l4proto);
 
897
        }
 
898
 
 
899
        if (info->match_flags & XT_CONNTRACK_ORIGSRC) {
 
900
                if (info->invert_flags & XT_CONNTRACK_PROTO)
 
901
                        printf("! ");
 
902
                printf("%sctorigsrc ", prefix);
 
903
                conntrack_dump_addr(&info->origsrc_addr, &info->origsrc_mask,
 
904
                                    family, numeric);
 
905
        }
 
906
 
 
907
        if (info->match_flags & XT_CONNTRACK_ORIGDST) {
 
908
                if (info->invert_flags & XT_CONNTRACK_PROTO)
 
909
                        printf("! ");
 
910
                printf("%sctorigdst ", prefix);
 
911
                conntrack_dump_addr(&info->origdst_addr, &info->origdst_mask,
 
912
                                    family, numeric);
 
913
        }
 
914
 
 
915
        if (info->match_flags & XT_CONNTRACK_REPLSRC) {
 
916
                if (info->invert_flags & XT_CONNTRACK_PROTO)
 
917
                        printf("! ");
 
918
                printf("%sctreplsrc ", prefix);
 
919
                conntrack_dump_addr(&info->replsrc_addr, &info->replsrc_mask,
 
920
                                    family, numeric);
 
921
        }
 
922
 
 
923
        if (info->match_flags & XT_CONNTRACK_REPLDST) {
 
924
                if (info->invert_flags & XT_CONNTRACK_PROTO)
 
925
                        printf("! ");
 
926
                printf("%sctrepldst ", prefix);
 
927
                conntrack_dump_addr(&info->repldst_addr, &info->repldst_mask,
 
928
                                    family, numeric);
 
929
        }
 
930
 
 
931
        if (info->match_flags & XT_CONNTRACK_ORIGSRC_PORT) {
 
932
                if (info->invert_flags & XT_CONNTRACK_ORIGSRC_PORT)
 
933
                        printf("! ");
 
934
                printf("%sctorigsrcport %u ", prefix,
 
935
                       ntohs(info->origsrc_port));
 
936
        }
 
937
 
 
938
        if (info->match_flags & XT_CONNTRACK_ORIGDST_PORT) {
 
939
                if (info->invert_flags & XT_CONNTRACK_ORIGDST_PORT)
 
940
                        printf("! ");
 
941
                printf("%sctorigdstport %u ", prefix,
 
942
                       ntohs(info->origdst_port));
 
943
        }
 
944
 
 
945
        if (info->match_flags & XT_CONNTRACK_REPLSRC_PORT) {
 
946
                if (info->invert_flags & XT_CONNTRACK_REPLSRC_PORT)
 
947
                        printf("! ");
 
948
                printf("%sctreplsrcport %u ", prefix,
 
949
                       ntohs(info->replsrc_port));
 
950
        }
 
951
 
 
952
        if (info->match_flags & XT_CONNTRACK_REPLDST_PORT) {
 
953
                if (info->invert_flags & XT_CONNTRACK_REPLDST_PORT)
 
954
                        printf("! ");
 
955
                printf("%sctrepldstport %u ", prefix,
 
956
                       ntohs(info->repldst_port));
 
957
        }
 
958
 
 
959
        if (info->match_flags & XT_CONNTRACK_STATUS) {
 
960
                if (info->invert_flags & XT_CONNTRACK_STATUS)
 
961
                        printf("! ");
 
962
                printf("%sctstatus ", prefix);
 
963
                print_status(info->status_mask);
 
964
        }
 
965
 
 
966
        if (info->match_flags & XT_CONNTRACK_EXPIRES) {
 
967
                if (info->invert_flags & XT_CONNTRACK_EXPIRES)
 
968
                        printf("! ");
 
969
                printf("%sctexpire ", prefix);
 
970
 
 
971
                if (info->expires_max == info->expires_min)
 
972
                        printf("%u ", (unsigned int)info->expires_min);
 
973
                else
 
974
                        printf("%u:%u ", (unsigned int)info->expires_min,
 
975
                               (unsigned int)info->expires_max);
 
976
        }
 
977
}
 
978
 
 
979
/* Prints out the matchinfo. */
 
980
static void conntrack_print(const void *ip, const struct xt_entry_match *match,
 
981
                            int numeric)
 
982
{
 
983
        matchinfo_print(ip, match, numeric, "");
 
984
}
 
985
 
 
986
static void
 
987
conntrack_mt_print(const void *ip, const struct xt_entry_match *match,
 
988
                   int numeric)
 
989
{
 
990
        conntrack_dump((const void *)match->data, "", AF_INET, numeric);
 
991
}
 
992
 
 
993
static void
 
994
conntrack_mt6_print(const void *ip, const struct xt_entry_match *match,
 
995
                    int numeric)
 
996
{
 
997
        conntrack_dump((const void *)match->data, "", AF_INET6, numeric);
 
998
}
 
999
 
 
1000
/* Saves the matchinfo in parsable form to stdout. */
 
1001
static void conntrack_save(const void *ip, const struct xt_entry_match *match)
 
1002
{
 
1003
        matchinfo_print(ip, match, 1, "--");
 
1004
}
 
1005
 
 
1006
static void conntrack_mt_save(const void *ip,
 
1007
                              const struct xt_entry_match *match)
 
1008
{
 
1009
        conntrack_dump((const void *)match->data, "--", AF_INET, true);
 
1010
}
 
1011
 
 
1012
static void conntrack_mt6_save(const void *ip,
 
1013
                               const struct xt_entry_match *match)
 
1014
{
 
1015
        conntrack_dump((const void *)match->data, "--", AF_INET6, true);
 
1016
}
 
1017
 
 
1018
static struct xtables_match conntrack_match = {
 
1019
        .version       = XTABLES_VERSION,
 
1020
        .name          = "conntrack",
 
1021
        .revision      = 0,
 
1022
        .family        = AF_INET,
 
1023
        .size          = XT_ALIGN(sizeof(struct xt_conntrack_info)),
 
1024
        .userspacesize = XT_ALIGN(sizeof(struct xt_conntrack_info)),
 
1025
        .help          = conntrack_mt_help,
 
1026
        .parse         = conntrack_parse,
 
1027
        .final_check   = conntrack_mt_check,
 
1028
        .print         = conntrack_print,
 
1029
        .save          = conntrack_save,
 
1030
        .extra_opts    = conntrack_mt_opts_v0,
 
1031
};
 
1032
 
 
1033
static struct xtables_match conntrack_mt_reg = {
 
1034
        .version       = XTABLES_VERSION,
 
1035
        .name          = "conntrack",
 
1036
        .revision      = 1,
 
1037
        .family        = AF_INET,
 
1038
        .size          = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo1)),
 
1039
        .userspacesize = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo1)),
 
1040
        .help          = conntrack_mt_help,
 
1041
        .parse         = conntrack_mt4_parse,
 
1042
        .final_check   = conntrack_mt_check,
 
1043
        .print         = conntrack_mt_print,
 
1044
        .save          = conntrack_mt_save,
 
1045
        .extra_opts    = conntrack_mt_opts,
 
1046
};
 
1047
 
 
1048
static struct xtables_match conntrack_mt6_reg = {
 
1049
        .version       = XTABLES_VERSION,
 
1050
        .name          = "conntrack",
 
1051
        .revision      = 1,
 
1052
        .family        = AF_INET6,
 
1053
        .size          = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo1)),
 
1054
        .userspacesize = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo1)),
 
1055
        .help          = conntrack_mt_help,
 
1056
        .parse         = conntrack_mt6_parse,
 
1057
        .final_check   = conntrack_mt_check,
 
1058
        .print         = conntrack_mt6_print,
 
1059
        .save          = conntrack_mt6_save,
 
1060
        .extra_opts    = conntrack_mt_opts,
 
1061
};
 
1062
 
 
1063
void _init(void)
 
1064
{
 
1065
        xtables_register_match(&conntrack_match);
 
1066
        xtables_register_match(&conntrack_mt_reg);
 
1067
        xtables_register_match(&conntrack_mt6_reg);
 
1068
}