~ubuntu-branches/ubuntu/trusty/conntrack/trusty-proposed

« back to all changes in this revision

Viewing changes to src/conntrack.c

  • Committer: Bazaar Package Importer
  • Author(s): Alexander Wirt, Max Kellermann
  • Date: 2008-04-14 23:09:22 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20080414230922-9xoi1gl38tc8lyng
Tags: 1:0.9.6-4
[ Max Kellermann ]
fix compilation on SPARC (printf argument mismatch)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 * (C) 2005 by Pablo Neira Ayuso <pablo@netfilter.org>
 
2
 * (C) 2005-2007 by Pablo Neira Ayuso <pablo@netfilter.org>
3
3
 *
4
4
 *      This program is free software; you can redistribute it and/or modify
5
5
 *      it under the terms of the GNU General Public License as published by
29
29
 *      Add support for expect creation
30
30
 * 2005-09-24 Harald Welte <laforge@netfilter.org>:
31
31
 *      Remove remaints of "-A"
 
32
 * 2007-04-22 Pablo Neira Ayuso <pablo@netfilter.org>:
 
33
 *      Ported to the new libnetfilter_conntrack API
32
34
 *
33
35
 */
 
36
 
 
37
#include "conntrack.h"
 
38
 
34
39
#include <stdio.h>
35
 
#include <sys/wait.h>
36
 
#include <stdlib.h>
37
40
#include <getopt.h>
38
41
#include <stdlib.h>
39
42
#include <stdarg.h>
41
44
#include <unistd.h>
42
45
#include <netinet/in.h>
43
46
#include <sys/types.h>
44
 
#include <sys/stat.h>
45
47
#include <sys/socket.h>
 
48
#include <sys/time.h>
 
49
#include <time.h>
46
50
#ifdef HAVE_ARPA_INET_H
47
51
#include <arpa/inet.h>
48
52
#endif
49
 
#include <fcntl.h>
50
 
#include <dlfcn.h>
 
53
#include <signal.h>
51
54
#include <string.h>
52
 
#include "linux_list.h"
53
 
#include "conntrack.h"
54
55
#include <libnetfilter_conntrack/libnetfilter_conntrack.h>
55
 
#include <libnetfilter_conntrack/libnetfilter_conntrack_ipv4.h>
56
 
#include <libnetfilter_conntrack/libnetfilter_conntrack_ipv6.h>
57
56
 
58
57
static const char cmdflags[NUMBER_OF_CMD]
59
58
= {'L','I','U','D','G','F','E','V','h','L','I','D','G','F','E'};
61
60
static const char cmd_need_param[NUMBER_OF_CMD]
62
61
= { 2,  0,  0,  0,  0,  2,  2,  2,  2,  2,  0,  0,  0,  2,  2 };
63
62
 
64
 
static const char optflags[NUMBER_OF_OPT]
65
 
= {'s','d','r','q','p','t','u','z','e','[',']','{','}','a','m','i','f'};
 
63
static const char *optflags[NUMBER_OF_OPT] = {
 
64
"src","dst","reply-src","reply-dst","protonum","timeout","status","zero",
 
65
"event-mask","tuple-src","tuple-dst","mask-src","mask-dst","nat-range","mark",
 
66
"id","family","src-nat","dst-nat","output","secmark"};
66
67
 
67
68
static struct option original_opts[] = {
68
69
        {"dump", 2, 0, 'L'},
75
76
        {"version", 0, 0, 'V'},
76
77
        {"help", 0, 0, 'h'},
77
78
        {"orig-src", 1, 0, 's'},
 
79
        {"src", 1, 0, 's'},
78
80
        {"orig-dst", 1, 0, 'd'},
 
81
        {"dst", 1, 0, 'd'},
79
82
        {"reply-src", 1, 0, 'r'},
80
83
        {"reply-dst", 1, 0, 'q'},
81
84
        {"protonum", 1, 0, 'p'},
87
90
        {"tuple-dst", 1, 0, ']'},
88
91
        {"mask-src", 1, 0, '{'},
89
92
        {"mask-dst", 1, 0, '}'},
90
 
        {"nat-range", 1, 0, 'a'},
 
93
        {"nat-range", 1, 0, 'a'},       /* deprecated */
91
94
        {"mark", 1, 0, 'm'},
92
 
        {"id", 2, 0, 'i'},
 
95
        {"secmark", 1, 0, 'c'},
 
96
        {"id", 2, 0, 'i'},              /* deprecated */
93
97
        {"family", 1, 0, 'f'},
 
98
        {"src-nat", 2, 0, 'n'},
 
99
        {"dst-nat", 2, 0, 'g'},
 
100
        {"output", 1, 0, 'o'},
94
101
        {0, 0, 0, 0}
95
102
};
96
103
 
