Login | Register For Free | Help
Search for: (Advanced)

Mailing List Archive: iptables: Devel

[PATCH 28/43] Unifies libip[6]t_tcp.c into libxt_tcp.c.

 

 

iptables devel RSS feed   Index | Next | Previous | View Threaded


yasuyuki.kozakai at toshiba

Jul 14, 2007, 11:11 AM

Post #1 of 9 (1459 views)
Permalink
[PATCH 28/43] Unifies libip[6]t_tcp.c into libxt_tcp.c.

Note: libipt_tcp handled '--syn' as '--flags SYN,RST,ACK,FIN SYN', but
libip6t_tcp handled it as '--flags SYN,RST,ACK SYN'. I keep this
difference for now.

---
extensions/Makefile | 6 +-
extensions/libip6t_tcp.c | 416 -----------------------------------------
extensions/libipt_tcp.c | 416 -----------------------------------------
extensions/libxt_tcp.c | 458 ++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 461 insertions(+), 835 deletions(-)
delete mode 100644 extensions/libip6t_tcp.c
delete mode 100644 extensions/libipt_tcp.c
create mode 100644 extensions/libxt_tcp.c

diff --git a/extensions/Makefile b/extensions/Makefile
index b0df81c..d57fabe 100644
--- a/extensions/Makefile
+++ b/extensions/Makefile
@@ -5,9 +5,9 @@
# header files are present in the include/linux directory of this iptables
# package (HW)
#
-PF_EXT_SLIB:=ah addrtype comment connlimit connmark conntrack dscp ecn esp hashlimit helper icmp iprange length limit mac owner physdev pkttype policy realm sctp standard state tcp tos ttl unclean CLASSIFY CONNMARK DNAT DSCP ECN LOG MARK MASQUERADE MIRROR NETMAP NFQUEUE REDIRECT REJECT SAME SNAT TCPMSS TOS TTL TRACE ULOG
-PF6_EXT_SLIB:=connlimit connmark eui64 hl icmp6 length limit mac owner physdev policy standard state tcp CONNMARK HL LOG NFQUEUE MARK TCPMSS TRACE
-PFX_EXT_SLIB:=mark multiport tcpmss udp NOTRACK
+PF_EXT_SLIB:=ah addrtype comment connlimit connmark conntrack dscp ecn esp hashlimit helper icmp iprange length limit mac owner physdev pkttype policy realm sctp standard state tos ttl unclean CLASSIFY CONNMARK DNAT DSCP ECN LOG MARK MASQUERADE MIRROR NETMAP NFQUEUE REDIRECT REJECT SAME SNAT TCPMSS TOS TTL TRACE ULOG
+PF6_EXT_SLIB:=connlimit connmark eui64 hl icmp6 length limit mac owner physdev policy standard state CONNMARK HL LOG NFQUEUE MARK TCPMSS TRACE
+PFX_EXT_SLIB:=mark multiport tcp tcpmss udp NOTRACK

