summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
author/C=EU/ST=EU/CN=Pablo Neira Ayuso/emailAddress=pablo@netfilter.org </C=EU/ST=EU/CN=Pablo Neira Ayuso/emailAddress=pablo@netfilter.org>2007-07-18 20:04:00 +0000
committer/C=EU/ST=EU/CN=Pablo Neira Ayuso/emailAddress=pablo@netfilter.org </C=EU/ST=EU/CN=Pablo Neira Ayuso/emailAddress=pablo@netfilter.org>2007-07-18 20:04:00 +0000
commit18bbf19becaab7dc4137406928f96ad089192f69 (patch)
treec6d75df8591e20083044cbf07d73e8f6738fd1fd /src
parent96084e1a1f2e0a49c961bbddb9fffd2e03bfae3f (diff)
conntrackd:
- use buffer of MTU size conntrack: - better protocol argument checkings - fix per-protocol filtering, eg. conntrack -[L|E] -p tcp now works - show per-protocol help, ie. conntrack -h -p tcp - add alias --src for --orig-src and alias --dst for --orig-dst
Diffstat (limited to 'src')
-rw-r--r--src/conntrack.c108
-rw-r--r--src/mcast.c14
-rw-r--r--src/network.c32
-rw-r--r--src/read_config_lex.l3
-rw-r--r--src/read_config_yy.y9
-rw-r--r--src/sync-mode.c9
6 files changed, 107 insertions, 68 deletions
diff --git a/src/conntrack.c b/src/conntrack.c
index eece45b..165809b 100644
--- a/src/conntrack.c
+++ b/src/conntrack.c
@@ -64,8 +64,10 @@ static const char cmdflags[NUMBER_OF_CMD]
static const char cmd_need_param[NUMBER_OF_CMD]
= { 2, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0, 0, 2, 2 };
-static const char optflags[NUMBER_OF_OPT]
-= {'s','d','r','q','p','t','u','z','e','[',']','{','}','a','m','i','f','n','g','x'};
+static const char *optflags[NUMBER_OF_OPT] = {
+"src","dst","reply-src","reply-dst","protonum","timeout","status","zero",
+"event-mask","tuple-src","tuple-dst","mask-src","mask-dst","nat-range","mark",
+"id","family","src-nat","dst-nat","output" };
static struct option original_opts[] = {
{"dump", 2, 0, 'L'},
@@ -78,7 +80,9 @@ static struct option original_opts[] = {
{"version", 0, 0, 'V'},
{"help", 0, 0, 'h'},
{"orig-src", 1, 0, 's'},
+ {"src", 1, 0, 's'},
{"orig-dst", 1, 0, 'd'},
+ {"dst", 1, 0, 'd'},
{"reply-src", 1, 0, 'r'},
{"reply-dst", 1, 0, 'q'},
{"protonum", 1, 0, 'p'},
@@ -127,7 +131,7 @@ static char commands_v_options[NUMBER_OF_CMD][NUMBER_OF_OPT] =
/*CT_FLUSH*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
/*CT_EVENT*/ {2,2,2,2,2,0,0,0,2,0,0,0,0,0,2,0,0,2,2,2},
/*VERSION*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
-/*HELP*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+/*HELP*/ {0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
/*EXP_LIST*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,0,0,0},
/*EXP_CREATE*/{1,1,2,2,1,1,2,0,0,1,1,1,1,0,0,0,0,0,0,0},
/*EXP_DELETE*/{1,1,2,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
@@ -172,12 +176,6 @@ static struct ctproto_handler *findproto(char *name)
return handler;
}
-enum exittype {
- OTHER_PROBLEM = 1,
- PARAMETER_PROBLEM,
- VERSION_PROBLEM
-};
-
void extension_help(struct ctproto_handler *h)
{
fprintf(stdout, "\n");
@@ -193,8 +191,7 @@ exit_tryhelp(int status)
exit(status);
}
-static void
-exit_error(enum exittype status, char *msg, ...)
+void exit_error(enum exittype status, char *msg, ...)
{
va_list args;
@@ -218,51 +215,43 @@ exit_error(enum exittype status, char *msg, ...)
static void
generic_cmd_check(int command, int options)
{
- int i;
-
- for (i = 0; i < NUMBER_OF_CMD; i++) {
- if (!(command & (1<<i)))
- continue;
-
- if (cmd_need_param[i] == 0 && !options)
- exit_error(PARAMETER_PROBLEM,
- "You need to supply parameters to `-%c'\n",
- cmdflags[i]);
- }
+ if (cmd_need_param[command] == 0 && !options)
+ exit_error(PARAMETER_PROBLEM,
+ "You need to supply parameters to `-%c'\n",
+ cmdflags[command]);
}
-static void
-generic_opt_check(int command, int options)
+static int bit2cmd(int command)
{
- int i, j, legal = 0;
+ int i;
- /* Check that commands are valid with options. Complicated by the
- * fact that if an option is legal with *any* command given, it is
- * legal overall (ie. -z and -l).
- */
- for (i = 0; i < NUMBER_OF_OPT; i++) {
- legal = 0; /* -1 => illegal, 1 => legal, 0 => undecided. */
+ for (i = 0; i < NUMBER_OF_CMD; i++)
+ if (command & (1<<i))
+ break;
- for (j = 0; j < NUMBER_OF_CMD; j++) {
- if (!(command & (1<<j)))
- continue;
+ return i;
+}
- if (!(options & (1<<i))) {
- if (commands_v_options[j][i] == 1)
- exit_error(PARAMETER_PROBLEM,
- "You need to supply the "
- "`-%c' option for this "
- "command\n", optflags[i]);
- } else {
- if (commands_v_options[j][i] != 0)
- legal = 1;
- else if (legal == 0)
- legal = -1;
- }
+void generic_opt_check(int options,
+ int num_opts,
+ char *optset,
+ const char *optflg[])
+{
+ int i;
+
+ for (i = 0; i < num_opts; i++) {
+ if (!(options & (1<<i))) {
+ if (optset[i] == 1)
+ exit_error(PARAMETER_PROBLEM,
+ "You need to supply the "
+ "`--%s' option for this "
+ "command\n", optflg[i]);
+ } else {
+ if (optset[i] == 0)
+ exit_error(PARAMETER_PROBLEM, "Illegal "
+ "option `--%s' with this "
+ "command\n", optflg[i]);
}
- if (legal == -1)
- exit_error(PARAMETER_PROBLEM, "Illegal option `-%c' "
- "with this command\n", optflags[i]);
}
}
@@ -664,7 +653,7 @@ static struct ctproto_handler *h;
int main(int argc, char *argv[])
{
- int c;
+ int c, cmd;
unsigned int type = 0, event_mask = 0, l4flags = 0, status = 0;
int res = 0;
int family = AF_UNSPEC;
@@ -978,7 +967,7 @@ int main(int argc, char *argv[])
break;
default:
if (h && h->parse_opts
- &&!h->parse_opts(c - h->option_offset, argv, obj,
+ &&!h->parse_opts(c - h->option_offset, obj,
exptuple, mask, &l4flags))
exit_error(PARAMETER_PROBLEM, "parse error\n");
@@ -996,16 +985,15 @@ int main(int argc, char *argv[])
if (family == AF_UNSPEC)
family = AF_INET;
- generic_cmd_check(command, options);
- generic_opt_check(command, options);
+ cmd = bit2cmd(command);
+ generic_cmd_check(cmd, options);
+ generic_opt_check(options,
+ NUMBER_OF_OPT,
+ commands_v_options[cmd],
+ optflags);
- if (!(command & CT_HELP)
- && h && h->final_check
- && !h->final_check(l4flags, command, obj)) {
- usage(argv[0]);
- extension_help(h);
- exit_error(PARAMETER_PROBLEM, "Missing protocol arguments!\n");
- }
+ if (!(command & CT_HELP) && h && h->final_check)
+ h->final_check(l4flags, cmd, obj);
switch(command) {
diff --git a/src/mcast.c b/src/mcast.c
index 6193a59..cdaed5f 100644
--- a/src/mcast.c
+++ b/src/mcast.c
@@ -26,6 +26,8 @@
#include <sys/time.h>
#include <unistd.h>
#include <string.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
#include "mcast.h"
#include "debug.h"
@@ -71,6 +73,18 @@ struct mcast_sock *mcast_server_create(struct mcast_conf *conf)
return NULL;
}
+ if(conf->iface[0]) {
+ struct ifreq ifr;
+
+ strncpy(ifr.ifr_name, conf->iface, sizeof(ifr.ifr_name));
+
+ if (ioctl(m->fd, SIOCGIFMTU, &ifr) == -1) {
+ debug("ioctl");
+ return NULL;
+ }
+ conf->mtu = ifr.ifr_mtu;
+ }
+
if (setsockopt(m->fd, SOL_SOCKET, SO_REUSEADDR, &yes,
sizeof(int)) == -1) {
debug("mcast_sock_server_create:setsockopt1");
diff --git a/src/network.c b/src/network.c
index d162839..a7843dc 100644
--- a/src/network.c
+++ b/src/network.c
@@ -90,9 +90,33 @@ int prepare_send_netmsg(struct mcast_sock *m, void *data)
return ret;
}
+static int tx_buflenmax;
static int tx_buflen = 0;
-/* XXX: use buffer size of interface MTU */
-static char __tx_buf[1460], *tx_buf = __tx_buf;
+static char *tx_buf;
+
+#define HEADERSIZ 28 /* IP header (20 bytes) + UDP header 8 (bytes) */
+
+int mcast_buffered_init(struct mcast_conf *conf)
+{
+ int mtu = conf->mtu - HEADERSIZ;
+
+ /* default to Ethernet MTU 1500 bytes */
+ if (mtu == 0)
+ mtu = 1500 - HEADERSIZ;
+
+ tx_buf = malloc(mtu);
+ if (tx_buf == NULL)
+ return -1;
+
+ tx_buflenmax = mtu;
+
+ return 0;
+}
+
+void mcast_buffered_destroy(void)
+{
+ free(tx_buf);
+}
/* return 0 if it is not sent, otherwise return 1 */
int mcast_buffered_send_netmsg(struct mcast_sock *m, void *data, int len)
@@ -101,8 +125,8 @@ int mcast_buffered_send_netmsg(struct mcast_sock *m, void *data, int len)
struct nethdr *net = data;
retry:
- if (tx_buflen + len < sizeof(__tx_buf)) {
- memcpy(__tx_buf + tx_buflen, net, len);
+ if (tx_buflen + len < tx_buflenmax) {
+ memcpy(tx_buf + tx_buflen, net, len);
tx_buflen += len;
} else {
__do_send(m, tx_buf, tx_buflen);
diff --git a/src/read_config_lex.l b/src/read_config_lex.l
index dee90c9..87e98d1 100644
--- a/src/read_config_lex.l
+++ b/src/read_config_lex.l
@@ -42,7 +42,7 @@ ip6_part {hex_255}":"?
ip6_form1 {ip6_part}{0,16}"::"{ip6_part}{0,16}
ip6_form2 ({hex_255}":"){16}{hex_255}
ip6 {ip6_form1}|{ip6_form2}
-string [a-zA-Z]*
+string [a-zA-Z0-9]*
persistent [P|p][E|e][R|r][S|s][I|i][S|s][T|t][E|e][N|n][T|T]
nack [N|n][A|a][C|c][K|k]
@@ -52,6 +52,7 @@ nack [N|n][A|a][C|c][K|k]
"IPv6_address" { return T_IPV6_ADDR; }
"IPv4_interface" { return T_IPV4_IFACE; }
"IPv6_interface" { return T_IPV6_IFACE; }
+"Interface" { return T_IFACE; }
"Port" { return T_PORT; }
"Multicast" { return T_MULTICAST; }
"HashSize" { return T_HASHSIZE; }
diff --git a/src/read_config_yy.y b/src/read_config_yy.y
index 57250b4..de592d2 100644
--- a/src/read_config_yy.y
+++ b/src/read_config_yy.y
@@ -1,6 +1,6 @@
%{
/*
- * (C) 2006 by Pablo Neira Ayuso <pablo@netfilter.org>
+ * (C) 2006-2007 by Pablo Neira Ayuso <pablo@netfilter.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -45,7 +45,7 @@ struct ct_conf conf;
%token T_GENERAL T_SYNC T_STATS T_RELAX_TRANSITIONS T_BUFFER_SIZE T_DELAY
%token T_SYNC_MODE T_LISTEN_TO T_FAMILY T_RESEND_BUFFER_SIZE
%token T_PERSISTENT T_NACK T_CHECKSUM T_WINDOWSIZE T_ON T_OFF
-%token T_REPLICATE T_FOR
+%token T_REPLICATE T_FOR T_IFACE
%token T_ESTABLISHED T_SYN_SENT T_SYN_RECV T_FIN_WAIT
%token T_CLOSE_WAIT T_LAST_ACK T_TIME_WAIT T_CLOSE T_LISTEN
@@ -227,6 +227,11 @@ multicast_option : T_IPV6_IFACE T_IP
conf.mcast.ipproto = AF_INET6;
};
+multicast_option : T_IFACE T_STRING
+{
+ strncpy(conf.mcast.iface, $2, IFNAMSIZ);
+};
+
multicast_option : T_BACKLOG T_NUMBER
{
fprintf(stderr, "Notice: Backlog option inside Multicast clause is "
diff --git a/src/sync-mode.c b/src/sync-mode.c
index f30cb95..917a3b2 100644
--- a/src/sync-mode.c
+++ b/src/sync-mode.c
@@ -86,7 +86,7 @@ retry:
static void mcast_handler()
{
int numbytes, remain;
- char __net[4096], *ptr = __net;
+ char __net[65536], *ptr = __net; /* XXX: maximum MTU for IPv4 */
numbytes = mcast_recv(STATE_SYNC(mcast_server), __net, sizeof(__net));
if (numbytes <= 0)
@@ -173,6 +173,11 @@ static int init_sync(void)
return -1;
}
+ if (mcast_buffered_init(&CONFIG(mcast)) == -1) {
+ dlog(STATE(log), "[FAIL] can't init tx buffer!");
+ return -1;
+ }
+
/* initialization of multicast sequence generation */
STATE_SYNC(last_seq_sent) = time(NULL);
@@ -207,6 +212,8 @@ static void kill_sync()
mcast_server_destroy(STATE_SYNC(mcast_server));
mcast_client_destroy(STATE_SYNC(mcast_client));
+ mcast_buffered_destroy();
+
if (STATE_SYNC(sync)->kill)
STATE_SYNC(sync)->kill();
}