From e8c0b55fc1aac2238419cf6119930559d5c3119b Mon Sep 17 00:00:00 2001 From: "/C=DE/ST=Berlin/L=Berlin/O=Netfilter Project/OU=Development/CN=laforge/emailAddress=laforge@netfilter.org" Date: Fri, 24 Jun 2005 16:28:24 +0000 Subject: o Fixed syntax error (tab/space issue) in help message o Fixed getopt handling on big endian machines o Fixed possible future read-over-end-of-array in TCP extension o Add manpage o Add missing space at output of libct_proto_icmp.c o Add status bits that were introduced in 2.6.11 o Add SCTP extension o Add support for expect creation o Bump version number to 0.63 --- AUTHORS | 1 + ChangeLog | 11 +++ configure.in | 2 +- conntrack.8 | 152 ++++++++++++++++++++++++++++++++++++++ extensions/Makefile.am | 4 +- extensions/libct_proto_icmp.c | 2 +- extensions/libct_proto_icmp.man | 10 +++ extensions/libct_proto_sctp.c | 160 ++++++++++++++++++++++++++++++++++++++++ extensions/libct_proto_tcp.c | 18 +++-- extensions/libct_proto_tcp.man | 16 ++++ extensions/libct_proto_udp.man | 13 ++++ src/conntrack.c | 86 +++++++++++++++------ src/libct.c | 25 ++++++- 13 files changed, 468 insertions(+), 32 deletions(-) create mode 100644 conntrack.8 create mode 100644 extensions/libct_proto_icmp.man create mode 100644 extensions/libct_proto_sctp.c create mode 100644 extensions/libct_proto_tcp.man create mode 100644 extensions/libct_proto_udp.man diff --git a/AUTHORS b/AUTHORS index 2cc79e0..d1cb6fa 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1 +1,2 @@ Pablo Neira Ayuso +Harald Welte diff --git a/ChangeLog b/ChangeLog index a1c11e3..688b0cc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2005-05-23 + + o Fixed syntax error (tab/space issue) in help message + o Fixed getopt handling on big endian machines + o Fixed possible future read-over-end-of-array in TCP extension + o Add manpage + o Add missing space at output of libct_proto_icmp.c + o Add status bits that were introduced in 2.6.11 + o Add SCTP extension + o Add support for expect creation + o Bump version number to 0.63 2005-04-25 o Added support for mask based event dumping diff --git a/configure.in b/configure.in index 468e759..efdacf1 100644 --- a/configure.in +++ b/configure.in @@ -2,7 +2,7 @@ AC_INIT AC_CANONICAL_SYSTEM -AM_INIT_AUTOMAKE(conntrack, 0.50) +AM_INIT_AUTOMAKE(conntrack, 0.63) AM_CONFIG_HEADER(config.h) AC_PROG_CC diff --git a/conntrack.8 b/conntrack.8 new file mode 100644 index 0000000..5ba8494 --- /dev/null +++ b/conntrack.8 @@ -0,0 +1,152 @@ +.TH CONNTRACK 8 "Jun 23, 2005" "" "" + +.\" Man page written by Harald Welte . diff --git a/extensions/Makefile.am b/extensions/Makefile.am index ab29a6d..ecd3a91 100644 --- a/extensions/Makefile.am +++ b/extensions/Makefile.am @@ -8,8 +8,10 @@ INCLUDES=-I../include -I/lib/modules/$(shell (uname -r))/build/include CFLAGS=-fPIC -Wall LIBS= -lib_LTLIBRARIES = libct_proto_tcp.la libct_proto_udp.la libct_proto_icmp.la +lib_LTLIBRARIES = libct_proto_tcp.la libct_proto_udp.la libct_proto_icmp.la \ + libct_proto_sctp.la libct_proto_tcp_la_SOURCES = libct_proto_tcp.c libct_proto_udp_la_SOURCES = libct_proto_udp.c libct_proto_icmp_la_SOURCES = libct_proto_icmp.c +libct_proto_sctp_la_SOURCES = libct_proto_sctp.c diff --git a/extensions/libct_proto_icmp.c b/extensions/libct_proto_icmp.c index 43ffa30..6a2db92 100644 --- a/extensions/libct_proto_icmp.c +++ b/extensions/libct_proto_icmp.c @@ -81,7 +81,7 @@ int final_check(unsigned int flags) void print_tuple(struct ip_conntrack_tuple *t) { - fprintf(stdout, "type=%d code=%d id=%d", t->dst.u.icmp.type, + fprintf(stdout, "type=%d code=%d id=%d ", t->dst.u.icmp.type, t->dst.u.icmp.code, t->src.u.icmp.id); } diff --git a/extensions/libct_proto_icmp.man b/extensions/libct_proto_icmp.man new file mode 100644 index 0000000..3b860d0 --- /dev/null +++ b/extensions/libct_proto_icmp.man @@ -0,0 +1,10 @@ +This module matches on ICMP-specific fields. +.TP +.BI "--icmp-type " "TYPE" +ICMP Type. Has to be specified numerically. +.TP +.BI "--icmp-code " "CODE" +ICMP Code. Has to be specified numerically. +.TP +.BI "--icmp-id " "ID" +ICMP Id. Has to be specified numerically. diff --git a/extensions/libct_proto_sctp.c b/extensions/libct_proto_sctp.c new file mode 100644 index 0000000..b84c2ba --- /dev/null +++ b/extensions/libct_proto_sctp.c @@ -0,0 +1,160 @@ +/* + * (C) 2005 by Harald Welte + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License Version 2 as + * published by the Free Software Foundation + * + */ +#include +#include +#include +#include +#include /* For htons */ +#include +#include +#include "libct_proto.h" + +static struct option opts[] = { + {"orig-port-src", 1, 0, '1'}, + {"orig-port-dst", 1, 0, '2'}, + {"reply-port-src", 1, 0, '3'}, + {"reply-port-dst", 1, 0, '4'}, + {"state", 1, 0, '5'}, + {0, 0, 0, 0} +}; + +enum sctp_param_flags { + ORIG_SPORT_BIT = 0, + ORIG_SPORT = (1 << ORIG_SPORT_BIT), + + ORIG_DPORT_BIT = 1, + ORIG_DPORT = (1 << ORIG_DPORT_BIT), + + REPL_SPORT_BIT = 2, + REPL_SPORT = (1 << REPL_SPORT_BIT), + + REPL_DPORT_BIT = 3, + REPL_DPORT = (1 << REPL_DPORT_BIT), + + STATE_BIT = 4, + STATE = (1 << STATE_BIT) +}; + +static const char *states[] = { + "NONE", + "CLOSED", + "COOKIE_WAIT", + "COOKIE_ECHOED", + "ESTABLISHED", + "SHUTDOWN_SENT", + "SHUTDOWN_RECV", + "SHUTDOWN_ACK_SENT", +}; + +static void help() +{ + fprintf(stdout, "--orig-port-src original source port\n"); + fprintf(stdout, "--orig-port-dst original destination port\n"); + fprintf(stdout, "--reply-port-src reply source port\n"); + fprintf(stdout, "--reply-port-dst reply destination port\n"); + fprintf(stdout, "--state SCTP state, eg. ESTABLISHED\n"); +} + +static int parse(char c, char *argv[], + struct ip_conntrack_tuple *orig, + struct ip_conntrack_tuple *reply, + union ip_conntrack_proto *proto, + unsigned int *flags) +{ + switch(c) { + case '1': + if (optarg) { + orig->src.u.sctp.port = htons(atoi(optarg)); + *flags |= ORIG_SPORT; + } + break; + case '2': + if (optarg) { + orig->dst.u.sctp.port = htons(atoi(optarg)); + *flags |= ORIG_DPORT; + } + break; + case '3': + if (optarg) { + reply->src.u.sctp.port = htons(atoi(optarg)); + *flags |= REPL_SPORT; + } + break; + case '4': + if (optarg) { + reply->dst.u.sctp.port = htons(atoi(optarg)); + *flags |= REPL_DPORT; + } + break; + case '5': + if (optarg) { + int i; + for (i=0; i<10; i++) { + if (strcmp(optarg, states[i]) == 0) { + proto->sctp.state = i; + break; + } + } + if (i == 10) { + printf("doh?\n"); + return 0; + } + } + break; + } + return 1; +} + +static int final_check(unsigned int flags) +{ + if ((flags & ORIG_SPORT) && (flags & ORIG_DPORT)) + return 1; + else if ((flags & REPL_SPORT) && (flags & REPL_DPORT)) + return 1; + + return 0; +} + +static void print_tuple(struct ip_conntrack_tuple *t) +{ + fprintf(stdout, "sport=%d dport=%d ", ntohs(t->src.u.sctp.port), + ntohs(t->dst.u.sctp.port)); +} + +static void print_proto(union ip_conntrack_proto *proto) +{ + if (proto->sctp.state > sizeof(states)/sizeof(char *)) + fprintf(stdout, "[%u] ", proto->sctp.state); + else + fprintf(stdout, "[%s] ", states[proto->sctp.state]); +} + +static struct ctproto_handler sctp = { + .name = "sctp", + .protonum = 132, + .parse = parse, + .print_tuple = print_tuple, + .print_proto = print_proto, + .final_check = final_check, + .help = help, + .opts = opts, +}; + +void __attribute__ ((constructor)) init(void); +void __attribute__ ((destructor)) fini(void); + +void init(void) +{ + register_proto(&sctp); +} + +void fini(void) +{ + unregister_proto(&sctp); +} diff --git a/extensions/libct_proto_tcp.c b/extensions/libct_proto_tcp.c index 4cddf53..45ee29b 100644 --- a/extensions/libct_proto_tcp.c +++ b/extensions/libct_proto_tcp.c @@ -10,6 +10,7 @@ #include #include #include +#include #include /* For htons */ #include #include @@ -54,7 +55,7 @@ static const char *states[] = { "LISTEN" }; -void help() +static void help() { fprintf(stdout, "--orig-port-src original source port\n"); fprintf(stdout, "--orig-port-dst original destination port\n"); @@ -63,7 +64,7 @@ void help() fprintf(stdout, "--state TCP state, fe. ESTABLISHED\n"); } -int parse(char c, char *argv[], +static int parse(char c, char *argv[], struct ip_conntrack_tuple *orig, struct ip_conntrack_tuple *reply, union ip_conntrack_proto *proto, @@ -113,7 +114,7 @@ int parse(char c, char *argv[], return 1; } -int final_check(unsigned int flags) +static int final_check(unsigned int flags) { if ((flags & ORIG_SPORT) && (flags & ORIG_DPORT)) return 1; @@ -123,15 +124,18 @@ int final_check(unsigned int flags) return 0; } -void print_tuple(struct ip_conntrack_tuple *t) +static void print_tuple(struct ip_conntrack_tuple *t) { fprintf(stdout, "sport=%d dport=%d ", ntohs(t->src.u.tcp.port), ntohs(t->dst.u.tcp.port)); } -void print_proto(union ip_conntrack_proto *proto) +static void print_proto(union ip_conntrack_proto *proto) { - fprintf(stdout, "[%s] ", states[proto->tcp.state]); + if (proto->tcp.state > sizeof(states)/sizeof(char *)) + fprintf(stdout, "[%u] ", states[proto->tcp.state]); + else + fprintf(stdout, "[%s] ", states[proto->tcp.state]); } static struct ctproto_handler tcp = { @@ -142,7 +146,7 @@ static struct ctproto_handler tcp = { .print_proto = print_proto, .final_check = final_check, .help = help, - .opts = opts + .opts = opts, }; void __attribute__ ((constructor)) init(void); diff --git a/extensions/libct_proto_tcp.man b/extensions/libct_proto_tcp.man new file mode 100644 index 0000000..41783f8 --- /dev/null +++ b/extensions/libct_proto_tcp.man @@ -0,0 +1,16 @@ +This module matches on TCP-specific fields. +.TP +.BI "--orig-port-src " "PORT" +Source port in original direction +.TP +.BI "--orig-port-dst " "PORT" +Destination port in original direction +.TP +.BI "--reply-port-src " "PORT" +Source port in reply direction +.TP +.BI "--reply-port-dst " "PORT" +Destination port in reply direction +.TP +.BI "--state " "[NONE|SYN_SENT|SYN_RECV|ESTABLISHED|FIN_WAIT|CLOSE_WAIT|LAST_ACK|TIME_WAIT|CLOSE|LISTEN]" +TCP state diff --git a/extensions/libct_proto_udp.man b/extensions/libct_proto_udp.man new file mode 100644 index 0000000..c67fedf --- /dev/null +++ b/extensions/libct_proto_udp.man @@ -0,0 +1,13 @@ +This module matches on UDP-specific fields. +.TP +.BI "--orig-port-src " "PORT" +Source port in original direction +.TP +.BI "--orig-port-dst " "PORT" +Destination port in original direction +.TP +.BI "--reply-port-src " "PORT" +Source port in reply direction +.TP +.BI "--reply-port-dst " "PORT" +Destination port in reply direction diff --git a/src/conntrack.c b/src/conntrack.c index 11a6b54..dfedf68 100644 --- a/src/conntrack.c +++ b/src/conntrack.c @@ -25,6 +25,8 @@ * * 2005-04-16 Harald Welte : * Add support for conntrack accounting and conntrack mark + * 2005-06-23 Harald Welte : + * Add support for expect creation * */ #include @@ -47,7 +49,7 @@ #include "libct_proto.h" #define PROGNAME "conntrack" -#define VERSION "0.62" +#define VERSION "0.63" #if 0 #define DEBUGP printf @@ -127,11 +129,22 @@ enum options { CT_OPT_EVENT_MASK_BIT = 10, CT_OPT_EVENT_MASK = (1 << CT_OPT_EVENT_MASK_BIT), + CT_OPT_TUPLE_SRC_BIT = 11, + CT_OPT_TUPLE_SRC = (1 << CT_OPT_TUPLE_SRC_BIT), + + CT_OPT_TUPLE_DST_BIT = 12, + CT_OPT_TUPLE_DST = (1 << CT_OPT_TUPLE_DST_BIT), + + CT_OPT_MASK_SRC_BIT = 13, + CT_OPT_MASK_SRC = (1 << CT_OPT_MASK_SRC_BIT), + + CT_OPT_MASK_DST_BIT = 14, + CT_OPT_MASK_DST = (1 << CT_OPT_MASK_DST_BIT), }; -#define NUMBER_OF_OPT 11 +#define NUMBER_OF_OPT 15 static const char optflags[NUMBER_OF_OPT] -= { 's', 'd', 'r', 'q', 'p', 't', 'u', 'z','m','g','e'}; += { 's', 'd', 'r', 'q', 'p', 't', 'u', 'z','m','g','e', '[',']','{','}'}; static struct option original_opts[] = { {"dump", 2, 0, 'L'}, @@ -154,6 +167,10 @@ static struct option original_opts[] = { {"dump-mask", 1, 0, 'm'}, {"groups", 1, 0, 'g'}, {"event-mask", 1, 0, 'e'}, + {"tuple-src", 1, 0, '['}, + {"tuple-dst", 1, 0, ']'}, + {"mask-src", 1, 0, '{'}, + {"mask-dst", 1, 0, '}'}, {0, 0, 0, 0} }; @@ -174,16 +191,16 @@ static unsigned int global_option_offset = 0; static char commands_v_options[NUMBER_OF_CMD][NUMBER_OF_OPT] = /* Well, it's better than "Re: Linux vs FreeBSD" */ { - /* -s -d -r -q -p -t -u -z -m -g -e */ -/*LIST*/ {'x','x','x','x','x','x','x',' ','x','x','x'}, -/*CREATE*/ {'+','+','+','+','+','+','+','x','x','x','x'}, -/*DELETE*/ {' ',' ',' ',' ',' ','x','x','x','x','x','x'}, -/*GET*/ {' ',' ',' ',' ','+','x','x','x','x','x','x'}, -/*FLUSH*/ {'x','x','x','x','x','x','x','x','x','x','x'}, -/*EVENT*/ {'x','x','x','x','x','x','x','x','x',' ','x'}, -/*ACTION*/ {'x','x','x','x','x','x','x','x',' ','x',' '}, -/*VERSION*/ {'x','x','x','x','x','x','x','x','x','x','x'}, -/*HELP*/ {'x','x','x','x',' ','x','x','x','x','x','x'}, + /* -s -d -r -q -p -t -u -z -m -g -e ts td ms md */ +/*LIST*/ {'x','x','x','x','x','x','x',' ','x','x','x','x','x','x','x'}, +/*CREATE*/ {'+','+','+','+','+','+','+','x','x','x','x','+','+','+','+'}, +/*DELETE*/ {' ',' ',' ',' ',' ','x','x','x','x','x','x',' ',' ',' ',' '}, +/*GET*/ {' ',' ',' ',' ','+','x','x','x','x','x','x',' ',' ',' ',' '}, +/*FLUSH*/ {'x','x','x','x','x','x','x','x','x','x','x','x','x','x','x'}, +/*EVENT*/ {'x','x','x','x','x','x','x','x','x',' ','x','x','x','x','x'}, +/*ACTION*/ {'x','x','x','x','x','x','x','x',' ','x',' ','x','x','x','x'}, +/*VERSION*/ {'x','x','x','x','x','x','x','x','x','x','x','x','x','x','x'}, +/*HELP*/ {'x','x','x','x',' ','x','x','x','x','x','x','x','x','x','x'}, }; /* FIXME: hardcoded!, this must be defined during compilation time */ @@ -355,9 +372,11 @@ static struct parse_parameter { size_t size; unsigned int value[10]; } parse_array[PARSE_MAX] = { - { {"ASSURED", "SEEN_REPLY", "UNSET"}, - 3, - { IPS_ASSURED, IPS_SEEN_REPLY, 0} }, + { {"EXPECTED", "ASSURED", "SEEN_REPLY", "CONFIRMED", "SNAT", "DNAT", + "SEQ_ADJUST", "UNSET"}, + 8, + { IPS_EXPECTED, IPS_ASSURED, IPS_SEEN_REPLY, IPS_CONFIRMED, + IPS_SRC_NAT, IPS_DST_NAT, IPS_SEQ_ADJUST, 0} }, { {"ALL", "TCP", "UDP", "ICMP"}, 4, {~0U, NFGRP_IPV4_CT_TCP, NFGRP_IPV4_CT_UDP, NFGRP_IPV4_CT_ICMP} }, @@ -502,7 +521,7 @@ fprintf(stdout, "Usage: %s [commands] [options]\n", prog); fprintf(stdout, "\n"); fprintf(stdout, "Commands:\n"); fprintf(stdout, "-L [table] [-z] List conntrack or expectation table\n"); -fprintf(stdout, "-G [table] parameters Get conntrack or expectation\n"); +fprintf(stdout, "-G [table] parameters Get conntrack or expectation\n"); fprintf(stdout, "-D [table] parameters Delete conntrack or expectation\n"); fprintf(stdout, "-I [table] parameters Create a conntrack or expectation\n"); fprintf(stdout, "-E [table] [options] Show events\n"); @@ -514,6 +533,10 @@ fprintf(stdout, "--orig-src ip Source address from original direction\n"); fprintf(stdout, "--orig-dst ip Destination address from original direction\n"); fprintf(stdout, "--reply-src ip Source addres from reply direction\n"); fprintf(stdout, "--reply-dst ip Destination address from reply direction\n"); +fprintf(stdout, "--tuple-src ip Source address in expect tuple\n"); +fprintf(stdout, "--tuple-dst ip Destination address in expect tuple\n"); +fprintf(stdout, "--mask-src ip Source mask in expect\n"); +fprintf(stdout, "--mask-dst ip Destination mask in expect\n"); fprintf(stdout, "-p proto Layer 4 Protocol\n"); fprintf(stdout, "-t timeout Set timeout\n"); fprintf(stdout, "-u status Set status\n"); @@ -525,9 +548,9 @@ fprintf(stdout, "-z Zero Counters\n"); int main(int argc, char *argv[]) { - char c; + int c; unsigned int command = 0, options = 0; - struct ip_conntrack_tuple orig, reply, *o = NULL, *r = NULL; + struct ip_conntrack_tuple orig, reply, tuple, mask, *o = NULL, *r = NULL; struct ctproto_handler *h = NULL; union ip_conntrack_proto proto; unsigned long timeout = 0; @@ -543,7 +566,7 @@ int main(int argc, char *argv[]) reply.dst.dir = IP_CT_DIR_REPLY; while ((c = getopt_long(argc, argv, - "L::I::D::G::E::A::F::hVs:d:r:q:p:t:u:m:g:e:z", + "L::I::D::G::E::A::F::hVs:d:r:q:p:t:u:m:g:e:z[:]:{:}:", opts, NULL)) != -1) { switch(c) { case 'L': @@ -644,6 +667,26 @@ int main(int argc, char *argv[]) case 'z': options |= CT_OPT_ZERO; break; + case '[': + options |= CT_OPT_TUPLE_SRC; + if (optarg) + tuple.src.ip = inet_addr(optarg); + break; + case ']': + options |= CT_OPT_TUPLE_DST; + if (optarg) + tuple.dst.ip = inet_addr(optarg); + break; + case '{': + options |= CT_OPT_MASK_SRC; + if (optarg) + mask.src.ip = inet_addr(optarg); + break; + case '}': + options |= CT_OPT_MASK_DST; + if (optarg) + mask.dst.ip = inet_addr(optarg); + break; default: if (h && h->parse && !h->parse(c - h->option_offset, argv, &orig, &reply, @@ -687,7 +730,8 @@ int main(int argc, char *argv[]) res = create_conntrack(&orig, &reply, timeout, &proto, status); else - not_implemented_yet(); + res = create_expect(&tuple, &mask, &orig, + &reply, timeout); break; case CT_DELETE: diff --git a/src/libct.c b/src/libct.c index d40c7f1..0555ec8 100644 --- a/src/libct.c +++ b/src/libct.c @@ -1,5 +1,6 @@ /* - * (C) 2005 by Pablo Neira Ayuso + * (C) 2005 by Pablo Neira Ayuso , + * Harald Welte * * 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 @@ -233,6 +234,28 @@ int create_conntrack(struct ip_conntrack_tuple *orig, return 0; } +int create_expect(struct ip_conntrack_tuple *tuple, + struct ip_conntrack_tuple *mask, + struct ip_conntrack_tuple *master_tuple_orig, + struct ip_conntrack_tuple *master_tuple_reply, + unsigned long timeout) +{ + struct ctnl_handle cth; + int ret; + + if ((ret = ctnl_open(&cth, 0)) < 0) + return ret; + + if ((ret = ctnl_new_expect(&cth, tuple, mask, master_tuple_orig, + master_tuple_reply, timeout)) < 0) + return ret; + + if ((ret = ctnl_close(&cth)) < 0) + return ret; + + return -1; +} + int delete_conntrack(struct ip_conntrack_tuple *tuple, enum ctattr_type_t t) { -- cgit v1.2.3