ifeq ($(DO_SELINUX), 1)
PF_EXT_SE_SLIB:=SECMARK CONNSECMARK
diff --git a/extensions/libip6t_tcp.c b/extensions/libip6t_tcp.c
deleted file mode 100644
index 15f240e..0000000
--- a/extensions/libip6t_tcp.c
+++ /dev/null
@@ -1,416 +0,0 @@
-/* Shared library add-on to iptables to add TCP support. */
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <ip6tables.h>
-#include <linux/netfilter_ipv6/ip6_tables.h>
-
-/* Function which prints out usage message. */
-static void
-help(void)
-{
- printf(
-"TCP v%s options:\n"
-" --tcp-flags [!] mask comp match when TCP flags & mask == comp\n"
-" (Flags: SYN ACK FIN RST URG PSH ALL NONE)\n"
-"[!] --syn match when only SYN flag set\n"
-" (equivalent to --tcp-flags SYN,RST,ACK SYN)\n"
-" --source-port [!] port[:port]\n"
-" --sport ...\n"
-" match source port(s)\n"
-" --destination-port [!] port[:port]\n"
-" --dport ...\n"
-" match destination port(s)\n"
-" --tcp-option [!] number match if TCP option set\n\n",
-IPTABLES_VERSION);
-}
-
-static struct option opts[] = {
- { "source-port", 1, 0, '1' },
- { "sport", 1, 0, '1' }, /* synonym */
- { "destination-port", 1, 0, '2' },
- { "dport", 1, 0, '2' }, /* synonym */
- { "syn", 0, 0, '3' },
- { "tcp-flags", 1, 0, '4' },
- { "tcp-option", 1, 0, '5' },
- {0}
-};
-
-static void
-parse_tcp_ports(const char *portstring, u_int16_t *ports)
-{
- char *buffer;
- char *cp;
-
- buffer = strdup(portstring);
- if ((cp = strchr(buffer, ':')) == NULL)
- ports[0] = ports[1] = parse_port(buffer, "tcp");
- else {
- *cp = '\0';
- cp++;
-
- ports[0] = buffer[0] ? parse_port(buffer, "tcp") : 0;
- ports[1] = cp[0] ? parse_port(cp, "tcp") : 0xFFFF;
-
- if (ports[0] > ports[1])
- exit_error(PARAMETER_PROBLEM,
- "invalid portrange (min > max)");
- }
- free(buffer);
-}
-
-struct tcp_flag_names {
- const char *name;
- unsigned int flag;
-};
-
-static struct tcp_flag_names tcp_flag_names[]
-= { { "FIN", 0x01 },
- { "SYN", 0x02 },
- { "RST", 0x04 },
- { "PSH", 0x08 },
- { "ACK", 0x10 },
- { "URG", 0x20 },
- { "ALL", 0x3F },
- { "NONE", 0 },
-};
-
-static unsigned int
-parse_tcp_flag(const char *flags)
-{
- unsigned int ret = 0;
- char *ptr;
- char *buffer;
-
- buffer = strdup(flags);
-
- for (ptr = strtok(buffer, ","); ptr; ptr = strtok(NULL, ",")) {
- unsigned int i;
- for (i = 0;
- i < sizeof(tcp_flag_names)/sizeof(struct tcp_flag_names);
- i++) {
- if (strcasecmp(tcp_flag_names[i].name, ptr) == 0) {
- ret |= tcp_flag_names[i].flag;
- break;
- }
- }
- if (i == sizeof(tcp_flag_names)/sizeof(struct tcp_flag_names))
- exit_error(PARAMETER_PROBLEM,
- "Unknown TCP flag `%s'", ptr);
- }
-
- free(buffer);
- return ret;
-}
-
-static void
-parse_tcp_flags(struct ip6t_tcp *tcpinfo,
- const char *mask,
- const char *cmp,
- int invert)
-{
- tcpinfo->flg_mask = parse_tcp_flag(mask);
- tcpinfo->flg_cmp = parse_tcp_flag(cmp);
-
- if (invert)
- tcpinfo->invflags |= IP6T_TCP_INV_FLAGS;
-}
-
-static void
-parse_tcp_option(const char *option, u_int8_t *result)
-{
- unsigned int ret;
-
- if (string_to_number(option, 1, 255, &ret) == -1)
- exit_error(PARAMETER_PROBLEM, "Bad TCP option `%s'", option);
-
- *result = (u_int8_t)ret;
-}
-
-/* Initialize the match. */
-static void
-init(struct xt_entry_match *m, unsigned int *nfcache)
-{
- struct ip6t_tcp *tcpinfo = (struct ip6t_tcp *)m->data;
-
- tcpinfo->spts[1] = tcpinfo->dpts[1] = 0xFFFF;
-}
-
-#define TCP_SRC_PORTS 0x01
-#define TCP_DST_PORTS 0x02
-#define TCP_FLAGS 0x04
-#define TCP_OPTION 0x08
-
-/* Function which parses command options; returns true if it
- ate an option. */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry,
- unsigned int *nfcache,
- struct xt_entry_match **match)
-{
- struct ip6t_tcp *tcpinfo = (struct ip6t_tcp *)(*match)->data;
-
- switch (c) {
- case '1':
- if (*flags & TCP_SRC_PORTS)
- exit_error(PARAMETER_PROBLEM,
- "Only one `--source-port' allowed");
- check_inverse(optarg, &invert, &optind, 0);
- parse_tcp_ports(argv[optind-1], tcpinfo->spts);
- if (invert)
- tcpinfo->invflags |= IP6T_TCP_INV_SRCPT;
- *flags |= TCP_SRC_PORTS;
- break;
-
- case '2':
- if (*flags & TCP_DST_PORTS)
- exit_error(PARAMETER_PROBLEM,
- "Only one `--destination-port' allowed");
- check_inverse(optarg, &invert, &optind, 0);
- parse_tcp_ports(argv[optind-1], tcpinfo->dpts);
- if (invert)
- tcpinfo->invflags |= IP6T_TCP_INV_DSTPT;
- *flags |= TCP_DST_PORTS;
- break;
-
- case '3':
- if (*flags & TCP_FLAGS)
- exit_error(PARAMETER_PROBLEM,
- "Only one of `--syn' or `--tcp-flags' "
- " allowed");
- parse_tcp_flags(tcpinfo, "SYN,RST,ACK", "SYN", invert);
- *flags |= TCP_FLAGS;
- break;
-
- case '4':
- if (*flags & TCP_FLAGS)
- exit_error(PARAMETER_PROBLEM,
- "Only one of `--syn' or `--tcp-flags' "
- " allowed");
- check_inverse(optarg, &invert, &optind, 0);
-
- if (!argv[optind]
- || argv[optind][0] == '-' || argv[optind][0] == '!')
- exit_error(PARAMETER_PROBLEM,
- "--tcp-flags requires two args.");
-
- parse_tcp_flags(tcpinfo, argv[optind-1], argv[optind],
- invert);
- optind++;
- *flags |= TCP_FLAGS;
- break;
-
- case '5':
- if (*flags & TCP_OPTION)
- exit_error(PARAMETER_PROBLEM,
- "Only one `--tcp-option' allowed");
- check_inverse(optarg, &invert, &optind, 0);
- parse_tcp_option(argv[optind-1], &tcpinfo->option);
- if (invert)
- tcpinfo->invflags |= IP6T_TCP_INV_OPTION;
- *flags |= TCP_OPTION;
- break;
-
- default:
- return 0;
- }
-
- return 1;
-}
-
-/* Final check; we don't care. */
-static void
-final_check(unsigned int flags)
-{
-}
-
-static char *
-port_to_service(int port)
-{
- struct servent *service;
-
- if ((service = getservbyport(htons(port), "tcp")))
- return service->s_name;
-
- return NULL;
-}
-
-static void
-print_port(u_int16_t port, int numeric)
-{
- char *service;
-
- if (numeric || (service = port_to_service(port)) == NULL)
- printf("%u", port);
- else
- printf("%s", service);
-}
-
-static void
-print_ports(const char *name, u_int16_t min, u_int16_t max,
- int invert, int numeric)
-{
- const char *inv = invert ? "!" : "";
-
- if (min != 0 || max != 0xFFFF || invert) {
- printf("%s", name);
- if (min == max) {
- printf(":%s", inv);
- print_port(min, numeric);
- } else {
- printf("s:%s", inv);
- print_port(min, numeric);
- printf(":");
- print_port(max, numeric);
- }
- printf(" ");
- }
-}
-
-static void
-print_option(u_int8_t option, int invert, int numeric)
-{
- if (option || invert)
- printf("option=%s%u ", invert ? "!" : "", option);
-}
-
-static void
-print_tcpf(u_int8_t flags)
-{
- int have_flag = 0;
-
- while (flags) {
- unsigned int i;
-
- for (i = 0; (flags & tcp_flag_names[i].flag) == 0; i++);
-
- if (have_flag)
- printf(",");
- printf("%s", tcp_flag_names[i].name);
- have_flag = 1;
-
- flags &= ~tcp_flag_names[i].flag;
- }
-
- if (!have_flag)
- printf("NONE");
-}
-
-static void
-print_flags(u_int8_t mask, u_int8_t cmp, int invert, int numeric)
-{
- if (mask || invert) {
- printf("flags:%s", invert ? "!" : "");
- if (numeric)
- printf("0x%02X/0x%02X ", mask, cmp);
- else {
- print_tcpf(mask);
- printf("/");
- print_tcpf(cmp);
- printf(" ");
- }
- }
-}
-
-/* Prints out the union ipt_matchinfo. */
-static void
-print(const void *ip,
- const struct xt_entry_match *match, int numeric)
-{
- const struct ip6t_tcp *tcp = (struct ip6t_tcp *)match->data;
-
- printf("tcp ");
- print_ports("spt", tcp->spts[0], tcp->spts[1],
- tcp->invflags & IP6T_TCP_INV_SRCPT,
- numeric);
- print_ports("dpt", tcp->dpts[0], tcp->dpts[1],
- tcp->invflags & IP6T_TCP_INV_DSTPT,
- numeric);
- print_option(tcp->option,
- tcp->invflags & IP6T_TCP_INV_OPTION,
- numeric);
- print_flags(tcp->flg_mask, tcp->flg_cmp,
- tcp->invflags & IP6T_TCP_INV_FLAGS,
- numeric);
- if (tcp->invflags & ~IP6T_TCP_INV_MASK)
- printf("Unknown invflags: 0x%X ",
- tcp->invflags & ~IP6T_TCP_INV_MASK);
-}
-
-/* Saves the union ipt_matchinfo in parsable form to stdout. */
-static void save(const void *ip, const struct xt_entry_match *match)
-{
- const struct ip6t_tcp *tcpinfo = (struct ip6t_tcp *)match->data;
-
- if (tcpinfo->spts[0] != 0
- || tcpinfo->spts[1] != 0xFFFF) {
- if (tcpinfo->invflags & IP6T_TCP_INV_SRCPT)
- printf("! ");
- if (tcpinfo->spts[0]
- != tcpinfo->spts[1])
- printf("--sport %u:%u ",
- tcpinfo->spts[0],
- tcpinfo->spts[1]);
- else
- printf("--sport %u ",
- tcpinfo->spts[0]);
- }
-
- if (tcpinfo->dpts[0] != 0
- || tcpinfo->dpts[1] != 0xFFFF) {
- if (tcpinfo->invflags & IP6T_TCP_INV_DSTPT)
- printf("! ");
- if (tcpinfo->dpts[0]
- != tcpinfo->dpts[1])
- printf("--dport %u:%u ",
- tcpinfo->dpts[0],
- tcpinfo->dpts[1]);
- else
- printf("--dport %u ",
- tcpinfo->dpts[0]);
- }
-
- if (tcpinfo->option
- || (tcpinfo->invflags & IP6T_TCP_INV_OPTION)) {
- if (tcpinfo->invflags & IP6T_TCP_INV_OPTION)
- printf("! ");
- printf("--tcp-option %u ", tcpinfo->option);
- }
-
- if (tcpinfo->flg_mask
- || (tcpinfo->invflags & IP6T_TCP_INV_FLAGS)) {
- if (tcpinfo->invflags & IP6T_TCP_INV_FLAGS)
- printf("! ");
-
- printf("--tcp-flags ");
- if (tcpinfo->flg_mask != 0xFF) {
- print_tcpf(tcpinfo->flg_mask);
- }
- printf(" ");
- print_tcpf(tcpinfo->flg_cmp);
- printf(" ");
- }
-}
-
-static struct ip6tables_match tcp = {
- .name = "tcp",
- .version = IPTABLES_VERSION,
- .size = IP6T_ALIGN(sizeof(struct ip6t_tcp)),
- .userspacesize = IP6T_ALIGN(sizeof(struct ip6t_tcp)),
- .help = &help,
- .init = &init,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts,
-};
-
-void
-_init(void)
-{
- register_match6(&tcp);
-}
diff --git a/extensions/libipt_tcp.c b/extensions/libipt_tcp.c
deleted file mode 100644
index 287b00f..0000000
--- a/extensions/libipt_tcp.c
+++ /dev/null
@@ -1,416 +0,0 @@
-/* Shared library add-on to iptables to add TCP support. */
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <iptables.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-
-/* Function which prints out usage message. */
-static void
-help(void)
-{
- printf(
-"TCP v%s options:\n"
-" --tcp-flags [!] mask comp match when TCP flags & mask == comp\n"
-" (Flags: SYN ACK FIN RST URG PSH ALL NONE)\n"
-"[!] --syn match when only SYN flag set\n"
-" (equivalent to --tcp-flags SYN,RST,ACK SYN)\n"
-" --source-port [!] port[:port]\n"
-" --sport ...\n"
-" match source port(s)\n"
-" --destination-port [!] port[:port]\n"
-" --dport ...\n"
-" match destination port(s)\n"
-" --tcp-option [!] number match if TCP option set\n\n",
-IPTABLES_VERSION);
-}
-
-static struct option opts[] = {
- { "source-port", 1, 0, '1' },
- { "sport", 1, 0, '1' }, /* synonym */
- { "destination-port", 1, 0, '2' },
- { "dport", 1, 0, '2' }, /* synonym */
- { "syn", 0, 0, '3' },
- { "tcp-flags", 1, 0, '4' },
- { "tcp-option", 1, 0, '5' },
- {0}
-};
-
-static void
-parse_tcp_ports(const char *portstring, u_int16_t *ports)
-{
- char *buffer;
- char *cp;
-
- buffer = strdup(portstring);
- if ((cp = strchr(buffer, ':')) == NULL)
- ports[0] = ports[1] = parse_port(buffer, "tcp");
- else {
- *cp = '\0';
- cp++;
-
- ports[0] = buffer[0] ? parse_port(buffer, "tcp") : 0;
- ports[1] = cp[0] ? parse_port(cp, "tcp") : 0xFFFF;
-
- if (ports[0] > ports[1])
- exit_error(PARAMETER_PROBLEM,
- "invalid portrange (min > max)");
- }
- free(buffer);
-}
-
-struct tcp_flag_names {
- const char *name;
- unsigned int flag;
-};
-
-static struct tcp_flag_names tcp_flag_names[]
-= { { "FIN", 0x01 },
- { "SYN", 0x02 },
- { "RST", 0x04 },
- { "PSH", 0x08 },
- { "ACK", 0x10 },
- { "URG", 0x20 },
- { "ALL", 0x3F },
- { "NONE", 0 },
-};
-
-static unsigned int
-parse_tcp_flag(const char *flags)
-{
- unsigned int ret = 0;
- char *ptr;
- char *buffer;
-
- buffer = strdup(flags);
-
- for (ptr = strtok(buffer, ","); ptr; ptr = strtok(NULL, ",")) {
- unsigned int i;
- for (i = 0;
- i < sizeof(tcp_flag_names)/sizeof(struct tcp_flag_names);
- i++) {
- if (strcasecmp(tcp_flag_names[i].name, ptr) == 0) {
- ret |= tcp_flag_names[i].flag;
- break;
- }
- }
- if (i == sizeof(tcp_flag_names)/sizeof(struct tcp_flag_names))
- exit_error(PARAMETER_PROBLEM,
- "Unknown TCP flag `%s'", ptr);
- }
-
- free(buffer);
- return ret;
-}
-
-static void
-parse_tcp_flags(struct ipt_tcp *tcpinfo,
- const char *mask,
- const char *cmp,
- int invert)
-{
- tcpinfo->flg_mask = parse_tcp_flag(mask);
- tcpinfo->flg_cmp = parse_tcp_flag(cmp);
-
- if (invert)
- tcpinfo->invflags |= IPT_TCP_INV_FLAGS;
-}
-
-static void
-parse_tcp_option(const char *option, u_int8_t *result)
-{
- unsigned int ret;
-
- if (string_to_number(option, 1, 255, &ret) == -1)
- exit_error(PARAMETER_PROBLEM, "Bad TCP option `%s'", option);
-
- *result = (u_int8_t)ret;
-}
-
-/* Initialize the match. */
-static void
-init(struct xt_entry_match *m, unsigned int *nfcache)
-{
- struct ipt_tcp *tcpinfo = (struct ipt_tcp *)m->data;
-
- tcpinfo->spts[1] = tcpinfo->dpts[1] = 0xFFFF;
-}
-
-#define TCP_SRC_PORTS 0x01
-#define TCP_DST_PORTS 0x02
-#define TCP_FLAGS 0x04
-#define TCP_OPTION 0x08
-
-/* Function which parses command options; returns true if it
- ate an option. */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const void *entry,
- unsigned int *nfcache,
- struct xt_entry_match **match)
-{
- struct ipt_tcp *tcpinfo = (struct ipt_tcp *)(*match)->data;
-
- switch (c) {
- case '1':
- if (*flags & TCP_SRC_PORTS)
- exit_error(PARAMETER_PROBLEM,
- "Only one `--source-port' allowed");
- check_inverse(optarg, &invert, &optind, 0);
- parse_tcp_ports(argv[optind-1], tcpinfo->spts);
- if (invert)
- tcpinfo->invflags |= IPT_TCP_INV_SRCPT;
- *flags |= TCP_SRC_PORTS;
- break;
-
- case '2':
- if (*flags & TCP_DST_PORTS)
- exit_error(PARAMETER_PROBLEM,
- "Only one `--destination-port' allowed");
- check_inverse(optarg, &invert, &optind, 0);
- parse_tcp_ports(argv[optind-1], tcpinfo->dpts);
- if (invert)
- tcpinfo->invflags |= IPT_TCP_INV_DSTPT;
- *flags |= TCP_DST_PORTS;
- break;
-
- case '3':
- if (*flags & TCP_FLAGS)
- exit_error(PARAMETER_PROBLEM,
- "Only one of `--syn' or `--tcp-flags' "
- " allowed");
- parse_tcp_flags(tcpinfo, "SYN,RST,ACK,FIN", "SYN", invert);
- *flags |= TCP_FLAGS;
- break;
-
- case '4':
- if (*flags & TCP_FLAGS)
- exit_error(PARAMETER_PROBLEM,
- "Only one of `--syn' or `--tcp-flags' "
- " allowed");
- check_inverse(optarg, &invert, &optind, 0);
-
- if (!argv[optind]
- || argv[optind][0] == '-' || argv[optind][0] == '!')
- exit_error(PARAMETER_PROBLEM,
- "--tcp-flags requires two args.");
-
- parse_tcp_flags(tcpinfo, argv[optind-1], argv[optind],
- invert);
- optind++;
- *flags |= TCP_FLAGS;
- break;
-
- case '5':
- if (*flags & TCP_OPTION)
- exit_error(PARAMETER_PROBLEM,
- "Only one `--tcp-option' allowed");
- check_inverse(optarg, &invert, &optind, 0);
- parse_tcp_option(argv[optind-1], &tcpinfo->option);
- if (invert)
- tcpinfo->invflags |= IPT_TCP_INV_OPTION;
- *flags |= TCP_OPTION;
- break;
-
- default:
- return 0;
- }
-
- return 1;
-}
-
-/* Final check; we don't care. */
-static void
-final_check(unsigned int flags)
-{
-}
-
-static char *
-port_to_service(int port)
-{
- struct servent *service;
-
- if ((service = getservbyport(htons(port), "tcp")))
- return service->s_name;
-
- return NULL;
-}
-
-static void
-print_port(u_int16_t port, int numeric)
-{
- char *service;
-
- if (numeric || (service = port_to_service(port)) == NULL)
- printf("%u", port);
- else
- printf("%s", service);
-}
-
-static void
-print_ports(const char *name, u_int16_t min, u_int16_t max,
- int invert, int numeric)
-{
- const char *inv = invert ? "!" : "";
-
- if (min != 0 || max != 0xFFFF || invert) {
- printf("%s", name);
- if (min == max) {
- printf(":%s", inv);
- print_port(min, numeric);
- } else {
- printf("s:%s", inv);
- print_port(min, numeric);
- printf(":");
- print_port(max, numeric);
- }
- printf(" ");
- }
-}
-
-static void
-print_option(u_int8_t option, int invert, int numeric)
-{
- if (option || invert)
- printf("option=%s%u ", invert ? "!" : "", option);
-}
-
-static void
-print_tcpf(u_int8_t flags)
-{
- int have_flag = 0;
-
- while (flags) {
- unsigned int i;
-
- for (i = 0; (flags & tcp_flag_names[i].flag) == 0; i++);
-
- if (have_flag)
- printf(",");
- printf("%s", tcp_flag_names[i].name);
- have_flag = 1;
-
- flags &= ~tcp_flag_names[i].flag;
- }
-
- if (!have_flag)
- printf("NONE");
-}
-
-static void
-print_flags(u_int8_t mask, u_int8_t cmp, int invert, int numeric)
-{
- if (mask || invert) {
- printf("flags:%s", invert ? "!" : "");
- if (numeric)
- printf("0x%02X/0x%02X ", mask, cmp);
- else {
- print_tcpf(mask);
- printf("/");
- print_tcpf(cmp);
- printf(" ");
- }
- }
-}
-
-/* Prints out the union ipt_matchinfo. */
-static void
-print(const void *ip,
- const struct xt_entry_match *match, int numeric)
-{
- const struct ipt_tcp *tcp = (struct ipt_tcp *)match->data;
-
- printf("tcp ");
- print_ports("spt", tcp->spts[0], tcp->spts[1],
- tcp->invflags & IPT_TCP_INV_SRCPT,
- numeric);
- print_ports("dpt", tcp->dpts[0], tcp->dpts[1],
- tcp->invflags & IPT_TCP_INV_DSTPT,
- numeric);
- print_option(tcp->option,
- tcp->invflags & IPT_TCP_INV_OPTION,
- numeric);
- print_flags(tcp->flg_mask, tcp->flg_cmp,
- tcp->invflags & IPT_TCP_INV_FLAGS,
- numeric);
- if (tcp->invflags & ~IPT_TCP_INV_MASK)
- printf("Unknown invflags: 0x%X ",
- tcp->invflags & ~IPT_TCP_INV_MASK);
-}
-
-/* Saves the union ipt_matchinfo in parsable form to stdout. */
-static void save(const void *ip, const struct xt_entry_match *match)
-{
- const struct ipt_tcp *tcpinfo = (struct ipt_tcp *)match->data;
-
- if (tcpinfo->spts[0] != 0
- || tcpinfo->spts[1] != 0xFFFF) {
- if (tcpinfo->invflags & IPT_TCP_INV_SRCPT)
- printf("! ");
- if (tcpinfo->spts[0]
- != tcpinfo->spts[1])
- printf("--sport %u:%u ",
- tcpinfo->spts[0],
- tcpinfo->spts[1]);
- else
- printf("--sport %u ",
- tcpinfo->spts[0]);
- }
-
- if (tcpinfo->dpts[0] != 0
- || tcpinfo->dpts[1] != 0xFFFF) {
- if (tcpinfo->invflags & IPT_TCP_INV_DSTPT)
- printf("! ");
- if (tcpinfo->dpts[0]
- != tcpinfo->dpts[1])
- printf("--dport %u:%u ",
- tcpinfo->dpts[0],
- tcpinfo->dpts[1]);
- else
- printf("--dport %u ",
- tcpinfo->dpts[0]);
- }
-
- if (tcpinfo->option
- || (tcpinfo->invflags & IPT_TCP_INV_OPTION)) {
- if (tcpinfo->invflags & IPT_TCP_INV_OPTION)
- printf("! ");
- printf("--tcp-option %u ", tcpinfo->option);
- }
-
- if (tcpinfo->flg_mask
- || (tcpinfo->invflags & IPT_TCP_INV_FLAGS)) {
- if (tcpinfo->invflags & IPT_TCP_INV_FLAGS)
- printf("! ");
- printf("--tcp-flags ");
- if (tcpinfo->flg_mask != 0xFF) {
- print_tcpf(tcpinfo->flg_mask);
- }
- printf(" ");
- print_tcpf(tcpinfo->flg_cmp);
- printf(" ");
- }
-}
-
-static struct iptables_match tcp = {
- .next = NULL,
- .name = "tcp",
- .version = IPTABLES_VERSION,
- .size = IPT_ALIGN(sizeof(struct ipt_tcp)),
- .userspacesize = IPT_ALIGN(sizeof(struct ipt_tcp)),
- .help = &help,
- .init = &init,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
-};
-
-void
-_init(void)
-{
- register_match(&tcp);
-}
diff --git a/extensions/libxt_tcp.c b/extensions/libxt_tcp.c
new file mode 100644
index 0000000..0d0eed2
--- /dev/null
+++ b/extensions/libxt_tcp.c
@@ -0,0 +1,458 @@
+/* Shared library add-on to iptables to add TCP support. */
+#include <stdio.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <xtables.h>
+#include <linux/netfilter/xt_tcpudp.h>
+
+/* Function which prints out usage message. */
+static void
+help(void)
+{
+ printf(
+"TCP v%s options:\n"
+" --tcp-flags [!] mask comp match when TCP flags & mask == comp\n"
+" (Flags: SYN ACK FIN RST URG PSH ALL NONE)\n"
+"[!] --syn match when only SYN flag set\n"
+" (equivalent to --tcp-flags SYN,RST,ACK SYN)\n"
+" --source-port [!] port[:port]\n"
+" --sport ...\n"
+" match source port(s)\n"
+" --destination-port [!] port[:port]\n"
+" --dport ...\n"
+" match destination port(s)\n"
+" --tcp-option [!] number match if TCP option set\n\n",
+IPTABLES_VERSION);
+}
+
+static struct option opts[] = {
+ { "source-port", 1, 0, '1' },
+ { "sport", 1, 0, '1' }, /* synonym */
+ { "destination-port", 1, 0, '2' },
+ { "dport", 1, 0, '2' }, /* synonym */
+ { "syn", 0, 0, '3' },
+ { "tcp-flags", 1, 0, '4' },
+ { "tcp-option", 1, 0, '5' },
+ {0}
+};
+
+static void
+parse_tcp_ports(const char *portstring, u_int16_t *ports)
+{
+ char *buffer;
+ char *cp;
+
+ buffer = strdup(portstring);
+ if ((cp = strchr(buffer, ':')) == NULL)
+ ports[0] = ports[1] = parse_port(buffer, "tcp");
+ else {
+ *cp = '\0';
+ cp++;
+
+ ports[0] = buffer[0] ? parse_port(buffer, "tcp") : 0;
+ ports[1] = cp[0] ? parse_port(cp, "tcp") : 0xFFFF;
+
+ if (ports[0] > ports[1])
+ exit_error(PARAMETER_PROBLEM,
+ "invalid portrange (min > max)");
+ }
+ free(buffer);
+}
+
+struct tcp_flag_names {
+ const char *name;
+ unsigned int flag;
+};
+
+static struct tcp_flag_names tcp_flag_names[]
+= { { "FIN", 0x01 },
+ { "SYN", 0x02 },
+ { "RST", 0x04 },
+ { "PSH", 0x08 },
+ { "ACK", 0x10 },
+ { "URG", 0x20 },
+ { "ALL", 0x3F },
+ { "NONE", 0 },
+};
+
+static unsigned int
+parse_tcp_flag(const char *flags)
+{
+ unsigned int ret = 0;
+ char *ptr;
+ char *buffer;
+
+ buffer = strdup(flags);
+
+ for (ptr = strtok(buffer, ","); ptr; ptr = strtok(NULL, ",")) {
+ unsigned int i;
+ for (i = 0;
+ i < sizeof(tcp_flag_names)/sizeof(struct tcp_flag_names);
+ i++) {
+ if (strcasecmp(tcp_flag_names[i].name, ptr) == 0) {
+ ret |= tcp_flag_names[i].flag;
+ break;
+ }
+ }
+ if (i == sizeof(tcp_flag_names)/sizeof(struct tcp_flag_names))
+ exit_error(PARAMETER_PROBLEM,
+ "Unknown TCP flag `%s'", ptr);
+ }
+
+ free(buffer);
+ return ret;
+}
+
+static void
+parse_tcp_flags(struct xt_tcp *tcpinfo,
+ const char *mask,
+ const char *cmp,
+ int invert)
+{
+ tcpinfo->flg_mask = parse_tcp_flag(mask);
+ tcpinfo->flg_cmp = parse_tcp_flag(cmp);
+
+ if (invert)
+ tcpinfo->invflags |= XT_TCP_INV_FLAGS;
+}
+
+static void
+parse_tcp_option(const char *option, u_int8_t *result)
+{
+ unsigned int ret;
+
+ if (string_to_number(option, 1, 255, &ret) == -1)
+ exit_error(PARAMETER_PROBLEM, "Bad TCP option `%s'", option);
+
+ *result = (u_int8_t)ret;
+}
+
+/* Initialize the match. */
+static void
+init(struct xt_entry_match *m, unsigned int *nfcache)
+{
+ struct xt_tcp *tcpinfo = (struct xt_tcp *)m->data;
+
+ tcpinfo->spts[1] = tcpinfo->dpts[1] = 0xFFFF;
+}
+
+#define TCP_SRC_PORTS 0x01
+#define TCP_DST_PORTS 0x02
+#define TCP_FLAGS 0x04
+#define TCP_OPTION 0x08
+
+/* Function which parses command options; returns true if it
+ ate an option. */
+static int
+__parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry,
+ unsigned int *nfcache,
+ struct xt_entry_match **match,
+ u_int16_t pf)
+{
+ struct xt_tcp *tcpinfo = (struct xt_tcp *)(*match)->data;
+
+ switch (c) {
+ case '1':
+ if (*flags & TCP_SRC_PORTS)
+ exit_error(PARAMETER_PROBLEM,
+ "Only one `--source-port' allowed");
+ check_inverse(optarg, &invert, &optind, 0);
+ parse_tcp_ports(argv[optind-1], tcpinfo->spts);
+ if (invert)
+ tcpinfo->invflags |= XT_TCP_INV_SRCPT;
+ *flags |= TCP_SRC_PORTS;
+ break;
+
+ case '2':
+ if (*flags & TCP_DST_PORTS)
+ exit_error(PARAMETER_PROBLEM,
+ "Only one `--destination-port' allowed");
+ check_inverse(optarg, &invert, &optind, 0);
+ parse_tcp_ports(argv[optind-1], tcpinfo->dpts);
+ if (invert)
+ tcpinfo->invflags |= XT_TCP_INV_DSTPT;
+ *flags |= TCP_DST_PORTS;
+ break;
+
+ case '3':
+ if (*flags & TCP_FLAGS)
+ exit_error(PARAMETER_PROBLEM,
+ "Only one of `--syn' or `--tcp-flags' "
+ " allowed");
+ if (pf == AF_INET)
+ parse_tcp_flags(tcpinfo, "SYN,RST,ACK,FIN", "SYN",
+ invert);
+ else if (pf == AF_INET6)
+ parse_tcp_flags(tcpinfo, "SYN,RST,ACK", "SYN", invert);
+
+ *flags |= TCP_FLAGS;
+ break;
+
+ case '4':
+ if (*flags & TCP_FLAGS)
+ exit_error(PARAMETER_PROBLEM,
+ "Only one of `--syn' or `--tcp-flags' "
+ " allowed");
+ check_inverse(optarg, &invert, &optind, 0);
+
+ if (!argv[optind]
+ || argv[optind][0] == '-' || argv[optind][0] == '!')
+ exit_error(PARAMETER_PROBLEM,
+ "--tcp-flags requires two args.");
+
+ parse_tcp_flags(tcpinfo, argv[optind-1], argv[optind],
+ invert);
+ optind++;
+ *flags |= TCP_FLAGS;
+ break;
+
+ case '5':
+ if (*flags & TCP_OPTION)
+ exit_error(PARAMETER_PROBLEM,
+ "Only one `--tcp-option' allowed");
+ check_inverse(optarg, &invert, &optind, 0);
+ parse_tcp_option(argv[optind-1], &tcpinfo->option);
+ if (invert)
+ tcpinfo->invflags |= XT_TCP_INV_OPTION;
+ *flags |= TCP_OPTION;
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+static int
+parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry,
+ unsigned int *nfcache,
+ struct xt_entry_match **match)
+{
+ return __parse(c, argv, invert, flags, entry, nfcache, match, AF_INET);
+}
+
+static int
+parse6(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry,
+ unsigned int *nfcache,
+ struct xt_entry_match **match)
+{
+ return __parse(c, argv, invert, flags, entry, nfcache, match, AF_INET6);
+}
+
+/* Final check; we don't care. */
+static void
+final_check(unsigned int flags)
+{
+}
+
+static char *
+port_to_service(int port)
+{
+ struct servent *service;
+
+ if ((service = getservbyport(htons(port), "tcp")))
+ return service->s_name;
+
+ return NULL;
+}
+
+static void
+print_port(u_int16_t port, int numeric)
+{
+ char *service;
+
+ if (numeric || (service = port_to_service(port)) == NULL)
+ printf("%u", port);
+ else
+ printf("%s", service);
+}
+
+static void
+print_ports(const char *name, u_int16_t min, u_int16_t max,
+ int invert, int numeric)
+{
+ const char *inv = invert ? "!" : "";
+
+ if (min != 0 || max != 0xFFFF || invert) {
+ printf("%s", name);
+ if (min == max) {
+ printf(":%s", inv);
+ print_port(min, numeric);
+ } else {
+ printf("s:%s", inv);
+ print_port(min, numeric);
+ printf(":");
+ print_port(max, numeric);
+ }
+ printf(" ");
+ }
+}
+
+static void
+print_option(u_int8_t option, int invert, int numeric)
+{
+ if (option || invert)
+ printf("option=%s%u ", invert ? "!" : "", option);
+}
+
+static void
+print_tcpf(u_int8_t flags)
+{
+ int have_flag = 0;
+
+ while (flags) {
+ unsigned int i;
+
+ for (i = 0; (flags & tcp_flag_names[i].flag) == 0; i++);
+
+ if (have_flag)
+ printf(",");
+ printf("%s", tcp_flag_names[i].name);
+ have_flag = 1;
+
+ flags &= ~tcp_flag_names[i].flag;
+ }
+
+ if (!have_flag)
+ printf("NONE");
+}
+
+static void
+print_flags(u_int8_t mask, u_int8_t cmp, int invert, int numeric)
+{
+ if (mask || invert) {
+ printf("flags:%s", invert ? "!" : "");
+ if (numeric)
+ printf("0x%02X/0x%02X ", mask, cmp);
+ else {
+ print_tcpf(mask);
+ printf("/");
+ print_tcpf(cmp);
+ printf(" ");
+ }
+ }
+}
+
+/* Prints out the union ipt_matchinfo. */
+static void
+print(const void *ip,
+ const struct xt_entry_match *match, int numeric)
+{
+ const struct xt_tcp *tcp = (struct xt_tcp *)match->data;
+
+ printf("tcp ");
+ print_ports("spt", tcp->spts[0], tcp->spts[1],
+ tcp->invflags & XT_TCP_INV_SRCPT,
+ numeric);
+ print_ports("dpt", tcp->dpts[0], tcp->dpts[1],
+ tcp->invflags & XT_TCP_INV_DSTPT,
+ numeric);
+ print_option(tcp->option,
+ tcp->invflags & XT_TCP_INV_OPTION,
+ numeric);
+ print_flags(tcp->flg_mask, tcp->flg_cmp,
+ tcp->invflags & XT_TCP_INV_FLAGS,
+ numeric);
+ if (tcp->invflags & ~XT_TCP_INV_MASK)
+ printf("Unknown invflags: 0x%X ",
+ tcp->invflags & ~XT_TCP_INV_MASK);
+}
+
+/* Saves the union ipt_matchinfo in parsable form to stdout. */
+static void save(const void *ip, const struct xt_entry_match *match)
+{
+ const struct xt_tcp *tcpinfo = (struct xt_tcp *)match->data;
+
+ if (tcpinfo->spts[0] != 0
+ || tcpinfo->spts[1] != 0xFFFF) {
+ if (tcpinfo->invflags & XT_TCP_INV_SRCPT)
+ printf("! ");
+ if (tcpinfo->spts[0]
+ != tcpinfo->spts[1])
+ printf("--sport %u:%u ",
+ tcpinfo->spts[0],
+ tcpinfo->spts[1]);
+ else
+ printf("--sport %u ",
+ tcpinfo->spts[0]);
+ }
+
+ if (tcpinfo->dpts[0] != 0
+ || tcpinfo->dpts[1] != 0xFFFF) {
+ if (tcpinfo->invflags & XT_TCP_INV_DSTPT)
+ printf("! ");
+ if (tcpinfo->dpts[0]
+ != tcpinfo->dpts[1])
+ printf("--dport %u:%u ",
+ tcpinfo->dpts[0],
+ tcpinfo->dpts[1]);
+ else
+ printf("--dport %u ",
+ tcpinfo->dpts[0]);
+ }
+
+ if (tcpinfo->option
+ || (tcpinfo->invflags & XT_TCP_INV_OPTION)) {
+ if (tcpinfo->invflags & XT_TCP_INV_OPTION)
+ printf("! ");
+ printf("--tcp-option %u ", tcpinfo->option);
+ }
+
+ if (tcpinfo->flg_mask
+ || (tcpinfo->invflags & XT_TCP_INV_FLAGS)) {
+ if (tcpinfo->invflags & XT_TCP_INV_FLAGS)
+ printf("! ");
+ printf("--tcp-flags ");
+ if (tcpinfo->flg_mask != 0xFF) {
+ print_tcpf(tcpinfo->flg_mask);
+ }
+ printf(" ");
+ print_tcpf(tcpinfo->flg_cmp);
+ printf(" ");
+ }
+}
+
+static struct xtables_match tcp = {
+ .next = NULL,
+ .family = AF_INET,
+ .name = "tcp",
+ .version = IPTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_tcp)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_tcp)),
+ .help = &help,
+ .init = &init,
+ .parse = &parse,
+ .final_check = &final_check,
+ .print = &print,
+ .save = &save,
+ .extra_opts = opts
+};
+
+static struct xtables_match tcp6 = {
+ .next = NULL,
+ .family = AF_INET6,
+ .name = "tcp",
+ .version = IPTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_tcp)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_tcp)),
+ .help = &help,
+ .init = &init,
+ .parse = &parse6,
+ .final_check = &final_check,
+ .print = &print,
+ .save = &save,
+ .extra_opts = opts
+};
+
+void
+_init(void)
+{
+ xtables_register_match(&tcp);
+ xtables_register_match(&tcp6);
+}
--
1.5.2.2


