summaryrefslogtreecommitdiffstats
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
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
-rw-r--r--ChangeLog7
-rw-r--r--examples/sync/nack/node1/conntrackd.conf1
-rw-r--r--examples/sync/nack/node2/conntrackd.conf1
-rw-r--r--examples/sync/persistent/node1/conntrackd.conf1
-rw-r--r--examples/sync/persistent/node2/conntrackd.conf1
-rw-r--r--extensions/libct_proto_icmp.c45
-rw-r--r--extensions/libct_proto_tcp.c63
-rw-r--r--extensions/libct_proto_udp.c50
-rw-r--r--include/conntrack.h28
-rw-r--r--include/mcast.h3
-rw-r--r--include/network.h7
-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
17 files changed, 266 insertions, 116 deletions
diff --git a/ChangeLog b/ChangeLog
index b65966b..23ab6e9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -5,6 +5,7 @@ version 0.9.5 (yet unreleased)
o conntrack-tools requires libnetfilter_conntrack >= 0.0.81
o add len field to nethdr
o implement buffered send/recv to batch messages
+o use buffer of MTU size
o stop using netlink format for network messages: use similar TLV-based format
o reduce synchronization messages size up to 60%
o introduce periodic alive messages for sync-nack protocol
@@ -14,6 +15,12 @@ o remove major use of libnfnetlink functions: use libnetfilter_conntrack API
o deprecate conntrackd -F, use conntrack -F instead
o major rework of the network infrastructure: much simple, less messy
+= conntrack =
+o better protocol argument checkings
+o fix per-protocol filtering, eg. conntrack -L -p tcp
+o show per-protocol help, ie. conntrack -h -p tcp
+o add alias --src for --orig-src and alias --dst for --orig-dst
+
version 0.9.4 (2007/07/02)
------------------------------
diff --git a/examples/sync/nack/node1/conntrackd.conf b/examples/sync/nack/node1/conntrackd.conf
index edec9cf..9a7d55f 100644
--- a/examples/sync/nack/node1/conntrackd.conf
+++ b/examples/sync/nack/node1/conntrackd.conf
@@ -32,6 +32,7 @@ Sync {
Multicast {
IPv4_address 225.0.0.50
IPv4_interface 192.168.100.100 # IP of dedicated link
+ Interface eth2
Group 3780
}
diff --git a/examples/sync/nack/node2/conntrackd.conf b/examples/sync/nack/node2/conntrackd.conf
index de5f4d2..cee16c8 100644
--- a/examples/sync/nack/node2/conntrackd.conf
+++ b/examples/sync/nack/node2/conntrackd.conf
@@ -31,6 +31,7 @@ Sync {
Multicast {
IPv4_address 225.0.0.50
IPv4_interface 192.168.100.200 # IP of dedicated link
+ Interface eth2
Group 3780
}
diff --git a/examples/sync/persistent/node1/conntrackd.conf b/examples/sync/persistent/node1/conntrackd.conf
index 60f264b..e80921b 100644
--- a/examples/sync/persistent/node1/conntrackd.conf
+++ b/examples/sync/persistent/node1/conntrackd.conf
@@ -37,6 +37,7 @@ Sync {
Multicast {
IPv4_address 225.0.0.50
IPv4_interface 192.168.100.100 # IP of dedicated link
+ Interface eth2
Group 3780
}
diff --git a/examples/sync/persistent/node2/conntrackd.conf b/examples/sync/persistent/node2/conntrackd.conf
index 6a1806b..ad4b040 100644
--- a/examples/sync/persistent/node2/conntrackd.conf
+++ b/examples/sync/persistent/node2/conntrackd.conf
@@ -37,6 +37,7 @@ Sync {
Multicast {
IPv4_address 225.0.0.50
IPv4_interface 192.168.100.200 # IP of dedicated link
+ Interface eth2
Group 3780
}
diff --git a/extensions/libct_proto_icmp.c b/extensions/libct_proto_icmp.c
index 765ced4..09fd8da 100644
--- a/extensions/libct_proto_icmp.c
+++ b/extensions/libct_proto_icmp.c
@@ -24,6 +24,33 @@ static struct option opts[] = {
{0, 0, 0, 0}
};
+#define ICMP_NUMBER_OF_OPT 4
+
+static const char *icmp_optflags[ICMP_NUMBER_OF_OPT] = {
+"icmp-type", "icmp-code", "icmp-id"
+};
+
+static char icmp_commands_v_options[NUMBER_OF_CMD][ICMP_NUMBER_OF_OPT] =
+/* Well, it's better than "Re: Maradona vs Pele" */
+{
+ /* 1 2 3 */
+/*CT_LIST*/ {2,2,2},
+/*CT_CREATE*/ {1,1,2},
+/*CT_UPDATE*/ {1,1,2},
+/*CT_DELETE*/ {1,1,2},
+/*CT_GET*/ {1,1,2},
+/*CT_FLUSH*/ {0,0,0},
+/*CT_EVENT*/ {2,2,2},
+/*CT_VERSION*/ {0,0,0},
+/*CT_HELP*/ {0,0,0},
+/*EXP_LIST*/ {0,0,0},
+/*EXP_CREATE*/ {0,0,0},
+/*EXP_DELETE*/ {0,0,0},
+/*EXP_GET*/ {0,0,0},
+/*EXP_FLUSH*/ {0,0,0},
+/*EXP_EVENT*/ {0,0,0},
+};
+
static void help()
{
fprintf(stdout, " --icmp-type\t\t\ticmp type\n");
@@ -31,7 +58,7 @@ static void help()
fprintf(stdout, " --icmp-id\t\t\ticmp id\n");
}
-static int parse(char c, char *argv[],
+static int parse(char c,
struct nf_conntrack *ct,
struct nf_conntrack *exptuple,
struct nf_conntrack *mask,
@@ -69,16 +96,14 @@ static int parse(char c, char *argv[],
return 1;
}
-static int final_check(unsigned int flags,
- unsigned int command,
- struct nf_conntrack *ct)
+static void final_check(unsigned int flags,
+ unsigned int cmd,
+ struct nf_conntrack *ct)
{
- if (!(flags & ICMP_TYPE))
- return 0;
- else if (!(flags & ICMP_CODE))
- return 0;
-
- return 1;
+ generic_opt_check(flags,
+ ICMP_NUMBER_OF_OPT,
+ icmp_commands_v_options[cmd],
+ icmp_optflags);
}
static struct ctproto_handler icmp = {
diff --git a/extensions/libct_proto_tcp.c b/extensions/libct_proto_tcp.c
index 5a40cef..1f630b3 100644
--- a/extensions/libct_proto_tcp.c
+++ b/extensions/libct_proto_tcp.c
@@ -32,6 +32,34 @@ static struct option opts[] = {
{0, 0, 0, 0}
};
+#define TCP_NUMBER_OF_OPT 10
+
+static const char *tcp_optflags[TCP_NUMBER_OF_OPT] = {
+"sport", "dport", "reply-port-src", "reply-port-dst", "mask-port-src",
+"mask-port-dst", "state", "tuple-port-src", "tuple-port-dst"
+};
+
+static char tcp_commands_v_options[NUMBER_OF_CMD][TCP_NUMBER_OF_OPT] =
+/* Well, it's better than "Re: Sevilla vs Betis" */
+{
+ /* 1 2 3 4 5 6 7 8 9 */
+/*CT_LIST*/ {2,2,2,2,0,0,2,0,0},
+/*CT_CREATE*/ {1,1,1,1,0,0,1,0,0},
+/*CT_UPDATE*/ {1,1,1,1,0,0,2,0,0},
+/*CT_DELETE*/ {1,1,1,1,0,0,0,0,0},
+/*CT_GET*/ {1,1,1,1,0,0,2,0,0},
+/*CT_FLUSH*/ {0,0,0,0,0,0,0,0,0},
+/*CT_EVENT*/ {2,2,2,2,0,0,2,0,0},
+/*CT_VERSION*/ {0,0,0,0,0,0,0,0,0},
+/*CT_HELP*/ {0,0,0,0,0,0,0,0,0},
+/*EXP_LIST*/ {0,0,0,0,0,0,0,0,0},
+/*EXP_CREATE*/ {1,1,1,1,1,1,0,1,1},
+/*EXP_DELETE*/ {1,1,1,1,0,0,0,0,0},
+/*EXP_GET*/ {1,1,1,1,0,0,0,0,0},
+/*EXP_FLUSH*/ {0,0,0,0,0,0,0,0,0},
+/*EXP_EVENT*/ {0,0,0,0,0,0,0,0,0},
+};
+
static const char *states[] = {
"NONE",
"SYN_SENT",
@@ -58,7 +86,7 @@ static void help()
fprintf(stdout, " --state\t\t\tTCP state, fe. ESTABLISHED\n");
}
-static int parse_options(char c, char *argv[],
+static int parse_options(char c,
struct nf_conntrack *ct,
struct nf_conntrack *exptuple,
struct nf_conntrack *mask,
@@ -139,10 +167,9 @@ static int parse_options(char c, char *argv[],
break;
}
}
- if (i == 10) {
- printf("doh?\n");
- return 0;
- }
+ if (i == 10)
+ exit_error(PARAMETER_PROBLEM,
+ "Unknown TCP state %s\n", optarg);
*flags |= TCP_STATE;
break;
case '8':
@@ -169,12 +196,10 @@ static int parse_options(char c, char *argv[],
return 1;
}
-static int final_check(unsigned int flags,
- unsigned int command,
- struct nf_conntrack *ct)
+static void final_check(unsigned int flags,
+ unsigned int cmd,
+ struct nf_conntrack *ct)
{
- int ret = 0;
-
if ((flags & (TCP_ORIG_SPORT|TCP_ORIG_DPORT))
&& !(flags & (TCP_REPL_SPORT|TCP_REPL_DPORT))) {
nfct_set_attr_u16(ct,
@@ -183,7 +208,8 @@ static int final_check(unsigned int flags,
nfct_set_attr_u16(ct,
ATTR_REPL_PORT_DST,
nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC));
- ret = 1;
+ flags |= TCP_REPL_SPORT;
+ flags |= TCP_REPL_DPORT;
} else if (!(flags & (TCP_ORIG_SPORT|TCP_ORIG_DPORT))
&& (flags & (TCP_REPL_SPORT|TCP_REPL_DPORT))) {
nfct_set_attr_u16(ct,
@@ -192,17 +218,14 @@ static int final_check(unsigned int flags,
nfct_set_attr_u16(ct,
ATTR_ORIG_PORT_DST,
nfct_get_attr_u16(ct, ATTR_REPL_PORT_SRC));
- ret = 1;
+ flags |= TCP_ORIG_SPORT;
+ flags |= TCP_ORIG_DPORT;
}
- if ((flags & (TCP_ORIG_SPORT|TCP_ORIG_DPORT))
- && ((flags & (TCP_REPL_SPORT|TCP_REPL_DPORT))))
- ret = 1;
-
- /* --state is missing and we are trying to create a conntrack */
- if (ret && (command & CT_CREATE) && (!(flags & TCP_STATE)))
- ret = 0;
- return ret;
+ generic_opt_check(flags,
+ TCP_NUMBER_OF_OPT,
+ tcp_commands_v_options[cmd],
+ tcp_optflags);
}
static struct ctproto_handler tcp = {
diff --git a/extensions/libct_proto_udp.c b/extensions/libct_proto_udp.c
index cb131d6..2216b71 100644
--- a/extensions/libct_proto_udp.c
+++ b/extensions/libct_proto_udp.c
@@ -31,6 +31,13 @@ static struct option opts[] = {
{0, 0, 0, 0}
};
+#define UDP_NUMBER_OF_OPT 9
+
+static const char *udp_optflags[UDP_NUMBER_OF_OPT] = {
+"sport", "dport", "reply-port-src", "reply-port-dst", "mask-port-src",
+"mask-port-dst", "tuple-port-src", "tuple-port-dst"
+};
+
static void help()
{
fprintf(stdout, " --orig-port-src\t\toriginal source port\n");
@@ -43,7 +50,28 @@ static void help()
fprintf(stdout, " --tuple-port-src\t\texpectation tuple dst port\n");
}
-static int parse_options(char c, char *argv[],
+static char udp_commands_v_options[NUMBER_OF_CMD][UDP_NUMBER_OF_OPT] =
+/* Well, it's better than "Re: Galeano vs Vargas Llosa" */
+{
+ /* 1 2 3 4 5 6 7 8 */
+/*CT_LIST*/ {2,2,2,2,0,0,0,0},
+/*CT_CREATE*/ {1,1,1,1,0,0,0,0},
+/*CT_UPDATE*/ {1,1,1,1,0,0,0,0},
+/*CT_DELETE*/ {1,1,1,1,0,0,0,0},
+/*CT_GET*/ {1,1,1,1,0,0,0,0},
+/*CT_FLUSH*/ {0,0,0,0,0,0,0,0},
+/*CT_EVENT*/ {2,2,2,2,0,0,0,0},
+/*CT_VERSION*/ {0,0,0,0,0,0,0,0},
+/*CT_HELP*/ {0,0,0,0,0,0,0,0},
+/*EXP_LIST*/ {0,0,0,0,0,0,0,0},
+/*EXP_CREATE*/ {1,1,1,1,1,1,1,1},
+/*EXP_DELETE*/ {1,1,1,1,0,0,0,0},
+/*EXP_GET*/ {1,1,1,1,0,0,0,0},
+/*EXP_FLUSH*/ {0,0,0,0,0,0,0,0},
+/*EXP_EVENT*/ {0,0,0,0,0,0,0,0},
+};
+
+static int parse_options(char c,
struct nf_conntrack *ct,
struct nf_conntrack *exptuple,
struct nf_conntrack *mask,
@@ -134,9 +162,9 @@ static int parse_options(char c, char *argv[],
return 1;
}
-static int final_check(unsigned int flags,
- unsigned int command,
- struct nf_conntrack *ct)
+static void final_check(unsigned int flags,
+ unsigned int cmd,
+ struct nf_conntrack *ct)
{
int ret = 0;
@@ -148,7 +176,8 @@ static int final_check(unsigned int flags,
nfct_set_attr_u16(ct,
ATTR_REPL_PORT_DST,
nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC));
- ret = 1;
+ flags |= UDP_REPL_SPORT;
+ flags |= UDP_REPL_DPORT;
} else if (!(flags & (UDP_ORIG_SPORT|UDP_ORIG_DPORT))
&& (flags & (UDP_REPL_SPORT|UDP_REPL_DPORT))) {
nfct_set_attr_u16(ct,
@@ -157,13 +186,14 @@ static int final_check(unsigned int flags,
nfct_set_attr_u16(ct,
ATTR_ORIG_PORT_DST,
nfct_get_attr_u16(ct, ATTR_REPL_PORT_SRC));
- ret = 1;
+ flags |= UDP_ORIG_SPORT;
+ flags |= UDP_ORIG_DPORT;
}
- if ((flags & (UDP_ORIG_SPORT|UDP_ORIG_DPORT))
- && ((flags & (UDP_REPL_SPORT|UDP_REPL_DPORT))))
- ret = 1;
- return ret;
+ generic_opt_check(flags,
+ UDP_NUMBER_OF_OPT,
+ udp_commands_v_options[cmd],
+ udp_optflags);
}
static struct ctproto_handler udp = {
diff --git a/include/conntrack.h b/include/conntrack.h
index f344d72..5edc0e9 100644
--- a/include/conntrack.h
+++ b/include/conntrack.h
@@ -151,15 +151,15 @@ struct ctproto_handler {
enum ctattr_protoinfo protoinfo_attr;
- int (*parse_opts)(char c, char *argv[],
- struct nf_conntrack *ct,
- struct nf_conntrack *exptuple,
- struct nf_conntrack *mask,
- unsigned int *flags);
+ int (*parse_opts)(char c,
+ struct nf_conntrack *ct,
+ struct nf_conntrack *exptuple,
+ struct nf_conntrack *mask,
+ unsigned int *flags);
- int (*final_check)(unsigned int flags,
- unsigned int command,
- struct nf_conntrack *ct);
+ void (*final_check)(unsigned int flags,
+ unsigned int command,
+ struct nf_conntrack *ct);
void (*help)();
@@ -168,6 +168,18 @@ struct ctproto_handler {
unsigned int option_offset;
};
+enum exittype {
+ OTHER_PROBLEM = 1,
+ PARAMETER_PROBLEM,
+ VERSION_PROBLEM
+};
+
+void generic_opt_check(int options,
+ int nops,
+ char *optset,
+ const char *optflg[]);
+void exit_error(enum exittype status, char *msg, ...);
+
extern void register_proto(struct ctproto_handler *h);
extern void register_tcp(void);
diff --git a/include/mcast.h b/include/mcast.h
index 66676dc..d4fd335 100644
--- a/include/mcast.h
+++ b/include/mcast.h
@@ -2,6 +2,7 @@
#define _MCAST_H_
#include <netinet/in.h>
+#include <net/if.h>
struct mcast_conf {
int ipproto;
@@ -16,6 +17,8 @@ struct mcast_conf {
struct in_addr interface_addr;
struct in6_addr interface_addr6;
} ifa;
+ int mtu;
+ char iface[IFNAMSIZ];
};
struct mcast_stats {
diff --git a/include/network.h b/include/network.h
index bc9431d..f8fdd0d 100644
--- a/include/network.h
+++ b/include/network.h
@@ -55,6 +55,13 @@ int prepare_send_netmsg(struct mcast_sock *m, void *data);
int mcast_send_netmsg(struct mcast_sock *m, void *data);
int mcast_recv_netmsg(struct mcast_sock *m, void *data, int len);
+struct mcast_conf;
+
+int mcast_buffered_init(struct mcast_conf *conf);
+void mcast_buffered_destroy();
+int mcast_buffered_send_netmsg(struct mcast_sock *m, void *data, int len);
+int mcast_buffered_pending_netmsg(struct mcast_sock *m);
+
#define IS_DATA(x) ((x->flags & ~NET_F_HELLO) == 0)
#define IS_ACK(x) (x->flags & NET_F_ACK)
#define IS_NACK(x) (x->flags & NET_F_NACK)
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();
}