112
119
static char commands_v_options[NUMBER_OF_CMD][NUMBER_OF_OPT] =
113
120
/* Well, it's better than "Re: Linux vs FreeBSD" */
114
121
{
115
 
          /*   s d r q p t u z e x y k l a m i f*/
116
 
/*CT_LIST*/   {2,2,2,2,2,0,0,2,0,0,0,0,0,0,2,2,2},
117
 
/*CT_CREATE*/ {2,2,2,2,1,1,1,0,0,0,0,0,0,2,2,0,0},
118
 
/*CT_UPDATE*/ {2,2,2,2,1,2,2,0,0,0,0,0,0,0,2,2,0},
119
 
/*CT_DELETE*/ {2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,2,0},
120
 
/*CT_GET*/    {2,2,2,2,1,0,0,0,0,0,0,0,0,0,0,2,0},
121
 
/*CT_FLUSH*/  {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
122
 
/*CT_EVENT*/  {2,2,2,2,2,0,0,0,2,0,0,0,0,0,2,0,0},
123
 
/*VERSION*/   {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
124
 
/*HELP*/      {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
125
 
/*EXP_LIST*/  {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2},
126
 
/*EXP_CREATE*/{1,1,2,2,1,1,2,0,0,1,1,1,1,0,0,0,0},
127
 
/*EXP_DELETE*/{1,1,2,2,1,0,0,0,0,0,0,0,0,0,0,0,0},
128
 
/*EXP_GET*/   {1,1,2,2,1,0,0,0,0,0,0,0,0,0,0,0,0},
129
 
/*EXP_FLUSH*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
130
 
/*EXP_EVENT*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
 
122
          /*   s d r q p t u z e [ ] { } a m i f n g o c */
 
123
/*CT_LIST*/   {2,2,2,2,2,0,0,2,0,0,0,0,0,0,2,2,2,2,2,2,2},
 
124
/*CT_CREATE*/ {2,2,2,2,1,1,1,0,0,0,0,0,0,2,2,0,0,2,2,0,2},
 
125
/*CT_UPDATE*/ {2,2,2,2,1,2,2,0,0,0,0,0,0,0,2,2,0,0,0,0,2},
 
126
/*CT_DELETE*/ {2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0},
 
127
/*CT_GET*/    {2,2,2,2,1,0,0,0,0,0,0,0,0,0,0,2,0,0,0,2,0},
 
128
/*CT_FLUSH*/  {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
 
129
/*CT_EVENT*/  {2,2,2,2,2,0,0,0,2,0,0,0,0,0,2,0,0,2,2,2,2},
 
130
/*VERSION*/   {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
 
131
/*HELP*/      {0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
 
132
/*EXP_LIST*/  {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,0,0,0,0},
 
133
/*EXP_CREATE*/{1,1,2,2,1,1,2,0,0,1,1,1,1,0,0,0,0,0,0,0,0},
 
134
/*EXP_DELETE*/{1,1,2,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
 
135
/*EXP_GET*/   {1,1,2,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
 
136
/*EXP_FLUSH*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
 
137
/*EXP_EVENT*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
131
138
};
132
139
 
133
 
static char *lib_dir = CONNTRACK_LIB_DIR;
134
 
 
135
140
static LIST_HEAD(proto_list);
136
141
 
 
142
static unsigned int options;
 
143
 
 
144
#define CT_COMPARISON (CT_OPT_PROTO | CT_OPT_ORIG | CT_OPT_REPL | CT_OPT_MARK |\
 
145
                       CT_OPT_SECMARK)
 
146
 
137
147
void register_proto(struct ctproto_handler *h)
138
148
{
139
149
        if (strcmp(h->version, VERSION) != 0) {
146
156
 
147
157
static struct ctproto_handler *findproto(char *name)
148
158
{
149
 
        struct list_head *i;
150
 
        struct ctproto_handler *cur = NULL, *handler = NULL;
 
159
        struct ctproto_handler *cur;
151
160
 
152
161
        if (!name) 
153
 
                return handler;
154
 
 
155
 
        lib_dir = getenv("CONNTRACK_LIB_DIR");
156
 
        if (!lib_dir)
157
 
                lib_dir = CONNTRACK_LIB_DIR;
158
 
 
159
 
        list_for_each(i, &proto_list) {
160
 
                cur = (struct ctproto_handler *) i;
161
 
                if (strcmp(cur->name, name) == 0) {
162
 
                        handler = cur;
163
 
                        break;
164
 
                }
165
 
        }
166
 
 
167
 
        if (!handler) {
168
 
                char path[sizeof("ct_proto_.so")
169
 
                         + strlen(name) + strlen(lib_dir)];
170
 
                sprintf(path, "%s/ct_proto_%s.so", lib_dir, name);
171
 
                if (dlopen(path, RTLD_NOW))
172
 
                        handler = findproto(name);
173
 
                else
174
 
                        fprintf(stderr, "%s\n", dlerror());
175
 
        }
176
 
 
177
 
        return handler;
 
162
                return NULL;
 
163
 
 
164
        list_for_each_entry(cur, &proto_list, head) {
 
165
                if (strcmp(cur->name, name) == 0)
 
166
                        return cur;
 
167
        }
 
168
 
 
169
        return NULL;
178
170
}
179
171
 
180
 
enum exittype {
181
 
        OTHER_PROBLEM = 1,
182
 
        PARAMETER_PROBLEM,
183
 
        VERSION_PROBLEM
184
 
};
185
 
 
186
 
void extension_help(struct ctproto_handler *h)
 
172
static void
 
173
extension_help(struct ctproto_handler *h)
187
174
{
188
175
        fprintf(stdout, "\n");
189
176
        fprintf(stdout, "Proto `%s' help:\n", h->name);
190
177
        h->help();
191
178
}
192
179
 
193
 
void
 
180
static void __attribute__((noreturn))
194
181
exit_tryhelp(int status)
195
182
{
196
183
        fprintf(stderr, "Try `%s -h' or '%s --help' for more information.\n",
198
185
        exit(status);
199
186
}
200
187
 
201
 
static void
202
 
exit_error(enum exittype status, char *msg, ...)
 
188
void __attribute__((noreturn))
 
189
exit_error(enum exittype status, const char *msg, ...)
203
190
{
204
191
        va_list args;
205
192
 
214
201
        fprintf(stderr,"%s v%s: ", PROGNAME, VERSION);
215
202
        vfprintf(stderr, msg, args);
216
203
        va_end(args);
217
 
        fprintf(stderr, "\n");
218
204
        if (status == PARAMETER_PROBLEM)
219
205
                exit_tryhelp(status);
220
206
        exit(status);
221
207
}
222
208
 
223
209
static void
224
 
generic_cmd_check(int command, int options)
225
 
{
226
 
        int i;
227
 
        
228
 
        for (i = 0; i < NUMBER_OF_CMD; i++) {
229
 
                if (!(command & (1<<i)))
230
 
                        continue;
231
 
 
232
 
                if (cmd_need_param[i] == 0 && !options)
233
 
                        exit_error(PARAMETER_PROBLEM,
234
 
                                   "You need to supply parameters to `-%c'\n",
235
 
                                   cmdflags[i]);
236
 
        }
237
 
}
238
 
 
239
 
static void
240
 
generic_opt_check(int command, int options)
241
 
{
242
 
        int i, j, legal = 0;
243
 
 
244
 
        /* Check that commands are valid with options.  Complicated by the
245
 
         * fact that if an option is legal with *any* command given, it is
246
 
         * legal overall (ie. -z and -l).
247
 
         */
248
 
        for (i = 0; i < NUMBER_OF_OPT; i++) {
249
 
                legal = 0; /* -1 => illegal, 1 => legal, 0 => undecided. */
250
 
 
251
 
                for (j = 0; j < NUMBER_OF_CMD; j++) {
252
 
                        if (!(command & (1<<j)))
253
 
                                continue;
254
 
 
255
 
                        if (!(options & (1<<i))) {
256
 
                                if (commands_v_options[j][i] == 1) 
257
 
                                        exit_error(PARAMETER_PROBLEM, 
258
 
                                                   "You need to supply the "
259
 
                                                   "`-%c' option for this "
260
 
                                                   "command\n", optflags[i]);
261
 
                        } else {
262
 
                                if (commands_v_options[j][i] != 0)
263
 
                                        legal = 1;
264
 
                                else if (legal == 0)
265
 
                                        legal = -1;
266
 
                        }
 
210
generic_cmd_check(int command, int local_options)
 
211
{
 
212
        if (cmd_need_param[command] == 0 && !local_options)
 
213
                exit_error(PARAMETER_PROBLEM,
 
214
                           "You need to supply parameters to `-%c'\n",
 
215
                           cmdflags[command]);
 
216
}
 
217
 
 
218
static int bit2cmd(int command)
 
219
{
 
220
        int i;
 
221
 
 
222
        for (i = 0; i < NUMBER_OF_CMD; i++)
 
223
                if (command & (1<<i))
 
224
                        break;
 
225
 
 
226
        return i;
 
227
}
 
228
 
 
229
void generic_opt_check(int local_options, 
 
230
                       int num_opts,
 
231
                       char *optset, 
 
232
                       const char *optflg[])
 
233
{
 
234
        int i;
 
235
 
 
236
        for (i = 0; i < num_opts; i++) {
 
237
                if (!(local_options & (1<<i))) {
 
238
                        if (optset[i] == 1)
 
239
                                exit_error(PARAMETER_PROBLEM, 
 
240
                                           "You need to supply the "
 
241
                                           "`--%s' option for this "
 
242
                                           "command\n", optflg[i]);
 
243
                } else {
 
244
                        if (optset[i] == 0)
 
245
                                exit_error(PARAMETER_PROBLEM, "Illegal "
 
246
                                           "option `--%s' with this "
 
247
                                           "command\n", optflg[i]);
267
248
                }
268
 
                if (legal == -1)
269
 
                        exit_error(PARAMETER_PROBLEM, "Illegal option `-%c' "
270
 
                                   "with this command\n", optflags[i]);
271
249
        }
272
250
}
273
251
 
285
263
        *option_offset = global_option_offset;
286
264
 
287
265
        merge = malloc(sizeof(struct option) * (num_new + num_old + 1));
 
266
        if (merge == NULL)
 
267
                return NULL;
 
268
 
288
269
        memcpy(merge, oldopts, num_old * sizeof(struct option));
289
270
        for (i = 0; i < num_new; i++) {
290
271
                merge[num_old + i] = newopts[i];
299
280
#define ENOTSUPP        524     /* Operation is not supported */
300
281
 
301
282
/* Translates errno numbers into more human-readable form than strerror. */
302
 
const char *
 
283
static const char *
303
284
err2str(int err, enum action command)
304
285
{
305
286
        unsigned int i;
308
289
                int err;
309
290
                const char *message;
310
291
        } table [] =
311
 
          { { CT_LIST, -ENOTSUPP, "function not implemented" },
312
 
            { 0xFFFF, -EINVAL, "invalid parameters" },
313
 
            { CT_CREATE, -EEXIST, "Such conntrack exists, try -U to update" },
314
 
            { CT_CREATE|CT_GET|CT_DELETE, -ENOENT, 
 
292
          { { CT_LIST, ENOTSUPP, "function not implemented" },
 
293
            { 0xFFFF, EINVAL, "invalid parameters" },
 
294
            { CT_CREATE, EEXIST, "Such conntrack exists, try -U to update" },
 
295
            { CT_CREATE|CT_GET|CT_DELETE, ENOENT, 
315
296
                    "such conntrack doesn't exist" },
316
 
            { CT_CREATE|CT_GET, -ENOMEM, "not enough memory" },
317
 
            { CT_GET, -EAFNOSUPPORT, "protocol not supported" },
318
 
            { CT_CREATE, -ETIME, "conntrack has expired" },
319
 
            { EXP_CREATE, -ENOENT, "master conntrack not found" },
320
 
            { EXP_CREATE, -EINVAL, "invalid parameters" },
321
 
            { ~0UL, -EPERM, "sorry, you must be root or get "
322
 
                            "CAP_NET_ADMIN capability to do this"}
 
297
            { CT_CREATE|CT_GET, ENOMEM, "not enough memory" },
 
298
            { CT_GET, EAFNOSUPPORT, "protocol not supported" },
 
299
            { CT_CREATE, ETIME, "conntrack has expired" },
 
300
            { EXP_CREATE, ENOENT, "master conntrack not found" },
 
301
            { EXP_CREATE, EINVAL, "invalid parameters" },
 
302
            { ~0UL, EPERM, "sorry, you must be root or get "
 
303
                           "CAP_NET_ADMIN capability to do this"}
323
304
          };
324
305
 
325
306
        for (i = 0; i < sizeof(table)/sizeof(struct table_struct); i++) {
332
313
 
333
314
#define PARSE_STATUS 0
334
315
#define PARSE_EVENT 1
335
 
#define PARSE_MAX 2
 
316
#define PARSE_OUTPUT 2
 
317
#define PARSE_MAX 3
336
318
 
337
319
static struct parse_parameter {
338
 
        char    *parameter[5];
 
320
        const char      *parameter[6];
339
321
        size_t  size;
340
 
        unsigned int value[5];
 
322
        unsigned int value[6];
341
323
} parse_array[PARSE_MAX] = {
342
 
        { {"ASSURED", "SEEN_REPLY", "UNSET", "SRC_NAT", "DST_NAT"}, 5,
343
 
          { IPS_ASSURED, IPS_SEEN_REPLY, 0, 
344
 
            IPS_SRC_NAT_DONE, IPS_DST_NAT_DONE} },
 
324
        { {"ASSURED", "SEEN_REPLY", "UNSET", "FIXED_TIMEOUT"}, 4,
 
325
          { IPS_ASSURED, IPS_SEEN_REPLY, 0, IPS_FIXED_TIMEOUT} },
345
326
        { {"ALL", "NEW", "UPDATES", "DESTROY"}, 4,
346
327
          {~0U, NF_NETLINK_CONNTRACK_NEW, NF_NETLINK_CONNTRACK_UPDATE, 
347
328
           NF_NETLINK_CONNTRACK_DESTROY} },
 
329
        { {"xml", "extended", "timestamp" }, 3, 
 
330
          { _O_XML, _O_EXT, _O_TMS },
 
331
        },
348
332
};
349
333
 
350
334
static int
351
 
do_parse_parameter(const char *str, size_t strlen, unsigned int *value, 
 
335
do_parse_parameter(const char *str, size_t str_length, unsigned int *value, 
352
336
                   int parse_type)
353
337
{
354
 
        int i, ret = 0;
 
338
        size_t i;
 
339
        int ret = 0;
355
340
        struct parse_parameter *p = &parse_array[parse_type];
356
 
        
 
341
 
 
342
        if (strncasecmp(str, "SRC_NAT", str_length) == 0) {
 
343
                printf("skipping SRC_NAT, use --src-nat instead\n");
 
344
                return 1;
 
345
        }
 
346
 
 
347
        if (strncasecmp(str, "DST_NAT", str_length) == 0) {
 
348
                printf("skipping DST_NAT, use --dst-nat instead\n");
 
349
                return 1;
 
350
        }
 
351
 
357
352
        for (i = 0; i < p->size; i++)
358
 
                if (strncasecmp(str, p->parameter[i], strlen) == 0) {
 
353
                if (strncasecmp(str, p->parameter[i], str_length) == 0) {
359
354
                        *value |= p->value[i];
360
355
                        ret = 1;
361
356
                        break;
389
384
        *cmd |= newcmd;
390
385
}
391
386
 
392
 
unsigned int check_type(int argc, char *argv[])
 
387
static unsigned int
 
388
check_type(int argc, char *argv[])
393
389
{
394
390
        char *table = NULL;
395
391
 
429
425
        unsigned int family;
430
426
};
431
427
 
432
 
int __parse_inetaddr(const char *cp, struct addr_parse *parse)
 
428
static int
 
429
parse_inetaddr(const char *cp, struct addr_parse *parse)
433
430
{
434
431
        if (inet_aton(cp, &parse->addr))
435
432
                return AF_INET;
441
438
        exit_error(PARAMETER_PROBLEM, "Invalid IP address `%s'.", cp);
442
439
}
443
440
 
444
 
int parse_inetaddr(const char *cp, union nfct_address *address)
 
441
union ct_address {
 
442
        uint32_t v4;
 
443
        uint32_t v6[4];
 
444
};
 
445
 
 
446
static int
 
447
parse_addr(const char *cp, union ct_address *address)
445
448
{
446
449
        struct addr_parse parse;
447
450
        int ret;
448
 
        
449
 
        if ((ret = __parse_inetaddr(cp, &parse)) == AF_INET)
 
451
 
 
452
        if ((ret = parse_inetaddr(cp, &parse)) == AF_INET)
450
453
                address->v4 = parse.addr.s_addr;
451
454
        else if (ret == AF_INET6)
452
455
                memcpy(address->v6, &parse.addr6, sizeof(parse.addr6));
456
459
 
457
460
/* Shamelessly stolen from libipt_DNAT ;). Ranges expected in network order. */
458
461
static void
459
 
nat_parse(char *arg, int portok, struct nfct_nat *range)
 
462
nat_parse(char *arg, int portok, struct nf_conntrack *obj, int type)
460
463
{
461
 
        char *colon, *dash, *error;
462
 
        struct addr_parse parse;
 
464
        char *colon, *error;
 
465
        union ct_address parse;
463
466
 
464
 
        memset(range, 0, sizeof(range));
465
467
        colon = strchr(arg, ':');
466
468
 
467
469
        if (colon) {
468
 
                int port;
 
470
                uint16_t port;
469
471
 
470
472
                if (!portok)
471
473
                        exit_error(PARAMETER_PROBLEM,
472
474
                                   "Need TCP or UDP with port specification");
473
475
 
474
 
                port = atoi(colon+1);
475
 
                if (port == 0 || port > 65535)
 
476
                port = (uint16_t)atoi(colon+1);
 
477
                if (port == 0)
476
478
                        exit_error(PARAMETER_PROBLEM,
477
479
                                   "Port `%s' not valid\n", colon+1);
478
480
 
479
481
                error = strchr(colon+1, ':');
480
482
                if (error)
481
483
                        exit_error(PARAMETER_PROBLEM,
482
 
                                   "Invalid port:port syntax - use dash\n");
483
 
 
484
 
                dash = strchr(colon, '-');
485
 
                if (!dash) {
486
 
                        range->l4min.tcp.port
487
 
                                = range->l4max.tcp.port
488
 
                                = htons(port);
489
 
                } else {
490
 
                        int maxport;
491
 
 
492
 
                        maxport = atoi(dash + 1);
493
 
                        if (maxport == 0 || maxport > 65535)
494
 
                                exit_error(PARAMETER_PROBLEM,
495
 
                                           "Port `%s' not valid\n", dash+1);
496
 
                        if (maxport < port)
497
 
                                /* People are stupid.  */
498
 
                                exit_error(PARAMETER_PROBLEM,
499
 
                                           "Port range `%s' funky\n", colon+1);
500
 
                        range->l4min.tcp.port = htons(port);
501
 
                        range->l4max.tcp.port = htons(maxport);
502
 
                }
503
 
                /* Starts with a colon? No IP info... */
504
 
                if (colon == arg)
505
 
                        return;
506
 
                *colon = '\0';
 
484
                                   "Invalid port:port syntax\n");
 
485
 
 
486
                if (type == CT_OPT_SRC_NAT)
 
487
                        nfct_set_attr_u16(obj, ATTR_SNAT_PORT, port);
 
488
                else if (type == CT_OPT_DST_NAT)
 
489
                        nfct_set_attr_u16(obj, ATTR_DNAT_PORT, port);
507
490
        }
508
491
 
509
 
        dash = strchr(arg, '-');
510
 
        if (colon && dash && dash > colon)
511
 
                dash = NULL;
512
 
 
513
 
        if (dash)
514
 
                *dash = '\0';
515
 
 
516
 
        if (__parse_inetaddr(arg, &parse) != AF_INET)
 
492
        if (parse_addr(arg, &parse) != AF_INET)
517
493
                return;
518
494
 
519
 
        range->min_ip = parse.addr.s_addr;
520
 
        if (dash) {
521
 
                if (__parse_inetaddr(dash+1, &parse) != AF_INET)
522
 
                        return;
523
 
                range->max_ip = parse.addr.s_addr;
524
 
        } else
525
 
                range->max_ip = parse.addr.s_addr;
 
495
        if (type == CT_OPT_SRC_NAT)
 
496
                nfct_set_attr_u32(obj, ATTR_SNAT_IPV4, parse.v4);
 
497
        else if (type == CT_OPT_DST_NAT)
 
498
                nfct_set_attr_u32(obj, ATTR_DNAT_IPV4, parse.v4);
526
499
}
527
500
 
528
 
static void event_sighandler(int s)
 
501
static void __attribute__((noreturn))
 
502
event_sighandler(int s)
529
503
{
530
504
        fprintf(stdout, "Now closing conntrack event dumping...\n");
531
505
        nfct_close(cth);
547
521
 
548
522
static const char usage_conntrack_parameters[] =
549
523
        "Conntrack parameters and options:\n"
550
 
        "  -a, --nat-range min_ip[-max_ip]\tNAT ip range\n"
 
524
        "  -n, --src-nat ip\t\t\tsource NAT ip\n"
 
525
        "  -g, --dst-nat ip\t\t\tdestination NAT ip\n"
551
526
        "  -m, --mark mark\t\t\tSet mark\n"
 
527
        "  -c, --secmark secmark\t\t\tSet selinux secmark\n"
552
528
        "  -e, --event-mask eventmask\t\tEvent mask, eg. NEW,DESTROY\n"
553
529
        "  -z, --zero \t\t\t\tZero counters while listing\n"
554
 
        ;
 
530
        "  -o, --output type[,...]\t\tOutput format, eg. xml\n";
555
531
 
556
532
static const char usage_expectation_parameters[] =
557
533
        "Expectation parameters and options:\n"
570
546
        "  -f, --family proto\t\tLayer 3 Protocol, eg. 'ipv6'\n"
571
547
        "  -t, --timeout timeout\t\tSet timeout\n"
572
548
        "  -u, --status status\t\tSet status, eg. ASSURED\n"
573
 
        "  -i, --id [id]\t\t\tShow or set conntrack ID\n"
574
549
        ;
575
550
  
576
551
 
577
 
void usage(char *prog) {
578
 
        fprintf(stdout, "Tool to manipulate conntrack and expectations. Version %s\n", VERSION);
 
552
static void
 
553
usage(char *prog)
 
554
{
 
555
        fprintf(stdout, "Command line interface for the connection "
 
556
                        "tracking system. Version %s\n", VERSION);
579
557
        fprintf(stdout, "Usage: %s [commands] [options]\n", prog);
580
558
 
581
559
        fprintf(stdout, "\n%s", usage_commands);
582
560
        fprintf(stdout, "\n%s", usage_tables);
583
561
        fprintf(stdout, "\n%s", usage_conntrack_parameters);
584
562
        fprintf(stdout, "\n%s", usage_expectation_parameters);
585
 
        fprintf(stdout, "\n%s", usage_parameters);
586
 
}
587
 
 
588
 
#define CT_COMPARISON (CT_OPT_PROTO | CT_OPT_ORIG | CT_OPT_REPL | CT_OPT_MARK)
589
 
 
590
 
static struct nfct_tuple orig, reply, mask;
591
 
static struct nfct_tuple exptuple;
 
563
        fprintf(stdout, "\n%s\n", usage_parameters);
 
564
}
 
565
 
 
566
static unsigned int output_mask;
 
567
 
 
568
static int event_cb(enum nf_conntrack_msg_type type,
 
569
                    struct nf_conntrack *ct,
 
570
                    void *data)
 
571
{
 
572
        char buf[1024];
 
573
        struct nf_conntrack *obj = data;
 
574
        unsigned int output_type = NFCT_O_DEFAULT;
 
575
        unsigned int output_flags = 0;
 
576
 
 
577
        if (options & CT_OPT_SRC_NAT && options & CT_OPT_DST_NAT) {
 
578
                if (!nfct_getobjopt(ct, NFCT_GOPT_IS_SNAT) &&
 
579
                    !nfct_getobjopt(ct, NFCT_GOPT_IS_DNAT))
 
580
                        return NFCT_CB_CONTINUE;
 
581
        } else if (options & CT_OPT_SRC_NAT && 
 
582
                   !nfct_getobjopt(ct, NFCT_GOPT_IS_SNAT)) {
 
583
                return NFCT_CB_CONTINUE;
 
584
        } else if (options & CT_OPT_DST_NAT &&
 
585
                   !nfct_getobjopt(ct, NFCT_GOPT_IS_DNAT)) {
 
586
                return NFCT_CB_CONTINUE;
 
587
        }
 
588
 
 
589
        if (options & CT_COMPARISON && !nfct_compare(obj, ct))
 
590
                return NFCT_CB_CONTINUE;
 
591
 
 
592
        if (output_mask & _O_XML)
 
593
                output_type = NFCT_O_XML;
 
594
        if (output_mask & _O_EXT)
 
595
                output_flags = NFCT_OF_SHOW_LAYER3;
 
596
        if (output_mask & _O_TMS) {
 
597
                if (!(output_mask & _O_XML)) {
 
598
                        struct timeval tv;
 
599
                        gettimeofday(&tv, NULL);
 
600
                        printf("[%-8ld.%-6ld]\t", tv.tv_sec, tv.tv_usec);
 
601
                } else
 
602
                        output_flags |= NFCT_OF_TIME;
 
603
        }       
 
604
 
 
605
        nfct_snprintf(buf, 1024, ct, type, output_type, output_flags);
 
606
        printf("%s\n", buf);
 
607
        fflush(stdout);
 
608
 
 
609
        return NFCT_CB_CONTINUE;
 
610
}
 
611
 
 
612
static int dump_cb(enum nf_conntrack_msg_type type,
 
613
                   struct nf_conntrack *ct,
 
614
                   void *data)
 
615
{
 
616
        char buf[1024];
 
617
        struct nf_conntrack *obj = data;
 
618
        unsigned int output_type = NFCT_O_DEFAULT;
 
619
        unsigned int output_flags = 0;
 
620
 
 
621
        if (options & CT_OPT_SRC_NAT && options & CT_OPT_DST_NAT) {
 
622
                if (!nfct_getobjopt(ct, NFCT_GOPT_IS_SNAT) &&
 
623
                    !nfct_getobjopt(ct, NFCT_GOPT_IS_DNAT))
 
624
                        return NFCT_CB_CONTINUE;
 
625
        } else if (options & CT_OPT_SRC_NAT && 
 
626
                   !nfct_getobjopt(ct, NFCT_GOPT_IS_SNAT)) {
 
627
                return NFCT_CB_CONTINUE;
 
628
        } else if (options & CT_OPT_DST_NAT &&
 
629
                   !nfct_getobjopt(ct, NFCT_GOPT_IS_DNAT)) {
 
630
                return NFCT_CB_CONTINUE;
 
631
        }
 
632
 
 
633
        if (options & CT_COMPARISON && !nfct_compare(obj, ct))
 
634
                return NFCT_CB_CONTINUE;
 
635
 
 
636
        if (output_mask & _O_XML)
 
637
                output_type = NFCT_O_XML;
 
638
        if (output_mask & _O_EXT)
 
639
                output_flags = NFCT_OF_SHOW_LAYER3;
 
640
 
 
641
        nfct_snprintf(buf, 1024, ct, NFCT_T_UNKNOWN, output_type, output_flags);
 
642
        printf("%s\n", buf);
 
643
 
 
644
        return NFCT_CB_CONTINUE;
 
645
}
 
646
 
 
647
static int dump_exp_cb(enum nf_conntrack_msg_type type,
 
648
                      struct nf_expect *exp,
 
649
                      void *data)
 
650
{
 
651
        char buf[1024];
 
652
 
 
653
        nfexp_snprintf(buf, 1024, exp, NFCT_T_UNKNOWN, NFCT_O_DEFAULT, 0);
 
654
        printf("%s\n", buf);
 
655
 
 
656
        return NFCT_CB_CONTINUE;
 
657
}
 
658
 
592
659
static struct ctproto_handler *h;
593
 
static union nfct_protoinfo proto;
594
 
static struct nfct_nat range;
595
 
static struct nfct_conntrack *ct;
596
 
static struct nfct_expect *exp;
597
 
static unsigned long timeout;
598
 
static unsigned int status;
599
 
static unsigned int mark;
600
 
static unsigned int id = NFCT_ANY_ID;
601
 
static struct nfct_conntrack_compare cmp;
602
660
 
603
661
int main(int argc, char *argv[])
604
662
{
605
 
        int c;
606
 
        unsigned int command = 0, options = 0;
607
 
        unsigned int type = 0, event_mask = 0;
608
 
        unsigned int l3flags = 0, l4flags = 0, metaflags = 0;
 
663
        int c, cmd;
 
664
        unsigned int type = 0, event_mask = 0, l4flags = 0, status = 0;
609
665
        int res = 0;
610
666
        int family = AF_UNSPEC;
611
 
        struct nfct_conntrack_compare *pcmp;
612
 
 
613
 
        while ((c = getopt_long(argc, argv, 
614
 
                "L::I::U::D::G::E::F::hVs:d:r:q:p:t:u:e:a:z[:]:{:}:m:i::f:", 
615
 
                opts, NULL)) != -1) {
 
667
        char __obj[nfct_maxsize()];
 
668
        char __exptuple[nfct_maxsize()];
 
669
        char __mask[nfct_maxsize()];
 
670
        struct nf_conntrack *obj = (struct nf_conntrack *)(void*) __obj;
 
671
        struct nf_conntrack *exptuple = (struct nf_conntrack *)(void*) __exptuple;
 
672
        struct nf_conntrack *mask = (struct nf_conntrack *)(void*) __mask;
 
673
        char __exp[nfexp_maxsize()];
 
674
        struct nf_expect *exp = (struct nf_expect *)(void*) __exp;
 
675
        int l3protonum;
 
676
        union ct_address ad;
 
677
        unsigned int command = 0;
 
678
 
 
679
        memset(__obj, 0, sizeof(__obj));
 
680
        memset(__exptuple, 0, sizeof(__exptuple));
 
681
        memset(__mask, 0, sizeof(__mask));
 
682
        memset(__exp, 0, sizeof(__exp));
 
683
 
 
684
        register_tcp();
 
685
        register_udp();
 
686
        register_icmp();
 
687
 
 
688
        while ((c = getopt_long(argc, argv, "L::I::U::D::G::E::F::hVs:d:r:q:"
 
689
                                            "p:t:u:e:a:z[:]:{:}:m:i::f:o:n::"
 
690
                                            "g::c:", 
 
691
                                            opts, NULL)) != -1) {
616
692
        switch(c) {
617
693
                case 'L':
618
694
                        type = check_type(argc, argv);
672
748
                        break;
673
749
                case 's':
674
750
                        options |= CT_OPT_ORIG_SRC;
675
 
                        if (optarg) {
676
 
                                orig.l3protonum =
677
 
                                        parse_inetaddr(optarg, &orig.src);
678
 
                                set_family(&family, orig.l3protonum);
679
 
                                if (orig.l3protonum == AF_INET)
680
 
                                        l3flags |= IPV4_ORIG_SRC;
681
 
                                else if (orig.l3protonum == AF_INET6)
682
 
                                        l3flags |= IPV6_ORIG_SRC;
 
751
                        if (!optarg)
 
752
                                break;
 
753
 
 
754
                        l3protonum = parse_addr(optarg, &ad);
 
755
                        set_family(&family, l3protonum);
 
756
                        if (l3protonum == AF_INET) {
 
757
                                nfct_set_attr_u32(obj, 
 
758
                                                  ATTR_ORIG_IPV4_SRC, 
 
759
                                                  ad.v4);
 
760
                        } else if (l3protonum == AF_INET6) {
 
761
                                nfct_set_attr(obj,
 
762
                                              ATTR_ORIG_IPV6_SRC, 
 
763
                                              &ad.v6);
683
764
                        }
 
765
                        nfct_set_attr_u8(obj, ATTR_ORIG_L3PROTO, l3protonum);
684
766
                        break;
685
767
                case 'd':
686
768
                        options |= CT_OPT_ORIG_DST;
687
 
                        if (optarg) {
688
 
                                orig.l3protonum = 
689
 
                                        parse_inetaddr(optarg, &orig.dst);
690
 
                                set_family(&family, orig.l3protonum);
691
 
                                if (orig.l3protonum == AF_INET)
692
 
                                        l3flags |= IPV4_ORIG_DST;
693
 
                                else if (orig.l3protonum == AF_INET6)
694
 
                                        l3flags |= IPV6_ORIG_DST;
 
769
                        if (!optarg)
 
770
                                break;
 
771
 
 
772
                        l3protonum = parse_addr(optarg, &ad);
 
773
                        set_family(&family, l3protonum);
 
774
                        if (l3protonum == AF_INET) {
 
775
                                nfct_set_attr_u32(obj, 
 
776
                                                  ATTR_ORIG_IPV4_DST,
 
777
                                                  ad.v4);
 
778
                        } else if (l3protonum == AF_INET6) {
 
779
                                nfct_set_attr(obj,
 
780
                                              ATTR_ORIG_IPV6_DST,
 
781
                                              &ad.v6);
695
782
                        }
 
783
                        nfct_set_attr_u8(obj, ATTR_ORIG_L3PROTO, l3protonum);
696
784
                        break;
697
785
                case 'r':
698
786
                        options |= CT_OPT_REPL_SRC;
699
 
                        if (optarg) {
700
 
                                reply.l3protonum = 
701
 
                                        parse_inetaddr(optarg, &reply.src);
702
 
                                set_family(&family, reply.l3protonum);
703
 
                                if (orig.l3protonum == AF_INET)
704
 
                                        l3flags |= IPV4_REPL_SRC;
705
 
                                else if (orig.l3protonum == AF_INET6)
706
 
                                        l3flags |= IPV6_REPL_SRC;
 
787
                        if (!optarg)
 
788
                                break;
 
789
 
 
790
                        l3protonum = parse_addr(optarg, &ad);
 
791
                        set_family(&family, l3protonum);
 
792
                        if (l3protonum == AF_INET) {
 
793
                                nfct_set_attr_u32(obj,
 
794
                                                  ATTR_REPL_IPV4_SRC, 
 
795
                                                  ad.v4);
 
796
                        } else if (l3protonum == AF_INET6) {
 
797
                                nfct_set_attr(obj,
 
798
                                              ATTR_REPL_IPV6_SRC,
 
799
                                              &ad.v6);
707
800
                        }
 
801
                        nfct_set_attr_u8(obj, ATTR_REPL_L3PROTO, l3protonum);
708
802
                        break;
709
803
                case 'q':
710
804
                        options |= CT_OPT_REPL_DST;
711
 
                        if (optarg) {
712
 
                                reply.l3protonum = 
713
 
                                        parse_inetaddr(optarg, &reply.dst);
714
 
                                set_family(&family, reply.l3protonum);
715
 
                                if (orig.l3protonum == AF_INET)
716
 
                                        l3flags |= IPV4_REPL_DST;
717
 
                                else if (orig.l3protonum == AF_INET6)
718
 
                                        l3flags |= IPV6_REPL_DST;
 
805
                        if (!optarg)
 
806
                                break;
 
807
 
 
808
                        l3protonum = parse_addr(optarg, &ad);
 
809
                        set_family(&family, l3protonum);
 
810
                        if (l3protonum == AF_INET) {
 
811
                                nfct_set_attr_u32(obj,
 
812
                                                  ATTR_REPL_IPV4_DST,
 
813
                                                  ad.v4);
 
814
                        } else if (l3protonum == AF_INET6) {
 
815
                                nfct_set_attr(obj,
 
816
                                              ATTR_REPL_IPV6_DST,
 
817
                                              &ad.v6);
719
818
                        }
 
819
                        nfct_set_attr_u8(obj, ATTR_REPL_L3PROTO, l3protonum);
720
820
                        break;
721
821
                case 'p':
722
822
                        options |= CT_OPT_PROTO;
723
823
                        h = findproto(optarg);
724
824
                        if (!h)
725
825
                                exit_error(PARAMETER_PROBLEM, "proto needed\n");
726
 
                        orig.protonum = h->protonum;
727
 
                        reply.protonum = h->protonum;
728
 
                        exptuple.protonum = h->protonum;
729
 
                        mask.protonum = h->protonum;
730
 
                        opts = merge_options(opts, h->opts, 
731
 
                                             &h->option_offset);
 
826
 
 
827
                        nfct_set_attr_u8(obj, ATTR_ORIG_L4PROTO, h->protonum);
 
828
                        nfct_set_attr_u8(obj, ATTR_REPL_L4PROTO, h->protonum);
 
829
                        nfct_set_attr_u8(exptuple, 
 
830
                                         ATTR_ORIG_L4PROTO, 
 
831
                                         h->protonum);
 
832
                        nfct_set_attr_u8(mask, 
 
833
                                         ATTR_ORIG_L4PROTO, 
 
834
                                         h->protonum);
 
835
                        opts = merge_options(opts, h->opts, &h->option_offset);
 
836
                        if (opts == NULL)
 
837
                                exit_error(EXIT_FAILURE, "out of memory\n");
732
838
                        break;
733
839
                case 't':
734
840
                        options |= CT_OPT_TIMEOUT;
735
 
                        if (optarg)
736
 
                                timeout = atol(optarg);
 
841
                        if (!optarg)
 
842
                                continue;
 
843
 
 
844
                        nfct_set_attr_u32(obj, ATTR_TIMEOUT, atol(optarg));
 
845
                        nfexp_set_attr_u32(exp, ATTR_EXP_TIMEOUT, atol(optarg));
737
846
                        break;
738
847
                case 'u': {
739
848
                        if (!optarg)
741
850
 
742
851
                        options |= CT_OPT_STATUS;
743
852
                        parse_parameter(optarg, &status, PARSE_STATUS);
 
853
                        nfct_set_attr_u32(obj, ATTR_STATUS, status);
744
854
                        break;
745
855
                }
746
856
                case 'e':
752
862
                        break;
753
863
                case '{':
754
864
                        options |= CT_OPT_MASK_SRC;
755
 
                        if (optarg) {
756
 
                                mask.l3protonum = 
757
 
                                        parse_inetaddr(optarg, &mask.src);
758
 
                                set_family(&family, mask.l3protonum);
 
865
                        if (!optarg)
 
866
                                break;
 
867
 
 
868
                        l3protonum = parse_addr(optarg, &ad);
 
869
                        set_family(&family, l3protonum);
 
870
                        if (l3protonum == AF_INET) {
 
871
                                nfct_set_attr_u32(mask, 
 
872
                                                  ATTR_ORIG_IPV4_SRC,
 
873
                                                  ad.v4);
 
874
                        } else if (l3protonum == AF_INET6) {
 
875
                                nfct_set_attr(mask,
 
876
                                              ATTR_ORIG_IPV6_SRC,
 
877
                                              &ad.v6);
759
878
                        }
 
879
                        nfct_set_attr_u8(mask, ATTR_ORIG_L3PROTO, l3protonum);
760
880
                        break;
761
881
                case '}':
762
882
                        options |= CT_OPT_MASK_DST;
763
 
                        if (optarg) {
764
 
                                mask.l3protonum = 
765
 
                                        parse_inetaddr(optarg, &mask.dst);
766
 
                                set_family(&family, mask.l3protonum);
 
883
                        if (!optarg)
 
884
                                break;
 
885
 
 
886
                        l3protonum = parse_addr(optarg, &ad);
 
887
                        set_family(&family, l3protonum);
 
888
                        if (l3protonum == AF_INET) {
 
889
                                nfct_set_attr_u32(mask, 
 
890
                                                  ATTR_ORIG_IPV4_DST,
 
891
                                                  ad.v4);
 
892
                        } else if (l3protonum == AF_INET6) {
 
893
                                nfct_set_attr(mask,
 
894
                                              ATTR_ORIG_IPV6_DST,
 
895
                                              &ad.v6);
767
896
                        }
 
897
                        nfct_set_attr_u8(mask, ATTR_ORIG_L3PROTO, l3protonum);
768
898
                        break;
769
899
                case '[':
770
900
                        options |= CT_OPT_EXP_SRC;
771
 
                        if (optarg) {
772
 
                                exptuple.l3protonum = 
773
 
                                        parse_inetaddr(optarg, &exptuple.src);
774
 
                                set_family(&family, exptuple.l3protonum);
 
901
                        if (!optarg)
 
902
                                break;
 
903
 
 
904
                        l3protonum = parse_addr(optarg, &ad);
 
905
                        set_family(&family, l3protonum);
 
906
                        if (l3protonum == AF_INET) {
 
907
                                nfct_set_attr_u32(exptuple, 
 
908
                                                  ATTR_ORIG_IPV4_SRC,
 
909
                                                  ad.v4);
 
910
                        } else if (l3protonum == AF_INET6) {
 
911
                                nfct_set_attr(exptuple,
 
912
                                              ATTR_ORIG_IPV6_SRC,
 
913
                                              &ad.v6);
775
914
                        }
 
915
                        nfct_set_attr_u8(exptuple, 
 
916
                                         ATTR_ORIG_L3PROTO, 
 
917
                                         l3protonum);
776
918
                        break;
777
919
                case ']':
778
920
                        options |= CT_OPT_EXP_DST;
779
 
                        if (optarg) {
780
 
                                exptuple.l3protonum = 
781
 
                                        parse_inetaddr(optarg, &exptuple.dst);
782
 
                                set_family(&family, exptuple.l3protonum);
 
921
                        if (!optarg)
 
922
                                break;
 
923
 
 
924
                        l3protonum = parse_addr(optarg, &ad);
 
925
                        set_family(&family, l3protonum);
 
926
                        if (l3protonum == AF_INET) {
 
927
                                nfct_set_attr_u32(exptuple, 
 
928
                                                  ATTR_ORIG_IPV4_DST,
 
929
                                                  ad.v4);
 
930
                        } else if (l3protonum == AF_INET6) {
 
931
                                nfct_set_attr(exptuple,
 
932
                                              ATTR_ORIG_IPV6_DST,
 
933
                                              &ad.v6);
783
934
                        }
 
935
                        nfct_set_attr_u8(exptuple, 
 
936
                                         ATTR_ORIG_L3PROTO, 
 
937
                                         l3protonum);
784
938
                        break;
785
939
                case 'a':
786
 
                        options |= CT_OPT_NATRANGE;
787
 
                        set_family(&family, AF_INET);
788
 
                        nat_parse(optarg, 1, &range);
789
 
                        break;
 
940
                        fprintf(stderr, "warning: ignoring --nat-range, "
 
941
                                "use --src-nat or --dst-nat instead.\n");
 
942
                        break;
 
943
                case 'n':
 
944
                        options |= CT_OPT_SRC_NAT;
 
945
                        if (!optarg)
 
946
                                break;
 
947
                        set_family(&family, AF_INET);
 
948
                        nat_parse(optarg, 1, obj, CT_OPT_SRC_NAT);
 
949
                        break;
 
950
                case 'g':
 
951
                        options |= CT_OPT_DST_NAT;
 
952
                        if (!optarg)
 
953
                                break;
 
954
                        set_family(&family, AF_INET);
 
955
                        nat_parse(optarg, 1, obj, CT_OPT_DST_NAT);
790
956
                case 'm':
791
957
                        options |= CT_OPT_MARK;
792
 
                        mark = atol(optarg);
793
 
                        metaflags |= NFCT_MARK;
794
 
                        break;
795
 
                case 'i': {
796
 
                        char *s = NULL;
797
 
                        options |= CT_OPT_ID;
798
 
                        if (optarg)
799
 
                                break;
800
 
                        else if (optind < argc && argv[optind][0] != '-'
801
 
                                        && argv[optind][0] != '!')
802
 
                                s = argv[optind++];
803
 
 
804
 
                        if (s)
805
 
                                id = atol(s);
806
 
                        break;
807
 
                }
 
958
                        if (!optarg)
 
959
                                continue;
 
960
                        nfct_set_attr_u32(obj, ATTR_MARK, atol(optarg));
 
961
                        break;
 
962
                case 'c':
 
963
                        options |= CT_OPT_SECMARK;
 
964
                        if (!optarg)
 
965
                                continue;
 
966
                        nfct_set_attr_u32(obj, ATTR_SECMARK, atol(optarg));
 
967
                        break;
 
968
                case 'i':
 
969
                        fprintf(stderr, 
 
970
                                "warning: ignoring --id. deprecated option.\n");
 
971
                        break;
808
972
                case 'f':
809
973
                        options |= CT_OPT_FAMILY;
810
974
                        if (strncmp(optarg, "ipv4", strlen("ipv4")) == 0)
815
979
                                exit_error(PARAMETER_PROBLEM, "Unknown "
816
980
                                           "protocol family\n");
817
981
                        break;
 
982
                case 'o':
 
983
                        options |= CT_OPT_OUTPUT;
 
984
                        parse_parameter(optarg, &output_mask, PARSE_OUTPUT);
 
985
                        break;
818
986
                default:
819
987
                        if (h && h->parse_opts 
820
 
                            &&!h->parse_opts(c - h->option_offset, argv, &orig, 
821
 
                                             &reply, &exptuple, &mask, &proto, 
822
 
                                             &l4flags))
 
988
                            &&!h->parse_opts(c - h->option_offset, obj,
 
989
                                             exptuple, mask, &l4flags))
823
990
                                exit_error(PARAMETER_PROBLEM, "parse error\n");
824
991
 
825
992
                        /* Unknown argument... */
836
1003
        if (family == AF_UNSPEC)
837
1004
                family = AF_INET;
838
1005
 
839
 
        generic_cmd_check(command, options);
840
 
        generic_opt_check(command, options);
 
1006
        cmd = bit2cmd(command);
 
1007
        generic_cmd_check(cmd, options);
 
1008
        generic_opt_check(options,
 
1009
                          NUMBER_OF_OPT,
 
1010
                          commands_v_options[cmd],
 
1011
                          optflags);
841
1012
 
842
 
        if (!(command & CT_HELP)
843
 
            && h && h->final_check 
844
 
            && !h->final_check(l4flags, command, &orig, &reply)) {
845
 
                usage(argv[0]);
846
 
                extension_help(h);
847
 
                exit_error(PARAMETER_PROBLEM, "Missing protocol arguments!\n");
848
 
        }
 
1013
        if (!(command & CT_HELP) && h && h->final_check)
 
1014
                h->final_check(l4flags, cmd, obj);
849
1015
 
850
1016
        switch(command) {
851
1017
 
854
1020
                if (!cth)
855
1021
                        exit_error(OTHER_PROBLEM, "Can't open handler");
856
1022
 
857
 
                if (options & CT_COMPARISON) {
858
 
 
859
 
                        if (options & CT_OPT_ZERO)
860
 
                                exit_error(PARAMETER_PROBLEM, "Can't use -z "
861
 
                                           "with filtering parameters");
862
 
 
863
 
                        ct = nfct_conntrack_alloc(&orig, &reply, timeout,
864
 
                                                  &proto, status, mark, id,
865
 
                                                  NULL);
866
 
                        if (!ct)
867
 
                                exit_error(OTHER_PROBLEM, "Not enough memory");
868
 
                        
869
 
                        cmp.ct = ct;
870
 
                        cmp.flags = metaflags;
871
 
                        cmp.l3flags = l3flags;
872
 
                        cmp.l4flags = l4flags;
873
 
                        pcmp = &cmp;
874
 
                }
875
 
 
876
 
                if (options & CT_OPT_ID)
877
 
                        nfct_register_callback(cth, 
878
 
                                        nfct_default_conntrack_display_id,
879
 
                                        (void *) pcmp);
880
 
                else
881
 
                        nfct_register_callback(cth,
882
 
                                        nfct_default_conntrack_display,
883
 
                                        (void *) pcmp);
884
 
                        
 
1023
                if (options & CT_COMPARISON && 
 
1024
                    options & CT_OPT_ZERO)
 
1025
                        exit_error(PARAMETER_PROBLEM, "Can't use -z with "
 
1026
                                                      "filtering parameters");
 
1027
 
 
1028
                nfct_callback_register(cth, NFCT_T_ALL, dump_cb, obj);
 
1029
 
885
1030
                if (options & CT_OPT_ZERO)
886
 
                        res = 
887
 
                        nfct_dump_conntrack_table_reset_counters(cth, family);
 
1031
                        res = nfct_query(cth, NFCT_Q_DUMP_RESET, &family);
888
1032
                else
889
 
                        res = nfct_dump_conntrack_table(cth, family);
 
1033
                        res = nfct_query(cth, NFCT_Q_DUMP, &family);
 
1034
 
890
1035
                nfct_close(cth);
891
1036
                break;
892
1037
 
894
1039
                cth = nfct_open(EXPECT, 0);
895
1040
                if (!cth)
896
1041
                        exit_error(OTHER_PROBLEM, "Can't open handler");
897
 
                if (options & CT_OPT_ID)
898
 
                        nfct_register_callback(cth, 
899
 
                                        nfct_default_expect_display_id,
900
 
                                        NULL);
901
 
                else
902
 
                        nfct_register_callback(cth,
903
 
                                        nfct_default_expect_display,
904
 
                                        NULL);
905
 
                res = nfct_dump_expect_list(cth, family);
 
1042
 
 
1043
                nfexp_callback_register(cth, NFCT_T_ALL, dump_exp_cb, NULL);
 
1044
                res = nfexp_query(cth, NFCT_Q_DUMP, &family);
906
1045
                nfct_close(cth);
907
1046
                break;
908
1047
                        
909
1048
        case CT_CREATE:
910
 
                if ((options & CT_OPT_ORIG) 
911
 
                    && !(options & CT_OPT_REPL)) {
912
 
                        reply.l3protonum = orig.l3protonum;
913
 
                        memcpy(&reply.src, &orig.dst, sizeof(reply.src));
914
 
                        memcpy(&reply.dst, &orig.src, sizeof(reply.dst));
915
 
                } else if (!(options & CT_OPT_ORIG)
916
 
                           && (options & CT_OPT_REPL)) {
917
 
                        orig.l3protonum = reply.l3protonum;
918
 
                        memcpy(&orig.src, &reply.dst, sizeof(orig.src));
919
 
                        memcpy(&orig.dst, &reply.src, sizeof(orig.dst));
920
 
                }
921
 
                if (options & CT_OPT_NATRANGE)
922
 
                        ct = nfct_conntrack_alloc(&orig, &reply, timeout, 
923
 
                                                  &proto, status, mark, id,
924
 
                                                  &range);
925
 
                else
926
 
                        ct = nfct_conntrack_alloc(&orig, &reply, timeout, 
927
 
                                                  &proto, status, mark, id,
928
 
                                                  NULL);
929
 
                if (!ct)
930
 
                        exit_error(OTHER_PROBLEM, "Not Enough memory");
931
 
                
 
1049
                if ((options & CT_OPT_ORIG) && !(options & CT_OPT_REPL))
 
1050
                        nfct_setobjopt(obj, NFCT_SOPT_SETUP_REPLY);
 
1051
                else if (!(options & CT_OPT_ORIG) && (options & CT_OPT_REPL))
 
1052
                        nfct_setobjopt(obj, NFCT_SOPT_SETUP_ORIGINAL);
 
1053
 
932
1054
                cth = nfct_open(CONNTRACK, 0);
933
 
                if (!cth) {
934
 
                        nfct_conntrack_free(ct);
 
1055
                if (!cth)
935
1056
                        exit_error(OTHER_PROBLEM, "Can't open handler");
936
 
                }
937
 
                res = nfct_create_conntrack(cth, ct);
 
1057
 
 
1058
                res = nfct_query(cth, NFCT_Q_CREATE, obj);
938
1059
                nfct_close(cth);
939
 
                nfct_conntrack_free(ct);
940
1060
                break;
941
1061
 
942
1062
        case EXP_CREATE:
943
 
                if (options & CT_OPT_ORIG)
944
 
                        exp = nfct_expect_alloc(&orig, &exptuple,
945
 
                                                &mask, timeout, id);
946
 
                else if (options & CT_OPT_REPL)
947
 
                        exp = nfct_expect_alloc(&reply, &exptuple,
948
 
                                                &mask, timeout, id);
949
 
                if (!exp)
950
 
                        exit_error(OTHER_PROBLEM, "Not enough memory");
 
1063
                nfexp_set_attr(exp, ATTR_EXP_MASTER, obj);
 
1064
                nfexp_set_attr(exp, ATTR_EXP_EXPECTED, exptuple);
 
1065
                nfexp_set_attr(exp, ATTR_EXP_MASK, mask);
951
1066
 
952
1067
                cth = nfct_open(EXPECT, 0);
953
 
                if (!cth) {
954
 
                        nfct_expect_free(exp);
 
1068
                if (!cth)
955
1069
                        exit_error(OTHER_PROBLEM, "Can't open handler");
956
 
                }
957
 
                res = nfct_create_expectation(cth, exp);
958
 
                nfct_expect_free(exp);
 
1070
 
 
1071
                res = nfexp_query(cth, NFCT_Q_CREATE, exp);
959
1072
                nfct_close(cth);
960
1073
                break;
961
1074
 
962
1075
        case CT_UPDATE:
963
 
                if ((options & CT_OPT_ORIG) 
964
 
                    && !(options & CT_OPT_REPL)) {
965
 
                        reply.l3protonum = orig.l3protonum;
966
 
                        memcpy(&reply.src, &orig.dst, sizeof(reply.src));
967
 
                        memcpy(&reply.dst, &orig.src, sizeof(reply.dst));
968
 
                } else if (!(options & CT_OPT_ORIG)
969
 
                           && (options & CT_OPT_REPL)) {
970
 
                        orig.l3protonum = reply.l3protonum;
971
 
                        memcpy(&orig.src, &reply.dst, sizeof(orig.src));
972
 
                        memcpy(&orig.dst, &reply.src, sizeof(orig.dst));
973
 
                }
974
 
                ct = nfct_conntrack_alloc(&orig, &reply, timeout,
975
 
                                          &proto, status, mark, id,
976
 
                                          NULL);
977
 
                if (!ct)
978
 
                        exit_error(OTHER_PROBLEM, "Not enough memory");
979
 
                
 
1076
                if ((options & CT_OPT_ORIG) && !(options & CT_OPT_REPL))
 
1077
                        nfct_setobjopt(obj, NFCT_SOPT_SETUP_REPLY);
 
1078
                else if (!(options & CT_OPT_ORIG) && (options & CT_OPT_REPL))
 
1079
                        nfct_setobjopt(obj, NFCT_SOPT_SETUP_ORIGINAL);
 
1080
 
980
1081
                cth = nfct_open(CONNTRACK, 0);
981
 
                if (!cth) {
982
 
                        nfct_conntrack_free(ct);
 
1082
                if (!cth)
983
1083
                        exit_error(OTHER_PROBLEM, "Can't open handler");
984
 
                }
985
 
                res = nfct_update_conntrack(cth, ct);
986
 
                nfct_conntrack_free(ct);
 
1084
 
 
1085
                res = nfct_query(cth, NFCT_Q_UPDATE, obj);
987
1086
                nfct_close(cth);
988
1087
                break;
989
1088
                
994
1093
                cth = nfct_open(CONNTRACK, 0);
995
1094
                if (!cth)
996
1095
                        exit_error(OTHER_PROBLEM, "Can't open handler");
997
 
                if (options & CT_OPT_ORIG)
998
 
                        res = nfct_delete_conntrack(cth, &orig, 
999
 
                                                    NFCT_DIR_ORIGINAL,
1000
 
                                                    id);
1001
 
                else if (options & CT_OPT_REPL)
1002
 
                        res = nfct_delete_conntrack(cth, &reply, 
1003
 
                                                    NFCT_DIR_REPLY,
1004
 
                                                    id);
 
1096
 
 
1097
                res = nfct_query(cth, NFCT_Q_DESTROY, obj);
1005
1098
                nfct_close(cth);
1006
1099
                break;
1007
1100
 
1008
1101
        case EXP_DELETE:
 
1102
                nfexp_set_attr(exp, ATTR_EXP_EXPECTED, obj);
 
1103
 
1009
1104
                cth = nfct_open(EXPECT, 0);
1010
1105
                if (!cth)
1011
1106
                        exit_error(OTHER_PROBLEM, "Can't open handler");
1012
 
                if (options & CT_OPT_ORIG)
1013
 
                        res = nfct_delete_expectation(cth, &orig, id);
1014
 
                else if (options & CT_OPT_REPL)
1015
 
                        res = nfct_delete_expectation(cth, &reply, id);
 
1107
 
 
1108
                res = nfexp_query(cth, NFCT_Q_DESTROY, exp);
1016
1109
                nfct_close(cth);
1017
1110
                break;
1018
1111
 
1020
1113
                cth = nfct_open(CONNTRACK, 0);
1021
1114
                if (!cth)
1022
1115
                        exit_error(OTHER_PROBLEM, "Can't open handler");
1023
 
                nfct_register_callback(cth, nfct_default_conntrack_display,
1024
 
                                        NULL);
1025
 
                if (options & CT_OPT_ORIG)
1026
 
                        res = nfct_get_conntrack(cth, &orig,
1027
 
                                                 NFCT_DIR_ORIGINAL, id);
1028
 
                else if (options & CT_OPT_REPL)
1029
 
                        res = nfct_get_conntrack(cth, &reply,
1030
 
                                                 NFCT_DIR_REPLY, id);
 
1116
 
 
1117
                nfct_callback_register(cth, NFCT_T_ALL, dump_cb, obj);
 
1118
                res = nfct_query(cth, NFCT_Q_GET, obj);
1031
1119
                nfct_close(cth);
1032
1120
                break;
1033
1121
 
1034
1122
        case EXP_GET:
 
1123
                nfexp_set_attr(exp, ATTR_EXP_MASTER, obj);
 
1124
 
1035
1125
                cth = nfct_open(EXPECT, 0);
1036
1126
                if (!cth)
1037
1127
                        exit_error(OTHER_PROBLEM, "Can't open handler");
1038
 
                nfct_register_callback(cth, nfct_default_expect_display,
1039
 
                                        NULL);
1040
 
                if (options & CT_OPT_ORIG)
1041
 
                        res = nfct_get_expectation(cth, &orig, id);
1042
 
                else if (options & CT_OPT_REPL)
1043
 
                        res = nfct_get_expectation(cth, &reply, id);
 
1128
 
 
1129
                nfexp_callback_register(cth, NFCT_T_ALL, dump_exp_cb, NULL);
 
1130
                res = nfexp_query(cth, NFCT_Q_GET, exp);
1044
1131
                nfct_close(cth);
1045
1132
                break;
1046
1133
 
1048
1135
                cth = nfct_open(CONNTRACK, 0);
1049
1136
                if (!cth)
1050
1137
                        exit_error(OTHER_PROBLEM, "Can't open handler");
1051
 
                res = nfct_flush_conntrack_table(cth, AF_INET);
 
1138
                res = nfct_query(cth, NFCT_Q_FLUSH, &family);
1052
1139
                nfct_close(cth);
1053
1140
                break;
1054
1141
 
1056
1143
                cth = nfct_open(EXPECT, 0);
1057
1144
                if (!cth)
1058
1145
                        exit_error(OTHER_PROBLEM, "Can't open handler");
1059
 
                res = nfct_flush_expectation_table(cth, AF_INET);
 
1146
                res = nfexp_query(cth, NFCT_Q_FLUSH, &family);
1060
1147
                nfct_close(cth);
1061
1148
                break;
1062
1149
                
1069
1156
                if (!cth)
1070
1157
                        exit_error(OTHER_PROBLEM, "Can't open handler");
1071
1158
                signal(SIGINT, event_sighandler);
1072
 
 
1073
 
                if (options & CT_COMPARISON) {
1074
 
                        ct = nfct_conntrack_alloc(&orig, &reply, timeout,
1075
 
                                                  &proto, status, mark, id, 
1076
 
                                                  NULL);
1077
 
                        if (!ct)
1078
 
                                exit_error(OTHER_PROBLEM, "Not enough memory");
1079
 
 
1080
 
                        cmp.ct = ct;
1081
 
                        cmp.flags = metaflags;
1082
 
                        cmp.l3flags = l3flags;
1083
 
                        cmp.l4flags = l4flags;
1084
 
                        pcmp = &cmp;
1085
 
                }
1086
 
 
1087
 
                nfct_register_callback(cth,
1088
 
                                       nfct_default_conntrack_event_display, 
1089
 
                                       (void *) pcmp);
1090
 
                res = nfct_event_conntrack(cth);
 
1159
                nfct_callback_register(cth, NFCT_T_ALL, event_cb, obj);
 
1160
                res = nfct_catch(cth);
1091
1161
                nfct_close(cth);
1092
1162
                break;
1093
1163
 
1096
1166
                if (!cth)
1097
1167
                        exit_error(OTHER_PROBLEM, "Can't open handler");
1098
1168
                signal(SIGINT, event_sighandler);
1099
 
                nfct_register_callback(cth, nfct_default_expect_display,
1100
 
                                        NULL);
1101
 
                res = nfct_event_expectation(cth);
 
1169
                nfexp_callback_register(cth, NFCT_T_ALL, dump_exp_cb, NULL);
 
1170
                res = nfexp_catch(cth);
1102
1171
                nfct_close(cth);
1103
1172
                break;
1104
1173
                        
1105
1174
        case CT_VERSION:
1106
 
                fprintf(stdout, "%s v%s\n", PROGNAME, VERSION);
 
1175
                printf("%s v%s (conntrack-tools)\n", PROGNAME, VERSION);
1107
1176
                break;
1108
1177
        case CT_HELP:
1109
1178
                usage(argv[0]);
1122
1191
        }
1123
1192
 
1124
1193
        if (res < 0) {
1125
 
                fprintf(stderr, "Operation failed: %s\n", err2str(res, command));
 
1194
                fprintf(stderr, "Operation failed: %s\n", err2str(errno, command));
1126
1195
                exit(OTHER_PROBLEM);
1127
1196
        }
1128
1197