jengelh at computergmbh

Jul 14, 2007, 11:44 AM

Post #2 of 9 (1414 views)
Permalink
Re: [PATCH 28/43] Unifies libip[6]t_tcp.c into libxt_tcp.c. [In reply to]

Hi,

On Jul 15 2007 03:11, Yasuyuki KOZAKAI wrote:
>
>Note: libipt_tcp handled '--syn' as '--flags SYN,RST,ACK,FIN SYN', but
> libip6t_tcp handled it as '--flags SYN,RST,ACK SYN'. I keep this
> difference for now.

Since SYN+FIN does not make much sense (unless the ipv6-tcp protocol _really_
allowed that), libipt_tcp's definition should be used.


Jan
--


kaber at trash

Jul 15, 2007, 7:36 AM

Post #3 of 9 (1409 views)
Permalink
Re: [PATCH 28/43] Unifies libip[6]t_tcp.c into libxt_tcp.c. [In reply to]

Jan Engelhardt wrote:
> On Jul 15 2007 03:11, Yasuyuki KOZAKAI wrote:
>
>>Note: libipt_tcp handled '--syn' as '--flags SYN,RST,ACK,FIN SYN', but
>> libip6t_tcp handled it as '--flags SYN,RST,ACK SYN'. I keep this
>> difference for now.
>
>
> Since SYN+FIN does not make much sense (unless the ipv6-tcp protocol _really_
> allowed that), libipt_tcp's definition should be used.


Agreed, that should work fine for both.


pascal.mail at plouf

Jul 15, 2007, 3:45 PM

Post #4 of 9 (1400 views)
Permalink
Re: [PATCH 28/43] Unifies libip[6]t_tcp.c into libxt_tcp.c. [In reply to]

Hello,

Jan Engelhardt a écrit :
>
> On Jul 15 2007 03:11, Yasuyuki KOZAKAI wrote:
>
>>Note: libipt_tcp handled '--syn' as '--flags SYN,RST,ACK,FIN SYN', but
>> libip6t_tcp handled it as '--flags SYN,RST,ACK SYN'. I keep this
>> difference for now.
>
> Since SYN+FIN does not make much sense (unless the ipv6-tcp protocol _really_
> allowed that), libipt_tcp's definition should be used.

I just asked about this difference - and the reason why the FIN check
was not originally present in libiptc_tcp but added later, in 1.3.2 - in
the netfilter user list a few days ago. No reply yet. IMHO it does not
matter whether SYN+FIN makes sense or not but whether it is a valid
combination or not per the RFCs. I have always believed that there is
some precedence among TCP flags, e.g. :
- RST has precedence over SYN and FIN ; if RST set, ignore SYN and FIN
- SYN has precedence over FIN ; if SYN set, ignore FIN

Have I been wrong all this time ?


yasuyuki.kozakai at toshiba

Jul 16, 2007, 1:31 AM

Post #5 of 9 (1407 views)
Permalink
Re: [PATCH 28/43] Unifies libip[6]t_tcp.c into libxt_tcp.c. [In reply to]

From: Patrick McHardy <kaber [at] trash>
Date: Sun, 15 Jul 2007 16:36:20 +0200

> Jan Engelhardt wrote:
> > On Jul 15 2007 03:11, Yasuyuki KOZAKAI wrote:
> >
> >>Note: libipt_tcp handled '--syn' as '--flags SYN,RST,ACK,FIN SYN', but
> >> libip6t_tcp handled it as '--flags SYN,RST,ACK SYN'. I keep this
> >> difference for now.
> >
> >
> > Since SYN+FIN does not make much sense (unless the ipv6-tcp protocol _really_
> > allowed that), libipt_tcp's definition should be used.
>
>
> Agreed, that should work fine for both.

OK, I don't come up with bad impact to current user, too.
I'll fix that before applying xtables pathes.

-- Yasuyuki Kozakai


yasuyuki.kozakai at toshiba

Jul 16, 2007, 8:44 PM

Post #6 of 9 (1410 views)
Permalink
Re: [PATCH 28/43] Unifies libip[6]t_tcp.c into libxt_tcp.c. [In reply to]

From: Yasuyuki KOZAKAI <yasuyuki.kozakai [at] toshiba>

> > > Since SYN+FIN does not make much sense (unless the ipv6-tcp protocol _really_
> > > allowed that), libipt_tcp's definition should be used.
> >
> >
> > Agreed, that should work fine for both.
>
> OK, I don't come up with bad impact to current user, too.
> I'll fix that before applying xtables pathes.

Well, I found missing FIN in text of help() in libipt_tcp.c then also
fixed. New release is necessary again ? grrr.. If so, I'll change version
in Makefile, and apply xtables patches to main trunk.


-- Yasuyuki Kozakai


yasuyuki.kozakai at toshiba

Jul 16, 2007, 9:21 PM

Post #7 of 9 (1402 views)
Permalink
Re: [PATCH 28/43] Unifies libip[6]t_tcp.c into libxt_tcp.c. [In reply to]

From: Pascal Hambourg <pascal.mail [at] plouf>
Date: Mon, 16 Jul 2007 00:45:16 +0200

> Hello,
>
> Jan Engelhardt a écrit :
> >
> > On Jul 15 2007 03:11, Yasuyuki KOZAKAI wrote:
> >
> >>Note: libipt_tcp handled '--syn' as '--flags SYN,RST,ACK,FIN SYN', but
> >> libip6t_tcp handled it as '--flags SYN,RST,ACK SYN'. I keep this
> >> difference for now.
> >
> > Since SYN+FIN does not make much sense (unless the ipv6-tcp protocol _really_
> > allowed that), libipt_tcp's definition should be used.
>
> I just asked about this difference - and the reason why the FIN check
> was not originally present in libiptc_tcp but added later, in 1.3.2 - in
> the netfilter user list a few days ago. No reply yet. IMHO it does not

I don't know Harald's intention for that change correctly, sorry.

> matter whether SYN+FIN makes sense or not but whether it is a valid
> combination or not per the RFCs. I have always believed that there is
> some precedence among TCP flags, e.g. :
> - RST has precedence over SYN and FIN ; if RST set, ignore SYN and FIN
> - SYN has precedence over FIN ; if SYN set, ignore FIN
>
> Have I been wrong all this time ?

IIRC RFC797 says nothing about the behavior when receiving such TCP
flags. But I've found

http://www.mail-archive.com/nanog [at] merit/msg06112.html

-- Yasuyuki Kozakai


pascal.mail at plouf

Jul 16, 2007, 11:45 PM

Post #8 of 9 (1404 views)
Permalink
Re: [PATCH 28/43] Unifies libip[6]t_tcp.c into libxt_tcp.c. [In reply to]

Yasuyuki KOZAKAI a écrit :
> From: Pascal Hambourg <pascal.mail [at] plouf>
>>>
>>>Since SYN+FIN does not make much sense (unless the ipv6-tcp protocol _really_
>>>allowed that), libipt_tcp's definition should be used.
>>
>>IMHO it does not
>>matter whether SYN+FIN makes sense or not but whether it is a valid
>>combination or not per the RFCs. I have always believed that there is
>>some precedence among TCP flags, e.g. :
>>- RST has precedence over SYN and FIN ; if RST set, ignore SYN and FIN
>>- SYN has precedence over FIN ; if SYN set, ignore FIN
>>
>>Have I been wrong all this time ?
>
> IIRC RFC797 says nothing about the behavior when receiving such TCP
> flags.

I suppose you mean RFC973 ? Well, it says that SYN is handled before FIN.

> But I've found
>
> http://www.mail-archive.com/nanog [at] merit/msg06112.html

I came across multiple similar discussions worrying about the so-called
SYN-FIN port scans. They all acknowledge that popular TCP/IP stack
implementations are "liberal" because they handle SYN+FIN as plain SYN.
But I do not agreed with them when they claim that packet filters which
unconditionally allow SYN+FIN through are "liberal" too. IMHO they are
not liberal but actually broken because they fail to identify SYN+FIN
either as plain SYN (which they should handle as such) or as an invalid
combination (which they should drop).

One of my concerns is that with the new conservative definition of
--syn, you cannot use it any more to drop SYN packets (e.g. to reject
incoming TCP connection attempts on a stateless packet filter) because
SYN+FIN won't match. Old rulesets which rely on --syn to detect and drop
packets become more permissive with the new definition.

However I agree that nowadays any decent packet filter should use TCP
connection tracking and not rely only on TCP flags. By the way, how does
the TCP connection tracking in ip_conntrack and nf_conntrack handle
"odd" flag combinations, i.e. more than one flag in RST, SYN and FIN set
at the same time ?


yasuyuki.kozakai at toshiba

Jul 17, 2007, 12:48 AM

Post #9 of 9 (1412 views)
Permalink
Re: [PATCH 28/43] Unifies libip[6]t_tcp.c into libxt_tcp.c. [In reply to]

From: Pascal Hambourg <pascal.mail [at] plouf>

> Yasuyuki KOZAKAI a écrit :
> > From: Pascal Hambourg <pascal.mail [at] plouf>
> >>>
> >>>Since SYN+FIN does not make much sense (unless the ipv6-tcp protocol _really_
> >>>allowed that), libipt_tcp's definition should be used.
> >>
> >>IMHO it does not
> >>matter whether SYN+FIN makes sense or not but whether it is a valid
> >>combination or not per the RFCs. I have always believed that there is
> >>some precedence among TCP flags, e.g. :
> >>- RST has precedence over SYN and FIN ; if RST set, ignore SYN and FIN
> >>- SYN has precedence over FIN ; if SYN set, ignore FIN
> >>
> >>Have I been wrong all this time ?
> >
> > IIRC RFC797 says nothing about the behavior when receiving such TCP
> > flags.
>
> I suppose you mean RFC973 ? Well, it says that SYN is handled before FIN.

No, RFC793 :) Sorry.


> > But I've found
> >
> > http://www.mail-archive.com/nanog [at] merit/msg06112.html
>
> I came across multiple similar discussions worrying about the so-called
> SYN-FIN port scans. They all acknowledge that popular TCP/IP stack
> implementations are "liberal" because they handle SYN+FIN as plain SYN.
> But I do not agreed with them when they claim that packet filters which
> unconditionally allow SYN+FIN through are "liberal" too. IMHO they are
> not liberal but actually broken because they fail to identify SYN+FIN
> either as plain SYN (which they should handle as such) or as an invalid
> combination (which they should drop).
>
> One of my concerns is that with the new conservative definition of
> --syn, you cannot use it any more to drop SYN packets (e.g. to reject
> incoming TCP connection attempts on a stateless packet filter) because
> SYN+FIN won't match. Old rulesets which rely on --syn to detect and drop
> packets become more permissive with the new definition.

Yes, so I think we'd better to add some texts about this change in
the announcement of next version.

And if users want to handle match SYN+FIN, they can use '--tcp-flags'.

> However I agree that nowadays any decent packet filter should use TCP
> connection tracking and not rely only on TCP flags. By the way, how does
> the TCP connection tracking in ip_conntrack and nf_conntrack handle
> "odd" flag combinations, i.e. more than one flag in RST, SYN and FIN set
> at the same time ?

From nf_conntrack_proto_tcp.c,

/* table of valid flag combinations - PUSH, ECE and CWR are always valid */
static u8 tcp_valid_flags[(TH_FIN|TH_SYN|TH_RST|TH_ACK|TH_URG) + 1] =
{
[TH_SYN] = 1,
[TH_SYN|TH_URG] = 1,
[TH_SYN|TH_ACK] = 1,
[TH_RST] = 1,
[TH_RST|TH_ACK] = 1,
[TH_FIN|TH_ACK] = 1,
[TH_FIN|TH_ACK|TH_URG] = 1,
[TH_ACK] = 1,
[TH_ACK|TH_URG] = 1,
};

-- Yasuyuki Kozakai

iptables devel RSS feed   Index | Next | Previous | View Threaded
 
 


Interested in having your list archived? Contact Gossamer Threads
 
  Web Applications & Managed Hosting Powered by Gossamer Threads Inc.