diff options
Diffstat (limited to 'extensions')
68 files changed, 1850 insertions, 300 deletions
diff --git a/extensions/GNUmakefile.in b/extensions/GNUmakefile.in index 52915725..4e94bd01 100644 --- a/extensions/GNUmakefile.in +++ b/extensions/GNUmakefile.in @@ -39,16 +39,24 @@ endif # Wildcard module list # pfx_build_mod := $(patsubst ${srcdir}/libxt_%.c,%,$(sort $(wildcard ${srcdir}/libxt_*.c))) +pfb_build_mod := $(patsubst ${srcdir}/libebt_%.c,%,$(sort $(wildcard ${srcdir}/libebt_*.c))) +pfa_build_mod := $(patsubst ${srcdir}/libarpt_%.c,%,$(sort $(wildcard ${srcdir}/libarpt_*.c))) pfx_symlinks := NOTRACK state @ENABLE_IPV4_TRUE@ pf4_build_mod := $(patsubst ${srcdir}/libipt_%.c,%,$(sort $(wildcard ${srcdir}/libipt_*.c))) @ENABLE_IPV6_TRUE@ pf6_build_mod := $(patsubst ${srcdir}/libip6t_%.c,%,$(sort $(wildcard ${srcdir}/libip6t_*.c))) pfx_build_mod := $(filter-out @blacklist_modules@,${pfx_build_mod}) +pfb_build_mod := $(filter-out @blacklist_modules@,${pfb_build_mod}) +pfa_build_mod := $(filter-out @blacklist_modules@,${pfa_build_mod}) pf4_build_mod := $(filter-out @blacklist_modules@,${pf4_build_mod}) pf6_build_mod := $(filter-out @blacklist_modules@,${pf6_build_mod}) pfx_objs := $(patsubst %,libxt_%.o,${pfx_build_mod}) +pfb_objs := $(patsubst %,libebt_%.o,${pfb_build_mod}) +pfa_objs := $(patsubst %,libarpt_%.o,${pfa_build_mod}) pf4_objs := $(patsubst %,libipt_%.o,${pf4_build_mod}) pf6_objs := $(patsubst %,libip6t_%.o,${pf6_build_mod}) pfx_solibs := $(patsubst %,libxt_%.so,${pfx_build_mod} ${pfx_symlinks}) +pfb_solibs := $(patsubst %,libebt_%.so,${pfb_build_mod}) +pfa_solibs := $(patsubst %,libarpt_%.so,${pfa_build_mod}) pf4_solibs := $(patsubst %,libipt_%.so,${pf4_build_mod}) pf6_solibs := $(patsubst %,libip6t_%.so,${pf6_build_mod}) @@ -56,13 +64,15 @@ pf6_solibs := $(patsubst %,libip6t_%.so,${pf6_build_mod}) # # Building blocks # -targets := libext.a libext4.a libext6.a matches.man targets.man +targets := libext.a libext4.a libext6.a libext_ebt.a libext_arpt.a matches.man targets.man targets_install := @ENABLE_STATIC_TRUE@ libext_objs := ${pfx_objs} +@ENABLE_STATIC_TRUE@ libext_ebt_objs := ${pfb_objs} +@ENABLE_STATIC_TRUE@ libext_arpt_objs := ${pfa_objs} @ENABLE_STATIC_TRUE@ libext4_objs := ${pf4_objs} @ENABLE_STATIC_TRUE@ libext6_objs := ${pf6_objs} -@ENABLE_STATIC_FALSE@ targets += ${pfx_solibs} ${pf4_solibs} ${pf6_solibs} -@ENABLE_STATIC_FALSE@ targets_install += ${pfx_solibs} ${pf4_solibs} ${pf6_solibs} +@ENABLE_STATIC_FALSE@ targets += ${pfx_solibs} ${pfb_solibs} ${pf4_solibs} ${pf6_solibs} ${pfa_solibs} +@ENABLE_STATIC_FALSE@ targets_install += ${pfx_solibs} ${pfb_solibs} ${pf4_solibs} ${pf6_solibs} ${pfa_solibs} .SECONDARY: @@ -75,7 +85,7 @@ install: ${targets_install} if test -n "${targets_install}"; then install -pm0755 $^ "${DESTDIR}${xtlibdir}/"; fi; clean: - rm -f *.o *.oo *.so *.a {matches,targets}.man initext.c initext4.c initext6.c; + rm -f *.o *.oo *.so *.a {matches,targets}.man initext.c initext4.c initext6.c initextb.c initexta.c; rm -f .*.d .*.dd; distclean: clean @@ -118,6 +128,12 @@ lib%.o: ${srcdir}/lib%.c libext.a: initext.o ${libext_objs} ${AM_VERBOSE_AR} ${AR} crs $@ $^; +libext_ebt.a: initextb.o ${libext_ebt_objs} + ${AM_VERBOSE_AR} ${AR} crs $@ $^; + +libext_arpt.a: initexta.o ${libext_arpt_objs} + ${AM_VERBOSE_AR} ${AR} crs $@ $^; + libext4.a: initext4.o ${libext4_objs} ${AM_VERBOSE_AR} ${AR} crs $@ $^; @@ -125,6 +141,8 @@ libext6.a: initext6.o ${libext6_objs} ${AM_VERBOSE_AR} ${AR} crs $@ $^; initext_func := $(addprefix xt_,${pfx_build_mod}) +initextb_func := $(addprefix ebt_,${pfb_build_mod}) +initexta_func := $(addprefix arpt_,${pfa_build_mod}) initext4_func := $(addprefix ipt_,${pf4_build_mod}) initext6_func := $(addprefix ip6t_,${pf6_build_mod}) @@ -133,6 +151,16 @@ initext6_func := $(addprefix ip6t_,${pf6_build_mod}) cmp -s $@ $@.tmp || mv $@.tmp $@; \ rm -f $@.tmp; +.initextb.dd: FORCE + @echo "${initextb_func}" >$@.tmp; \ + cmp -s $@ $@.tmp || mv $@.tmp $@; \ + rm -f $@.tmp; + +.initexta.dd: FORCE + @echo "${initexta_func}" >$@.tmp; \ + cmp -s $@ $@.tmp || mv $@.tmp $@; \ + rm -f $@.tmp; + .initext4.dd: FORCE @echo "${initext4_func}" >$@.tmp; \ cmp -s $@ $@.tmp || mv $@.tmp $@; \ @@ -159,6 +187,38 @@ initext.c: .initext.dd echo "}" >>$@; \ ); +initextb.c: .initextb.dd + ${AM_VERBOSE_GEN} + @( \ + echo "" >$@; \ + for i in ${initextb_func}; do \ + echo "extern void lib$${i}_init(void);" >>$@; \ + done; \ + echo "void init_extensionsb(void);" >>$@; \ + echo "void init_extensionsb(void)" >>$@; \ + echo "{" >>$@; \ + for i in ${initextb_func}; do \ + echo " ""lib$${i}_init();" >>$@; \ + done; \ + echo "}" >>$@; \ + ); + +initexta.c: .initexta.dd + ${AM_VERBOSE_GEN} + @( \ + echo "" >$@; \ + for i in ${initexta_func}; do \ + echo "extern void lib$${i}_init(void);" >>$@; \ + done; \ + echo "void init_extensionsa(void);" >>$@; \ + echo "void init_extensionsa(void)" >>$@; \ + echo "{" >>$@; \ + for i in ${initexta_func}; do \ + echo " ""lib$${i}_init();" >>$@; \ + done; \ + echo "}" >>$@; \ + ); + initext4.c: .initext4.dd ${AM_VERBOSE_GEN} @( \ @@ -219,8 +279,8 @@ man_run = \ fi; \ done >$@; -matches.man: .initext.dd .initext4.dd .initext6.dd $(wildcard ${srcdir}/lib*.man) - $(call man_run,$(call ex_matches,${pfx_build_mod} ${pf4_build_mod} ${pf6_build_mod} ${pfx_symlinks})) +matches.man: .initext.dd .initextb.dd .initexta.dd .initext4.dd .initext6.dd $(wildcard ${srcdir}/lib*.man) + $(call man_run,$(call ex_matches,${pfx_build_mod} ${pfb_build_mod} ${pfa_build_mod} ${pf4_build_mod} ${pf6_build_mod} ${pfx_symlinks})) -targets.man: .initext.dd .initext4.dd .initext6.dd $(wildcard ${srcdir}/lib*.man) - $(call man_run,$(call ex_targets,${pfx_build_mod} ${pf4_build_mod} ${pf6_build_mod} ${pfx_symlinks})) +targets.man: .initext.dd .initextb.dd .initexta.dd .initext4.dd .initext6.dd $(wildcard ${srcdir}/lib*.man) + $(call man_run,$(call ex_targets,${pfx_build_mod} ${pfb_build_mod} ${pfa_build_mod} ${pf4_build_mod} ${pf6_build_mod} ${pfx_symlinks})) diff --git a/extensions/libarpt_mangle.c b/extensions/libarpt_mangle.c new file mode 100644 index 00000000..03c31a94 --- /dev/null +++ b/extensions/libarpt_mangle.c @@ -0,0 +1,204 @@ +/* + * Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com> adapted + * this code to libxtables for arptables-compat in 2015 + */ + +#include <stdio.h> +#include <netdb.h> +#include <string.h> +#include <stdlib.h> +#include <limits.h> +#include <getopt.h> +#include <netinet/ether.h> +#include <xtables.h> +#include <linux/netfilter_arp/arpt_mangle.h> +#include "iptables/nft.h" +#include "iptables/nft-arp.h" + +static void arpmangle_print_help(void) +{ + printf( + "mangle target options:\n" + "--mangle-ip-s IP address\n" + "--mangle-ip-d IP address\n" + "--mangle-mac-s MAC address\n" + "--mangle-mac-d MAC address\n" + "--mangle-target target (DROP, CONTINUE or ACCEPT -- default is ACCEPT)\n"); +} + +#define MANGLE_IPS '1' +#define MANGLE_IPT '2' +#define MANGLE_DEVS '3' +#define MANGLE_DEVT '4' +#define MANGLE_TARGET '5' + +static struct option arpmangle_opts[] = { + { .name = "mangle-ip-s", .has_arg = true, .val = MANGLE_IPS }, + { .name = "mangle-ip-d", .has_arg = true, .val = MANGLE_IPT }, + { .name = "mangle-mac-s", .has_arg = true, .val = MANGLE_DEVS }, + { .name = "mangle-mac-d", .has_arg = true, .val = MANGLE_DEVT }, + { .name = "mangle-target", .has_arg = true, .val = MANGLE_TARGET }, + XT_GETOPT_TABLEEND, +}; + +static void arpmangle_init(struct xt_entry_target *target) +{ + struct arpt_mangle *mangle = (struct arpt_mangle *)target->data; + + mangle->target = NF_ACCEPT; +} + +static int +arpmangle_parse(int c, char **argv, int invert, unsigned int *flags, + const void *entry, struct xt_entry_target **target) +{ + struct arpt_mangle *mangle = (struct arpt_mangle *)(*target)->data; + struct in_addr *ipaddr, mask; + struct ether_addr *macaddr; + const struct arpt_entry *e = (const struct arpt_entry *)entry; + unsigned int nr; + int ret = 1; + + memset(&mask, 0, sizeof(mask)); + + switch (c) { + case MANGLE_IPS: + xtables_ipparse_any(optarg, &ipaddr, &mask, &nr); + mangle->u_s.src_ip.s_addr = ipaddr->s_addr; + free(ipaddr); + mangle->flags |= ARPT_MANGLE_SIP; + break; + case MANGLE_IPT: + xtables_ipparse_any(optarg, &ipaddr, &mask, &nr); + mangle->u_t.tgt_ip.s_addr = ipaddr->s_addr; + free(ipaddr); + mangle->flags |= ARPT_MANGLE_TIP; + break; + case MANGLE_DEVS: + if (e->arp.arhln_mask == 0) + xtables_error(PARAMETER_PROBLEM, + "no --h-length defined"); + if (e->arp.invflags & ARPT_INV_ARPHLN) + xtables_error(PARAMETER_PROBLEM, + "! --h-length not allowed for " + "--mangle-mac-s"); + if (e->arp.arhln != 6) + xtables_error(PARAMETER_PROBLEM, + "only --h-length 6 supported"); + macaddr = ether_aton(optarg); + if (macaddr == NULL) + xtables_error(PARAMETER_PROBLEM, + "invalid source MAC"); + memcpy(mangle->src_devaddr, macaddr, e->arp.arhln); + mangle->flags |= ARPT_MANGLE_SDEV; + break; + case MANGLE_DEVT: + if (e->arp.arhln_mask == 0) + xtables_error(PARAMETER_PROBLEM, + "no --h-length defined"); + if (e->arp.invflags & ARPT_INV_ARPHLN) + xtables_error(PARAMETER_PROBLEM, + "! hln not allowed for --mangle-mac-d"); + if (e->arp.arhln != 6) + xtables_error(PARAMETER_PROBLEM, + "only --h-length 6 supported"); + macaddr = ether_aton(optarg); + if (macaddr == NULL) + xtables_error(PARAMETER_PROBLEM, "invalid target MAC"); + memcpy(mangle->tgt_devaddr, macaddr, e->arp.arhln); + mangle->flags |= ARPT_MANGLE_TDEV; + break; + case MANGLE_TARGET: + if (!strcmp(optarg, "DROP")) + mangle->target = NF_DROP; + else if (!strcmp(optarg, "ACCEPT")) + mangle->target = NF_ACCEPT; + else if (!strcmp(optarg, "CONTINUE")) + mangle->target = XT_CONTINUE; + else + xtables_error(PARAMETER_PROBLEM, + "bad target for --mangle-target"); + break; + default: + ret = 0; + } + + return ret; +} + +static void arpmangle_final_check(unsigned int flags) +{ +} + +static void print_mac(const unsigned char *mac, int l) +{ + int j; + + for (j = 0; j < l; j++) + printf("%02x%s", mac[j], + (j==l-1) ? "" : ":"); +} + +static void +arpmangle_print(const void *ip, const struct xt_entry_target *target, + int numeric) +{ + struct arpt_mangle *m = (struct arpt_mangle *)(target->data); + char buf[100]; + + if (m->flags & ARPT_MANGLE_SIP) { + if (numeric) + sprintf(buf, "%s", + xtables_ipaddr_to_numeric(&(m->u_s.src_ip))); + else + sprintf(buf, "%s", + xtables_ipaddr_to_anyname(&(m->u_s.src_ip))); + printf("--mangle-ip-s %s ", buf); + } + if (m->flags & ARPT_MANGLE_SDEV) { + printf("--mangle-mac-s "); + print_mac((unsigned char *)m->src_devaddr, 6); + printf(" "); + } + if (m->flags & ARPT_MANGLE_TIP) { + if (numeric) + sprintf(buf, "%s", + xtables_ipaddr_to_numeric(&(m->u_t.tgt_ip))); + else + sprintf(buf, "%s", + xtables_ipaddr_to_anyname(&(m->u_t.tgt_ip))); + printf("--mangle-ip-d %s ", buf); + } + if (m->flags & ARPT_MANGLE_TDEV) { + printf("--mangle-mac-d "); + print_mac((unsigned char *)m->tgt_devaddr, 6); + printf(" "); + } + if (m->target != NF_ACCEPT) { + printf("--mangle-target "); + if (m->target == NF_DROP) + printf("DROP "); + else + printf("CONTINUE "); + } +} + +static struct xtables_target arpmangle_target = { + .name = "mangle", + .revision = 0, + .version = XTABLES_VERSION, + .family = NFPROTO_ARP, + .size = XT_ALIGN(sizeof(struct arpt_mangle)), + .userspacesize = XT_ALIGN(sizeof(struct arpt_mangle)), + .help = arpmangle_print_help, + .init = arpmangle_init, + .parse = arpmangle_parse, + .final_check = arpmangle_final_check, + .print = arpmangle_print, + .extra_opts = arpmangle_opts, +}; + +void _init(void) +{ + xtables_register_target(&arpmangle_target); +} diff --git a/extensions/libebt_802_3.c b/extensions/libebt_802_3.c new file mode 100644 index 00000000..3c4a1c3c --- /dev/null +++ b/extensions/libebt_802_3.c @@ -0,0 +1,133 @@ +/* 802_3 + * + * Author: + * Chris Vitale <csv@bluetail.com> + * + * May 2003 + * + * Adapted by Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com> + * to use libxtables for ebtables-compat + */ + +#include <stdbool.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <getopt.h> +#include <xtables.h> +#include <linux/netfilter_bridge/ebt_802_3.h> + +#define _802_3_SAP '1' +#define _802_3_TYPE '2' + +static const struct option br802_3_opts[] = { + { .name = "802_3-sap", .has_arg = true, .val = _802_3_SAP }, + { .name = "802_3-type", .has_arg = true, .val = _802_3_TYPE }, + XT_GETOPT_TABLEEND, +}; + +static void br802_3_print_help(void) +{ + printf( +"802_3 options:\n" +"--802_3-sap [!] protocol : 802.3 DSAP/SSAP- 1 byte value (hex)\n" +" DSAP and SSAP are always the same. One SAP applies to both fields\n" +"--802_3-type [!] protocol : 802.3 SNAP Type- 2 byte value (hex)\n" +" Type implies SAP value 0xaa\n"); +} + +static void br802_3_init(struct xt_entry_match *match) +{ + struct ebt_802_3_info *info = (struct ebt_802_3_info *)match->data; + + info->invflags = 0; + info->bitmask = 0; +} + +static int +br802_3_parse(int c, char **argv, int invert, unsigned int *flags, + const void *entry, struct xt_entry_match **match) +{ + struct ebt_802_3_info *info = (struct ebt_802_3_info *) (*match)->data; + unsigned int i; + char *end; + + switch (c) { + case _802_3_SAP: + if (invert) + info->invflags |= EBT_802_3_SAP; + i = strtoul(optarg, &end, 16); + if (i > 255 || *end != '\0') + xtables_error(PARAMETER_PROBLEM, + "Problem with specified " + "sap hex value, %x",i); + info->sap = i; /* one byte, so no byte order worries */ + info->bitmask |= EBT_802_3_SAP; + break; + case _802_3_TYPE: + if (invert) + info->invflags |= EBT_802_3_TYPE; + i = strtoul(optarg, &end, 16); + if (i > 65535 || *end != '\0') { + xtables_error(PARAMETER_PROBLEM, + "Problem with the specified " + "type hex value, %x",i); + } + info->type = htons(i); + info->bitmask |= EBT_802_3_TYPE; + break; + default: + return 0; + } + + *flags |= info->bitmask; + return 1; +} + +static void +br802_3_final_check(unsigned int flags) +{ + if (!flags) + xtables_error(PARAMETER_PROBLEM, + "You must specify proper arguments"); +} + +static void br802_3_print(const void *ip, const struct xt_entry_match *match, + int numeric) +{ + struct ebt_802_3_info *info = (struct ebt_802_3_info *)match->data; + + if (info->bitmask & EBT_802_3_SAP) { + printf("--802_3-sap "); + if (info->invflags & EBT_802_3_SAP) + printf("! "); + printf("0x%.2x ", info->sap); + } + if (info->bitmask & EBT_802_3_TYPE) { + printf("--802_3-type "); + if (info->invflags & EBT_802_3_TYPE) + printf("! "); + printf("0x%.4x ", ntohs(info->type)); + } +} + +static struct xtables_match br802_3_match = +{ + .name = "802_3", + .revision = 0, + .version = XTABLES_VERSION, + .family = NFPROTO_BRIDGE, + .size = XT_ALIGN(sizeof(struct ebt_802_3_info)), + .userspacesize = XT_ALIGN(sizeof(struct ebt_802_3_info)), + .init = br802_3_init, + .help = br802_3_print_help, + .parse = br802_3_parse, + .final_check = br802_3_final_check, + .print = br802_3_print, + .extra_opts = br802_3_opts, +}; + +void _init(void) +{ + xtables_register_match(&br802_3_match); +} diff --git a/extensions/libebt_ip.c b/extensions/libebt_ip.c new file mode 100644 index 00000000..8b628760 --- /dev/null +++ b/extensions/libebt_ip.c @@ -0,0 +1,312 @@ +/* ebt_ip + * + * Authors: + * Bart De Schuymer <bdschuym@pandora.be> + * + * Changes: + * added ip-sport and ip-dport; parsing of port arguments is + * based on code from iptables-1.2.7a + * Innominate Security Technologies AG <mhopf@innominate.com> + * September, 2002 + * + * Adapted by Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com> + * to use libxtables for ebtables-compat in 2015. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <getopt.h> +#include <netdb.h> +#include <xtables.h> +#include <linux/netfilter_bridge/ebt_ip.h> + +#define IP_SOURCE '1' +#define IP_DEST '2' +#define IP_EBT_TOS '3' /* include/bits/in.h seems to already define IP_TOS */ +#define IP_PROTO '4' +#define IP_SPORT '5' +#define IP_DPORT '6' + +static const struct option brip_opts[] = { + { .name = "ip-source", .has_arg = true, .val = IP_SOURCE }, + { .name = "ip-src", .has_arg = true, .val = IP_SOURCE }, + { .name = "ip-destination", .has_arg = true, .val = IP_DEST }, + { .name = "ip-dst", .has_arg = true, .val = IP_DEST }, + { .name = "ip-tos", .has_arg = true, .val = IP_EBT_TOS }, + { .name = "ip-protocol", .has_arg = true, .val = IP_PROTO }, + { .name = "ip-proto", .has_arg = true, .val = IP_PROTO }, + { .name = "ip-source-port", .has_arg = true, .val = IP_SPORT }, + { .name = "ip-sport", .has_arg = true, .val = IP_SPORT }, + { .name = "ip-destination-port",.has_arg = true, .val = IP_DPORT }, + { .name = "ip-dport", .has_arg = true, .val = IP_DPORT }, + XT_GETOPT_TABLEEND, +}; + +static void brip_print_help(void) +{ + printf( +"ip options:\n" +"--ip-src [!] address[/mask]: ip source specification\n" +"--ip-dst [!] address[/mask]: ip destination specification\n" +"--ip-tos [!] tos : ip tos specification\n" +"--ip-proto [!] protocol : ip protocol specification\n" +"--ip-sport [!] port[:port] : tcp/udp source port or port range\n" +"--ip-dport [!] port[:port] : tcp/udp destination port or port range\n"); +} + +static void brip_init(struct xt_entry_match *match) +{ + struct ebt_ip_info *info = (struct ebt_ip_info *)match->data; + + info->invflags = 0; + info->bitmask = 0; +} + +static void +parse_port_range(const char *protocol, const char *portstring, uint16_t *ports) +{ + char *buffer; + char *cp; + + buffer = strdup(portstring); + if ((cp = strchr(buffer, ':')) == NULL) + ports[0] = ports[1] = xtables_parse_port(buffer, NULL); + else { + *cp = '\0'; + cp++; + + ports[0] = buffer[0] ? xtables_parse_port(buffer, NULL) : 0; + ports[1] = cp[0] ? xtables_parse_port(cp, NULL) : 0xFFFF; + + if (ports[0] > ports[1]) + xtables_error(PARAMETER_PROBLEM, + "invalid portrange (min > max)"); + } + free(buffer); +} + +/* original code from ebtables: useful_functions.c */ +static int undot_ip(char *ip, unsigned char *ip2) +{ + char *p, *q, *end; + long int onebyte; + int i; + char buf[20]; + + strncpy(buf, ip, sizeof(buf) - 1); + + p = buf; + for (i = 0; i < 3; i++) { + if ((q = strchr(p, '.')) == NULL) + return -1; + *q = '\0'; + onebyte = strtol(p, &end, 10); + if (*end != '\0' || onebyte > 255 || onebyte < 0) + return -1; + ip2[i] = (unsigned char)onebyte; + p = q + 1; + } + + onebyte = strtol(p, &end, 10); + if (*end != '\0' || onebyte > 255 || onebyte < 0) + return -1; + ip2[3] = (unsigned char)onebyte; + + return 0; +} + +static int ip_mask(char *mask, unsigned char *mask2) +{ + char *end; + long int bits; + uint32_t mask22; + + if (undot_ip(mask, mask2)) { + /* not the /a.b.c.e format, maybe the /x format */ + bits = strtol(mask, &end, 10); + if (*end != '\0' || bits > 32 || bits < 0) + return -1; + if (bits != 0) { + mask22 = htonl(0xFFFFFFFF << (32 - bits)); + memcpy(mask2, &mask22, 4); + } else { + mask22 = 0xFFFFFFFF; + memcpy(mask2, &mask22, 4); + } + } + return 0; +} + +static void ebt_parse_ip_address(char *address, uint32_t *addr, uint32_t *msk) +{ + char *p; + + /* first the mask */ + if ((p = strrchr(address, '/')) != NULL) { + *p = '\0'; + if (ip_mask(p + 1, (unsigned char *)msk)) { + xtables_error(PARAMETER_PROBLEM, + "Problem with the IP mask '%s'", p + 1); + return; + } + } else + *msk = 0xFFFFFFFF; + + if (undot_ip(address, (unsigned char *)addr)) { + xtables_error(PARAMETER_PROBLEM, + "Problem with the IP address '%s'", address); + return; + } + *addr = *addr & *msk; +} + +static int +brip_parse(int c, char **argv, int invert, unsigned int *flags, + const void *entry, struct xt_entry_match **match) +{ + struct ebt_ip_info *info = (struct ebt_ip_info *)(*match)->data; + + switch (c) { + case IP_SOURCE: + if (invert) + info->invflags |= EBT_IP_SOURCE; + ebt_parse_ip_address(optarg, &info->saddr, &info->smsk); + info->bitmask |= EBT_IP_SOURCE; + break; + case IP_DEST: + if (invert) + info->invflags |= EBT_IP_DEST; + ebt_parse_ip_address(optarg, &info->daddr, &info->dmsk); + info->bitmask |= EBT_IP_DEST; + break; + case IP_SPORT: + if (invert) + info->invflags |= EBT_IP_SPORT; + parse_port_range(NULL, optarg, info->sport); + info->bitmask |= EBT_IP_SPORT; + break; + case IP_DPORT: + if (invert) + info->invflags |= EBT_IP_DPORT; + parse_port_range(NULL, optarg, info->dport); + info->bitmask |= EBT_IP_DPORT; + break; + case IP_EBT_TOS: + if (invert) + info->invflags |= EBT_IP_TOS; + if (!xtables_strtoul(optarg, NULL, (uintmax_t *)&info->tos, + 0, 255)) + xtables_error(PARAMETER_PROBLEM, + "Problem with specified IP tos"); + info->bitmask |= EBT_IP_TOS; + break; + case IP_PROTO: + if (invert) + info->invflags |= EBT_IP_PROTO; + info->protocol = xtables_parse_protocol(optarg); + if (info->protocol == -1) + xtables_error(PARAMETER_PROBLEM, + "Unknown specified IP protocol - %s", + optarg); + info->bitmask |= EBT_IP_PROTO; + break; + default: + return 0; + } + + *flags |= info->bitmask; + return 1; +} + +static void brip_final_check(unsigned int flags) +{ + if (!flags) + xtables_error(PARAMETER_PROBLEM, + "You must specify proper arguments"); +} + +static void print_port_range(uint16_t *ports) +{ + if (ports[0] == ports[1]) + printf("%d ", ports[0]); + else + printf("%d:%d ", ports[0], ports[1]); +} + +static void brip_print(const void *ip, const struct xt_entry_match *match, + int numeric) +{ + struct ebt_ip_info *info = (struct ebt_ip_info *)match->data; + struct in_addr *addrp, *maskp; + + if (info->bitmask & EBT_IP_SOURCE) { + printf("--ip-src "); + if (info->invflags & EBT_IP_SOURCE) + printf("! "); + addrp = (struct in_addr *)&info->saddr; + maskp = (struct in_addr *)&info->smsk; + printf("%s%s ", xtables_ipaddr_to_numeric(addrp), + xtables_ipmask_to_numeric(maskp)); + } + if (info->bitmask & EBT_IP_DEST) { + printf("--ip-dst "); + if (info->invflags & EBT_IP_DEST) + printf("! "); + addrp = (struct in_addr *)&info->daddr; + maskp = (struct in_addr *)&info->dmsk; + printf("%s%s ", xtables_ipaddr_to_numeric(addrp), + xtables_ipmask_to_numeric(maskp)); + } + if (info->bitmask & EBT_IP_TOS) { + printf("--ip-tos "); + if (info->invflags & EBT_IP_TOS) + printf("! "); + printf("0x%02X ", info->tos); + } + if (info->bitmask & EBT_IP_PROTO) { + struct protoent *pe; + + printf("--ip-proto "); + if (info->invflags & EBT_IP_PROTO) + printf("! "); + pe = getprotobynumber(info->protocol); + if (pe == NULL) { + printf("%d ", info->protocol); + } else { + printf("%s ", pe->p_name); + } + } + if (info->bitmask & EBT_IP_SPORT) { + printf("--ip-sport "); + if (info->invflags & EBT_IP_SPORT) + printf("! "); + print_port_range(info->sport); + } + if (info->bitmask & EBT_IP_DPORT) { + printf("--ip-dport "); + if (info->invflags & EBT_IP_DPORT) + printf("! "); + print_port_range(info->dport); + } +} + +static struct xtables_match brip_match = { + .name = "ip", + .revision = 0, + .version = XTABLES_VERSION, + .family = NFPROTO_BRIDGE, + .size = XT_ALIGN(sizeof(struct ebt_ip_info)), + .userspacesize = XT_ALIGN(sizeof(struct ebt_ip_info)), + .init = brip_init, + .help = brip_print_help, + .parse = brip_parse, + .final_check = brip_final_check, + .print = brip_print, + .extra_opts = brip_opts, +}; + +void _init(void) +{ + xtables_register_match(&brip_match); +} diff --git a/extensions/libebt_limit.c b/extensions/libebt_limit.c new file mode 100644 index 00000000..c71561c1 --- /dev/null +++ b/extensions/libebt_limit.c @@ -0,0 +1,179 @@ +/* ebt_limit + * + * Authors: + * Tom Marshall <tommy@home.tig-grr.com> + * + * Mostly copied from iptables' limit match. + * + * September, 2003 + * + * Translated to use libxtables for ebtables-compat in 2015 by + * Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com> + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <getopt.h> +#include <errno.h> +#include <xtables.h> +#include <linux/netfilter_bridge/ebt_limit.h> +#include "iptables/nft.h" +#include "iptables/nft-bridge.h" + +#define EBT_LIMIT_AVG "3/hour" +#define EBT_LIMIT_BURST 5 + +#define FLAG_LIMIT 0x01 +#define FLAG_LIMIT_BURST 0x02 +#define ARG_LIMIT '1' +#define ARG_LIMIT_BURST '2' + +static struct option brlimit_opts[] = +{ + { .name = "limit", .has_arg = true, .val = ARG_LIMIT }, + { .name = "limit-burst",.has_arg = true, .val = ARG_LIMIT_BURST }, + XT_GETOPT_TABLEEND, +}; + +static void brlimit_print_help(void) +{ + printf( +"limit options:\n" +"--limit avg : max average match rate: default "EBT_LIMIT_AVG"\n" +" [Packets per second unless followed by \n" +" /sec /minute /hour /day postfixes]\n" +"--limit-burst number : number to match in a burst, -1 < number < 10001,\n" +" default %u\n", EBT_LIMIT_BURST); +} + +static int parse_rate(const char *rate, uint32_t *val) +{ + const char *delim; + uint32_t r; + uint32_t mult = 1; /* Seconds by default. */ + + delim = strchr(rate, '/'); + if (delim) { + if (strlen(delim+1) == 0) + return 0; + + if (strncasecmp(delim+1, "second", strlen(delim+1)) == 0) + mult = 1; + else if (strncasecmp(delim+1, "minute", strlen(delim+1)) == 0) + mult = 60; + else if (strncasecmp(delim+1, "hour", strlen(delim+1)) == 0) + mult = 60*60; + else if (strncasecmp(delim+1, "day", strlen(delim+1)) == 0) + mult = 24*60*60; + else + return 0; + } + r = atoi(rate); + if (!r) + return 0; + + /* This would get mapped to infinite (1/day is minimum they + can specify, so we're ok at that end). */ + if (r / mult > EBT_LIMIT_SCALE) + return 0; + + *val = EBT_LIMIT_SCALE * mult / r; + return 1; +} + +static void brlimit_init(struct xt_entry_match *match) +{ + struct ebt_limit_info *r = (struct ebt_limit_info *)match->data; + + parse_rate(EBT_LIMIT_AVG, &r->avg); + r->burst = EBT_LIMIT_BURST; +} + +static int brlimit_parse(int c, char **argv, int invert, unsigned int *flags, + const void *entry, struct xt_entry_match **match) +{ + struct ebt_limit_info *r = (struct ebt_limit_info *)(*match)->data; + uintmax_t num; + + switch (c) { + case ARG_LIMIT: + EBT_CHECK_OPTION(flags, FLAG_LIMIT); + if (invert) + xtables_error(PARAMETER_PROBLEM, + "Unexpected `!' after --limit"); + if (!parse_rate(optarg, &r->avg)) + xtables_error(PARAMETER_PROBLEM, + "bad rate `%s'", optarg); + break; + case ARG_LIMIT_BURST: + EBT_CHECK_OPTION(flags, FLAG_LIMIT_BURST); + if (invert) + xtables_error(PARAMETER_PROBLEM, + "Unexpected `!' after --limit-burst"); + if (!xtables_strtoul(optarg, NULL, &num, 0, 10000)) + xtables_error(PARAMETER_PROBLEM, + "bad --limit-burst `%s'", optarg); + r->burst = num; + break; + default: + return 0; + } + + return 1; +} + +struct rates +{ + const char *name; + uint32_t mult; +}; + +static struct rates g_rates[] = +{ + { "day", EBT_LIMIT_SCALE*24*60*60 }, + { "hour", EBT_LIMIT_SCALE*60*60 }, + { "min", EBT_LIMIT_SCALE*60 }, + { "sec", EBT_LIMIT_SCALE } +}; + +static void print_rate(uint32_t period) +{ + unsigned int i; + + for (i = 1; i < sizeof(g_rates)/sizeof(struct rates); i++) + if (period > g_rates[i].mult || + g_rates[i].mult/period < g_rates[i].mult%period) + break; + + printf("%u/%s ", g_rates[i-1].mult / period, g_rates[i-1].name); +} + +static void brlimit_print(const void *ip, const struct xt_entry_match *match, + int numeric) +{ + struct ebt_limit_info *r = (struct ebt_limit_info *)match->data; + + printf("--limit "); + print_rate(r->avg); + printf("--limit-burst %u ", r->burst); +} + +static struct xtables_match brlimit_match = { + .name = "limit", + .revision = 0, + .version = XTABLES_VERSION, + .family = NFPROTO_BRIDGE, + .size = XT_ALIGN(sizeof(struct ebt_limit_info)), + .userspacesize = offsetof(struct ebt_limit_info, prev), + .init = brlimit_init, + .help = brlimit_print_help, + .parse = brlimit_parse, + .print = brlimit_print, + .extra_opts = brlimit_opts, +}; + +void _init(void) +{ + xtables_register_match(&brlimit_match); +} diff --git a/extensions/libebt_log.c b/extensions/libebt_log.c new file mode 100644 index 00000000..0799185d --- /dev/null +++ b/extensions/libebt_log.c @@ -0,0 +1,197 @@ +/* + * Bart De Schuymer <bdschuym@pandora.be> + * + * 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. + * + * Giuseppe Longo <giuseppelng@gmail.com> adapted the original code to the + * xtables-compat environment in 2015. + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <syslog.h> +#include <string.h> +#include <getopt.h> +#include <xtables.h> +#include <linux/netfilter_bridge/ebt_log.h> + +#define LOG_DEFAULT_LEVEL LOG_INFO + +#define LOG_PREFIX '1' +#define LOG_LEVEL '2' +#define LOG_ARP '3' +#define LOG_IP '4' +#define LOG_LOG '5' +#define LOG_IP6 '6' + +typedef struct _code { + char *c_name; + int c_val; +} CODE; + +static CODE eight_priority[] = { + { "emerg", LOG_EMERG }, + { "alert", LOG_ALERT }, + { "crit", LOG_CRIT }, + { "error", LOG_ERR }, + { "warning", LOG_WARNING }, + { "notice", LOG_NOTICE }, + { "info", LOG_INFO }, + { "debug", LOG_DEBUG } +}; + +static int name_to_loglevel(const char *arg) +{ + int i; + + for (i = 0; i < 8; i++) + if (!strcmp(arg, eight_priority[i].c_name)) + return eight_priority[i].c_val; + + /* return bad loglevel */ + return 9; +} + +static const struct option brlog_opts[] = { + { .name = "log-prefix", .has_arg = true, .val = LOG_PREFIX }, + { .name = "log-level", .has_arg = true, .val = LOG_LEVEL }, + { .name = "log-arp", .has_arg = false, .val = LOG_ARP }, + { .name = "log-ip", .has_arg = false, .val = LOG_IP }, + { .name = "log", .has_arg = false, .val = LOG_LOG }, + { .name = "log-ip6", .has_arg = false, .val = LOG_IP6 }, + XT_GETOPT_TABLEEND, +}; + +static void brlog_help(void) +{ + int i; + + printf( +"log options:\n" +"--log : use this if you're not specifying anything\n" +"--log-level level : level = [1-8] or a string\n" +"--log-prefix prefix : max. %d chars.\n" +"--log-ip : put ip info. in the log for ip packets\n" +"--log-arp : put (r)arp info. in the log for (r)arp packets\n" +"--log-ip6 : put ip6 info. in the log for ip6 packets\n" + , EBT_LOG_PREFIX_SIZE - 1); + for (i = 0; i < 8; i++) + printf("%d = %s\n", eight_priority[i].c_val, + eight_priority[i].c_name); +} + +static void brlog_init(struct xt_entry_target *t) +{ + struct ebt_log_info *loginfo = (struct ebt_log_info *)t->data; + + loginfo->bitmask = 0; + loginfo->prefix[0] = '\0'; + loginfo->loglevel = LOG_NOTICE; +} + +static int brlog_parse(int c, char **argv, int invert, unsigned int *flags, + const void *entry, struct xt_entry_target **target) +{ + struct ebt_log_info *loginfo = (struct ebt_log_info *)(*target)->data; + long int i; + char *end; + + switch (c) { + case LOG_PREFIX: + if (invert) + xtables_error(PARAMETER_PROBLEM, + "Unexpected `!` after --log-prefix"); + if (strlen(optarg) > sizeof(loginfo->prefix) - 1) + xtables_error(PARAMETER_PROBLEM, + "Prefix too long"); + if (strchr(optarg, '\"')) + xtables_error(PARAMETER_PROBLEM, + "Use of \\\" is not allowed" + " in the prefix"); + strcpy((char *)loginfo->prefix, (char *)optarg); + break; + case LOG_LEVEL: + i = strtol(optarg, &end, 16); + if (*end != '\0' || i < 0 || i > 7) + loginfo->loglevel = name_to_loglevel(optarg); + else + loginfo->loglevel = i; + + if (loginfo->loglevel == 9) + xtables_error(PARAMETER_PROBLEM, + "Problem with the log-level"); + break; + case LOG_IP: + if (invert) + xtables_error(PARAMETER_PROBLEM, + "Unexpected `!' after --log-ip"); + loginfo->bitmask |= EBT_LOG_IP; + break; + case LOG_ARP: + if (invert) + xtables_error(PARAMETER_PROBLEM, + "Unexpected `!' after --log-arp"); + loginfo->bitmask |= EBT_LOG_ARP; + case LOG_LOG: + if (invert) + xtables_error(PARAMETER_PROBLEM, + "Unexpected `!' after --log"); + break; + case LOG_IP6: + if (invert) + xtables_error(PARAMETER_PROBLEM, + "Unexpected `!' after --log-ip6"); + loginfo->bitmask |= EBT_LOG_IP6; + break; + default: + return 0; + } + + *flags |= loginfo->bitmask; + return 1; +} + +static void brlog_final_check(unsigned int flags) +{ +} + +static void brlog_print(const void *ip, const struct xt_entry_target *target, + int numeric) +{ + struct ebt_log_info *loginfo = (struct ebt_log_info *)target->data; + + printf("--log-level %s --log-prefix \"%s\"", + eight_priority[loginfo->loglevel].c_name, + loginfo->prefix); + + if (loginfo->bitmask & EBT_LOG_IP) + printf(" --log-ip"); + if (loginfo->bitmask & EBT_LOG_ARP) + printf(" --log-arp"); + if (loginfo->bitmask & EBT_LOG_IP6) + printf(" --log-ip6"); + printf(" "); +} + +static struct xtables_target brlog_target = { + .name = "log", + .revision = 0, + .version = XTABLES_VERSION, + .family = NFPROTO_BRIDGE, + .size = XT_ALIGN(sizeof(struct ebt_log_info)), + .userspacesize = XT_ALIGN(sizeof(struct ebt_log_info)), + .init = brlog_init, + .help = brlog_help, + .parse = brlog_parse, + .final_check = brlog_final_check, + .print = brlog_print, + .extra_opts = brlog_opts, +}; + +void _init(void) +{ + xtables_register_target(&brlog_target); +} diff --git a/extensions/libebt_mark.c b/extensions/libebt_mark.c new file mode 100644 index 00000000..587b4a63 --- /dev/null +++ b/extensions/libebt_mark.c @@ -0,0 +1,191 @@ +/* ebt_mark + * + * Authors: + * Bart De Schuymer <bdschuym@pandora.be> + * + * July, 2002, September 2006 + * + * Adapted by Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com> + * to use libxtables for ebtables-compat in 2015. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <getopt.h> +#include <xtables.h> +#include <linux/netfilter_bridge/ebt_mark_t.h> +#include "iptables/nft.h" +#include "iptables/nft-bridge.h" + +static int mark_supplied; + +#define MARK_TARGET '1' +#define MARK_SETMARK '2' +#define MARK_ORMARK '3' +#define MARK_ANDMARK '4' +#define MARK_XORMARK '5' +static struct option brmark_opts[] = { + { .name = "mark-target",.has_arg = true, .val = MARK_TARGET }, + /* an oldtime messup, we should have always used the scheme + * <extension-name>-<option> */ + { .name = "set-mark", .has_arg = true, .val = MARK_SETMARK }, + { .name = "mark-set", .has_arg = true, .val = MARK_SETMARK }, + { .name = "mark-or", .has_arg = true, .val = MARK_ORMARK }, + { .name = "mark-and", .has_arg = true, .val = MARK_ANDMARK }, + { .name = "mark-xor", .has_arg = true, .val = MARK_XORMARK }, + XT_GETOPT_TABLEEND, +}; + +static void brmark_print_help(void) +{ + printf( + "mark target options:\n" + " --mark-set value : Set nfmark value\n" + " --mark-or value : Or nfmark with value (nfmark |= value)\n" + " --mark-and value : And nfmark with value (nfmark &= value)\n" + " --mark-xor value : Xor nfmark with value (nfmark ^= value)\n" + " --mark-target target : ACCEPT, DROP, RETURN or CONTINUE\n"); +} + +static void brmark_init(struct xt_entry_target *target) +{ + struct ebt_mark_t_info *info = (struct ebt_mark_t_info *)target->data; + + info->target = EBT_ACCEPT; + info->mark = 0; + mark_supplied = 0; +} + +#define OPT_MARK_TARGET 0x01 +#define OPT_MARK_SETMARK 0x02 +#define OPT_MARK_ORMARK 0x04 +#define OPT_MARK_ANDMARK 0x08 +#define OPT_MARK_XORMARK 0x10 + +static int +brmark_parse(int c, char **argv, int invert, unsigned int *flags, + const void *entry, struct xt_entry_target **target) +{ + struct ebt_mark_t_info *info = (struct ebt_mark_t_info *) + (*target)->data; + char *end; + uint32_t mask; + + switch (c) { + case MARK_TARGET: + { unsigned int tmp; + EBT_CHECK_OPTION(flags, OPT_MARK_TARGET); + if (ebt_fill_target(optarg, &tmp)) + xtables_error(PARAMETER_PROBLEM, + "Illegal --mark-target target"); + /* the 4 lsb are left to designate the target */ + info->target = (info->target & ~EBT_VERDICT_BITS) | + (tmp & EBT_VERDICT_BITS); + } + return 1; + case MARK_SETMARK: + EBT_CHECK_OPTION(flags, OPT_MARK_SETMARK); + mask = (OPT_MARK_ORMARK|OPT_MARK_ANDMARK|OPT_MARK_XORMARK); + if (*flags & mask) + xtables_error(PARAMETER_PROBLEM, + "--mark-set cannot be used together with" + " specific --mark option"); + info->target = (info->target & EBT_VERDICT_BITS) | + MARK_SET_VALUE; + break; + case MARK_ORMARK: + EBT_CHECK_OPTION(flags, OPT_MARK_ORMARK); + mask = (OPT_MARK_SETMARK|OPT_MARK_ANDMARK|OPT_MARK_XORMARK); + if (*flags & mask) + xtables_error(PARAMETER_PROBLEM, + "--mark-or cannot be used together with" + " specific --mark option"); + info->target = (info->target & EBT_VERDICT_BITS) | + MARK_OR_VALUE; + break; + case MARK_ANDMARK: + EBT_CHECK_OPTION(flags, OPT_MARK_ANDMARK); + mask = (OPT_MARK_SETMARK|OPT_MARK_ORMARK|OPT_MARK_XORMARK); + if (*flags & mask) + xtables_error(PARAMETER_PROBLEM, + "--mark-and cannot be used together with" + " specific --mark option"); + info->target = (info->target & EBT_VERDICT_BITS) | + MARK_AND_VALUE; + break; + case MARK_XORMARK: + EBT_CHECK_OPTION(flags, OPT_MARK_XORMARK); + mask = (OPT_MARK_SETMARK|OPT_MARK_ANDMARK|OPT_MARK_ORMARK); + if (*flags & mask) + xtables_error(PARAMETER_PROBLEM, + "--mark-xor cannot be used together with" + " specific --mark option"); + info->target = (info->target & EBT_VERDICT_BITS) | + MARK_XOR_VALUE; + break; + default: + return 0; + } + /* mutual code */ + info->mark = strtoul(optarg, &end, 0); + if (*end != '\0' || end == optarg) + xtables_error(PARAMETER_PROBLEM, "Bad MARK value '%s'", + optarg); + + mark_supplied = 1; + return 1; +} + +static void brmark_print(const void *ip, const struct xt_entry_target *target, + int numeric) +{ + struct ebt_mark_t_info *info = (struct ebt_mark_t_info *)target->data; + int tmp; + + tmp = info->target & ~EBT_VERDICT_BITS; + if (tmp == MARK_SET_VALUE) + printf("--mark-set"); + else if (tmp == MARK_OR_VALUE) + printf("--mark-or"); + else if (tmp == MARK_XOR_VALUE) + printf("--mark-xor"); + else if (tmp == MARK_AND_VALUE) + printf("--mark-and"); + else + xtables_error(PARAMETER_PROBLEM, "Unknown mark action"); + + printf(" 0x%lx", info->mark); + tmp = info->target | ~EBT_VERDICT_BITS; + printf(" --mark-target %s", ebt_target_name(tmp)); +} + +static void brmark_final_check(unsigned int flags) +{ + if (mark_supplied == 0) + xtables_error(PARAMETER_PROBLEM, "No mark value supplied"); + + if (!flags) + xtables_error(PARAMETER_PROBLEM, + "You must specify some option"); +} + +static struct xtables_target brmark_target = { + .name = "mark", + .revision = 0, + .version = XTABLES_VERSION, + .family = NFPROTO_BRIDGE, + .size = XT_ALIGN(sizeof(struct ebt_mark_t_info)), + .userspacesize = XT_ALIGN(sizeof(struct ebt_mark_t_info)), + .help = brmark_print_help, + .init = brmark_init, + .parse = brmark_parse, + .final_check = brmark_final_check, + .print = brmark_print, + .extra_opts = brmark_opts, +}; + +void _init(void) +{ + xtables_register_target(&brmark_target); +} diff --git a/extensions/libebt_mark_m.c b/extensions/libebt_mark_m.c new file mode 100644 index 00000000..ef9eb6a6 --- /dev/null +++ b/extensions/libebt_mark_m.c @@ -0,0 +1,118 @@ +/* ebt_mark_m + * + * Authors: + * Bart De Schuymer <bdschuym@pandora.be> + * + * July, 2002 + * + * Adapted by Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com> + * to use libxtables for ebtables-compat in 2015. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <getopt.h> +#include <xtables.h> +#include <linux/netfilter_bridge/ebt_mark_m.h> + +#define MARK '1' + +static struct option brmark_m_opts[] = { + { .name = "mark", .has_arg = true, .val = MARK }, + XT_GETOPT_TABLEEND, +}; + +static void brmark_m_print_help(void) +{ + printf( +"mark option:\n" +"--mark [!] [value][/mask]: Match nfmask value (see man page)\n"); +} + +static void brmark_m_init(struct xt_entry_match *match) +{ + struct ebt_mark_m_info *info = (struct ebt_mark_m_info *)match->data; + + info->mark = 0; + info->mask = 0; + info->invert = 0; + info->bitmask = 0; +} + +#define OPT_MARK 0x01 +static int +brmark_m_parse(int c, char **argv, int invert, unsigned int *flags, + const void *entry, struct xt_entry_match **match) +{ + struct ebt_mark_m_info *info = (struct ebt_mark_m_info *) + (*match)->data; + char *end; + + switch (c) { + case MARK: + if (invert) + info->invert = 1; + info->mark = strtoul(optarg, &end, 0); + info->bitmask = EBT_MARK_AND; + if (*end == '/') { + if (end == optarg) + info->bitmask = EBT_MARK_OR; + info->mask = strtoul(end+1, &end, 0); + } else { + info->mask = 0xffffffff; + } + if (*end != '\0' || end == optarg) + xtables_error(PARAMETER_PROBLEM, "Bad mark value '%s'", + optarg); + break; + default: + return 0; + } + + *flags |= info->bitmask; + return 1; +} + +static void brmark_m_final_check(unsigned int flags) +{ + if (!flags) + xtables_error(PARAMETER_PROBLEM, + "You must specify proper arguments"); +} + +static void brmark_m_print(const void *ip, const struct xt_entry_match *match, + int numeric) +{ + struct ebt_mark_m_info *info = (struct ebt_mark_m_info *)match->data; + + printf("--mark "); + if (info->invert) + printf("! "); + if (info->bitmask == EBT_MARK_OR) + printf("/0x%lx ", info->mask); + else if (info->mask != 0xffffffff) + printf("0x%lx/0x%lx ", info->mark, info->mask); + else + printf("0x%lx ", info->mark); +} + +static struct xtables_match brmark_m_match = { + .name = "mark_m", + .revision = 0, + .version = XTABLES_VERSION, + .family = NFPROTO_BRIDGE, + .size = XT_ALIGN(sizeof(struct ebt_mark_m_info)), + .userspacesize = XT_ALIGN(sizeof(struct ebt_mark_m_info)), + .init = brmark_m_init, + .help = brmark_m_print_help, + .parse = brmark_m_parse, + .final_check = brmark_m_final_check, + .print = brmark_m_print, + .extra_opts = brmark_m_opts, +}; + +void _init(void) +{ + xtables_register_match(&brmark_m_match); +} diff --git a/extensions/libebt_nflog.c b/extensions/libebt_nflog.c new file mode 100644 index 00000000..72bf3724 --- /dev/null +++ b/extensions/libebt_nflog.c @@ -0,0 +1,144 @@ +/* ebt_nflog + * + * Authors: + * Peter Warasin <peter@endian.com> + * + * February, 2008 + * + * Based on: + * ebt_ulog.c, (C) 2004, Bart De Schuymer <bdschuym@pandora.be> + * libxt_NFLOG.c + * + * Adapted to libxtables for ebtables-compat in 2015 by + * Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com> + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <getopt.h> +#include <xtables.h> +#include "iptables/nft.h" +#include "iptables/nft-bridge.h" +#include <linux/netfilter_bridge/ebt_nflog.h> + +enum { + NFLOG_GROUP = 0x1, + NFLOG_PREFIX = 0x2, + NFLOG_RANGE = 0x4, + NFLOG_THRESHOLD = 0x8, + NFLOG_NFLOG = 0x16, +}; + +static struct option brnflog_opts[] = { + { .name = "nflog-group", .has_arg = true, .val = NFLOG_GROUP}, + { .name = "nflog-prefix", .has_arg = true, .val = NFLOG_PREFIX}, + { .name = "nflog-range", .has_arg = true, .val = NFLOG_RANGE}, + { .name = "nflog-threshold", .has_arg = true, .val = NFLOG_THRESHOLD}, + { .name = "nflog", .has_arg = false, .val = NFLOG_NFLOG}, + XT_GETOPT_TABLEEND, +}; + +static void brnflog_help(void) +{ + printf("nflog options:\n" + "--nflog : use the default nflog parameters\n" + "--nflog-prefix prefix : Prefix string for log message\n" + "--nflog-group group : NETLINK group used for logging\n" + "--nflog-range range : Number of byte to copy\n" + "--nflog-threshold : Message threshold of" + "in-kernel queue\n"); +} + +static void brnflog_init(struct xt_entry_target *t) +{ + struct ebt_nflog_info *info = (struct ebt_nflog_info *)t->data; + + info->prefix[0] = '\0'; + info->group = EBT_NFLOG_DEFAULT_GROUP; + info->threshold = EBT_NFLOG_DEFAULT_THRESHOLD; +} + +static int brnflog_parse(int c, char **argv, int invert, unsigned int *flags, + const void *entry, struct xt_entry_target **target) +{ + struct ebt_nflog_info *info = (struct ebt_nflog_info *)(*target)->data; + unsigned int i; + + if (invert) + xtables_error(PARAMETER_PROBLEM, + "The use of '!' makes no sense for the" + " nflog watcher"); + + switch (c) { + case NFLOG_PREFIX: + EBT_CHECK_OPTION(flags, NFLOG_PREFIX); + if (strlen(optarg) > EBT_NFLOG_PREFIX_SIZE - 1) + xtables_error(PARAMETER_PROBLEM, + "Prefix too long for nflog-prefix"); + strncpy(info->prefix, optarg, EBT_NFLOG_PREFIX_SIZE); + break; + case NFLOG_GROUP: + EBT_CHECK_OPTION(flags, NFLOG_GROUP); + if (!xtables_strtoui(optarg, NULL, &i, 1, UINT32_MAX)) + xtables_error(PARAMETER_PROBLEM, + "--nflog-group must be a number!"); + info->group = i; + break; + case NFLOG_RANGE: + EBT_CHECK_OPTION(flags, NFLOG_RANGE); + if (!xtables_strtoui(optarg, NULL, &i, 1, UINT32_MAX)) + xtables_error(PARAMETER_PROBLEM, + "--nflog-range must be a number!"); + info->len = i; + break; + case NFLOG_THRESHOLD: + EBT_CHECK_OPTION(flags, NFLOG_THRESHOLD); + if (!xtables_strtoui(optarg, NULL, &i, 1, UINT32_MAX)) + xtables_error(PARAMETER_PROBLEM, + "--nflog-threshold must be a number!"); + info->threshold = i; + break; + case NFLOG_NFLOG: + EBT_CHECK_OPTION(flags, NFLOG_NFLOG); + break; + default: + return 0; + } + return 1; +} + +static void +brnflog_print(const void *ip, const struct xt_entry_target *target, + int numeric) +{ + struct ebt_nflog_info *info = (struct ebt_nflog_info *)target->data; + + if (info->prefix[0] != '\0') + printf("--nflog-prefix \"%s\" ", info->prefix); + if (info->group) + printf("--nflog-group %d ", info->group); + if (info->len) + printf("--nflog-range %d ", info->len); + if (info->threshold != EBT_NFLOG_DEFAULT_THRESHOLD) + printf("--nflog-threshold %d ", info->threshold); +} + +static struct xtables_target brnflog_watcher = { + .name = "nflog", + .revision = 0, + .version = XTABLES_VERSION, + .family = NFPROTO_BRIDGE, + .size = XT_ALIGN(sizeof(struct ebt_nflog_info)), + .userspacesize = XT_ALIGN(sizeof(struct ebt_nflog_info)), + .init = brnflog_init, + .help = brnflog_help, + .parse = brnflog_parse, + .print = brnflog_print, + .extra_opts = brnflog_opts, +}; + +void _init(void) +{ + xtables_register_target(&brnflog_watcher); +} diff --git a/extensions/libip6t_DNAT.t b/extensions/libip6t_DNAT.t new file mode 100644 index 00000000..3141c299 --- /dev/null +++ b/extensions/libip6t_DNAT.t @@ -0,0 +1,8 @@ +:PREROUTING +*nat +-j DNAT --to-destination dead::beef;=;OK +-j DNAT --to-destination dead::beef-dead::fee7;=;OK +-p tcp -j DNAT --to-destination [dead::beef]:1025-65535;=;OK +-p tcp -j DNAT --to-destination [dead::beef-dead::fee7]:1025-65535;=;OK +-p tcp -j DNAT --to-destination [dead::beef-dead::fee7]:1025-65536;;FAIL +-j DNAT;;FAIL diff --git a/extensions/libip6t_DNPT.c b/extensions/libip6t_DNPT.c index a442de6d..d045e44c 100644 --- a/extensions/libip6t_DNPT.c +++ b/extensions/libip6t_DNPT.c @@ -52,9 +52,9 @@ static void DNPT_print(const void *ip, const struct xt_entry_target *target, { const struct ip6t_npt_tginfo *npt = (const void *)target->data; - printf("src-pfx %s/%u ", xtables_ip6addr_to_numeric(&npt->src_pfx.in6), + printf(" DNPT src-pfx %s/%u", xtables_ip6addr_to_numeric(&npt->src_pfx.in6), npt->src_pfx_len); - printf("dst-pfx %s/%u ", xtables_ip6addr_to_numeric(&npt->dst_pfx.in6), + printf(" dst-pfx %s/%u", xtables_ip6addr_to_numeric(&npt->dst_pfx.in6), npt->dst_pfx_len); } @@ -65,12 +65,12 @@ static void DNPT_save(const void *ip, const struct xt_entry_target *target) if (memcmp(&info->src_pfx.in6, &zero_addr, sizeof(zero_addr)) != 0 || info->src_pfx_len != 0) - printf("--src-pfx %s/%u ", + printf(" --src-pfx %s/%u", xtables_ip6addr_to_numeric(&info->src_pfx.in6), info->src_pfx_len); if (memcmp(&info->dst_pfx.in6, &zero_addr, sizeof(zero_addr)) != 0 || info->dst_pfx_len != 0) - printf("--dst-pfx %s/%u ", + printf(" --dst-pfx %s/%u", xtables_ip6addr_to_numeric(&info->dst_pfx.in6), info->dst_pfx_len); } diff --git a/extensions/libip6t_DNPT.t b/extensions/libip6t_DNPT.t new file mode 100644 index 00000000..0406dc90 --- /dev/null +++ b/extensions/libip6t_DNPT.t @@ -0,0 +1,7 @@ +:PREROUTING +*mangle +-j DNPT --src-pfx dead::/64 --dst-pfx 1c3::/64;=;OK +-j DNPT --src-pfx dead::beef --dst-pfx 1c3::/64;;FAIL +-j DNPT --src-pfx dead::/64;;FAIL +-j DNPT --dst-pfx dead::/64;;FAIL +-j DNPT;;FAIL diff --git a/extensions/libip6t_HL.t b/extensions/libip6t_HL.t new file mode 100644 index 00000000..4e529f88 --- /dev/null +++ b/extensions/libip6t_HL.t @@ -0,0 +1,10 @@ +:PREROUTING,INPUT,FORWARD,OUTPUT,POSTROUTING +*mangle +-j HL --hl-set 42;=;OK +-j HL --hl-inc 1;=;OK +-j HL --hl-dec 1;=;OK +-j HL --hl-set 256;;FAIL +-j HL --hl-inc 0;;FAIL +-j HL --hl-dec 0;;FAIL +-j HL --hl-dec 1 --hl-inc 1;;FAIL +-j HL --hl-set --hl-inc 1;;FAIL diff --git a/extensions/libip6t_MASQUERADE.t b/extensions/libip6t_MASQUERADE.t new file mode 100644 index 00000000..46502040 --- /dev/null +++ b/extensions/libip6t_MASQUERADE.t @@ -0,0 +1,8 @@ +:POSTROUTING +*nat +-j MASQUERADE;=;OK +-j MASQUERADE --random;=;OK +-p tcp -j MASQUERADE --to-ports 1024;=;OK +-p udp -j MASQUERADE --to-ports 1024-65535;=;OK +-p udp -j MASQUERADE --to-ports 1024-65536;;FAIL +-p udp -j MASQUERADE --to-ports -1;;FAIL diff --git a/extensions/libip6t_NETMAP.t b/extensions/libip6t_NETMAP.t new file mode 100644 index 00000000..043562d2 --- /dev/null +++ b/extensions/libip6t_NETMAP.t @@ -0,0 +1,4 @@ +:PREROUTING,INPUT,OUTPUT,POSTROUTING +*nat +-j NETMAP --to dead::/64;=;OK +-j NETMAP --to dead::beef;=;OK diff --git a/extensions/libip6t_REDIRECT.t b/extensions/libip6t_REDIRECT.t new file mode 100644 index 00000000..a0fb0ed1 --- /dev/null +++ b/extensions/libip6t_REDIRECT.t @@ -0,0 +1,6 @@ +:PREROUTING,OUTPUT +*nat +-p tcp -j REDIRECT --to-ports 42;=;OK +-p udp -j REDIRECT --to-ports 42-1234;=;OK +-p tcp -j REDIRECT --to-ports 42-1234 --random;=;OK +-j REDIRECT --to-ports 42;;FAIL diff --git a/extensions/libip6t_SNAT.t b/extensions/libip6t_SNAT.t new file mode 100644 index 00000000..bb080497 --- /dev/null +++ b/extensions/libip6t_SNAT.t @@ -0,0 +1,8 @@ +:POSTROUTING +*nat +-j SNAT --to-source dead::beef;=;OK +-j SNAT --to-source dead::beef-dead::fee7;=;OK +-p tcp -j SNAT --to-source [dead::beef]:1025-65535;=;OK +-p tcp -j SNAT --to-source [dead::beef-dead::fee7]:1025-65535;=;OK +-p tcp -j SNAT --to-source [dead::beef-dead::fee7]:1025-65536;;FAIL +-j SNAT;;FAIL diff --git a/extensions/libip6t_SNPT.c b/extensions/libip6t_SNPT.c index 4f10de03..65f787d9 100644 --- a/extensions/libip6t_SNPT.c +++ b/extensions/libip6t_SNPT.c @@ -52,9 +52,9 @@ static void SNPT_print(const void *ip, const struct xt_entry_target *target, { const struct ip6t_npt_tginfo *npt = (const void *)target->data; - printf("src-pfx %s/%u ", xtables_ip6addr_to_numeric(&npt->src_pfx.in6), + printf(" SNPT src-pfx %s/%u", xtables_ip6addr_to_numeric(&npt->src_pfx.in6), npt->src_pfx_len); - printf("dst-pfx %s/%u ", xtables_ip6addr_to_numeric(&npt->dst_pfx.in6), + printf(" dst-pfx %s/%u", xtables_ip6addr_to_numeric(&npt->dst_pfx.in6), npt->dst_pfx_len); } @@ -65,12 +65,12 @@ static void SNPT_save(const void *ip, const struct xt_entry_target *target) if (memcmp(&info->src_pfx.in6, &zero_addr, sizeof(zero_addr)) != 0 || info->src_pfx_len != 0) - printf("--src-pfx %s/%u ", + printf(" --src-pfx %s/%u", xtables_ip6addr_to_numeric(&info->src_pfx.in6), info->src_pfx_len); if (memcmp(&info->dst_pfx.in6, &zero_addr, sizeof(zero_addr)) != 0 || info->dst_pfx_len != 0) - printf("--dst-pfx %s/%u ", + printf(" --dst-pfx %s/%u", xtables_ip6addr_to_numeric(&info->dst_pfx.in6), info->dst_pfx_len); } diff --git a/extensions/libip6t_SNPT.t b/extensions/libip6t_SNPT.t new file mode 100644 index 00000000..7ed6d0c9 --- /dev/null +++ b/extensions/libip6t_SNPT.t @@ -0,0 +1,7 @@ +:INPUT,POSTROUTING +*mangle +-j SNPT --src-pfx dead::/64 --dst-pfx 1c3::/64;=;OK +-j SNPT --src-pfx dead::beef --dst-pfx 1c3::/64;;FAIL +-j SNPT --src-pfx dead::/64;;FAIL +-j SNPT --dst-pfx dead::/64;;FAIL +-j SNPT;;FAIL diff --git a/extensions/libip6t_dst.c b/extensions/libip6t_dst.c index 3fd4c019..fe7e3403 100644 --- a/extensions/libip6t_dst.c +++ b/extensions/libip6t_dst.c @@ -112,6 +112,8 @@ static void dst_parse(struct xt_option_call *cb) xtables_option_parse(cb); switch (cb->entry->id) { case O_DSTLEN: + if (cb->invert) + optinfo->invflags |= IP6T_OPTS_INV_LEN; optinfo->flags |= IP6T_OPTS_LEN; break; case O_DSTOPTS: diff --git a/extensions/libip6t_dst.t b/extensions/libip6t_dst.t new file mode 100644 index 00000000..0b0013b5 --- /dev/null +++ b/extensions/libip6t_dst.t @@ -0,0 +1,5 @@ +:INPUT,FORWARD,OUTPUT +-m dst --dst-len 0;=;OK +-m dst --dst-opts 149:92,12:12,123:12;=;OK +-m dst ! --dst-len 42;=;OK +-m dst --dst-len 42 --dst-opts 149:92,12:12,123:12;=;OK diff --git a/extensions/libip6t_frag.t b/extensions/libip6t_frag.t new file mode 100644 index 00000000..dab49894 --- /dev/null +++ b/extensions/libip6t_frag.t @@ -0,0 +1,11 @@ +:INPUT,FORWARD,OUTPUT +-m frag --fragid 1:42;=;OK +-m frag --fraglen 42;=;OK +-m frag --fragres;=;OK +-m frag --fragfirst;=;OK +-m frag --fragmore;=;OK +-m frag --fraglast;=;OK +-m frag ! --fragid 1 ! --fraglen 42 --fragres --fragfirst;=;OK +-m frag --fragfirst --fragmore;=;OK +-m frag --fragfirst --fraglast;=;OK +-m frag --fraglast --fragmore;;FAIL diff --git a/extensions/libip6t_hbh.t b/extensions/libip6t_hbh.t new file mode 100644 index 00000000..4b58f25a --- /dev/null +++ b/extensions/libip6t_hbh.t @@ -0,0 +1,5 @@ +:INPUT,FORWARD,OUTPUT +-m hbh;=;OK +-m hbh --hbh-len 42;=;OK +-m hbh ! --hbh-len 42;=;OK +-m hbh --hbh-len 42 --hbh-opts 1:2,23:42,4:6,8:10,42,23,4:5;=;OK diff --git a/extensions/libip6t_hl.t b/extensions/libip6t_hl.t new file mode 100644 index 00000000..b02816af --- /dev/null +++ b/extensions/libip6t_hl.t @@ -0,0 +1,8 @@ +:INPUT,FORWARD,OUTPUT +-m hl;;FAIL +-m hl --hl-eq 42;=;OK +-m hl ! --hl-eq 42;=;OK +-m hl --hl-lt 42;=;OK +-m hl --hl-gt 42;=;OK +-m hl --hl-gt 42 --hl-eq 42;;FAIL +-m hl --hl-gt;;FAIL diff --git a/extensions/libip6t_icmp6.t b/extensions/libip6t_icmp6.t new file mode 100644 index 00000000..028cfc16 --- /dev/null +++ b/extensions/libip6t_icmp6.t @@ -0,0 +1,6 @@ +:INPUT,FORWARD,OUTPUT +-m icmpv6;;FAIL +-p ipv6-icmp -m icmp6 --icmpv6-type 1/0;=;OK +-p ipv6-icmp -m icmp6 --icmpv6-type 2;=;OK +# cannot use option twice: +-p ipv6-icmp -m icmp6 --icmpv6-type no-route --icmpv6-type packet-too-big;;FAIL diff --git a/extensions/libip6t_ipv6header.t b/extensions/libip6t_ipv6header.t new file mode 100644 index 00000000..67fa4799 --- /dev/null +++ b/extensions/libip6t_ipv6header.t @@ -0,0 +1,4 @@ +:INPUT,FORWARD,OUTPUT +-m ipv6header --header hop-by-hop;=;OK +-m ipv6header --header hop-by-hop --soft;=;OK +-m ipv6header --header ipv6-nonxt;=;OK diff --git a/extensions/libip6t_mh.t b/extensions/libip6t_mh.t new file mode 100644 index 00000000..6b76d13d --- /dev/null +++ b/extensions/libip6t_mh.t @@ -0,0 +1,6 @@ +:INPUT,FORWARD,OUTPUT +-m mh;;FAIL +-p mobility-header -m mh;=;OK +-p mobility-header -m mh --mh-type 1;=;OK +-p mobility-header -m mh ! --mh-type 4;=;OK +-p mobility-header -m mh --mh-type 4:123;=;OK diff --git a/extensions/libip6t_rt.t b/extensions/libip6t_rt.t new file mode 100644 index 00000000..71701388 --- /dev/null +++ b/extensions/libip6t_rt.t @@ -0,0 +1,4 @@ +:INPUT,FORWARD,OUTPUT +-m rt --rt-type 0 --rt-segsleft 1:23 --rt-len 42 --rt-0-res;=;OK +-m rt --rt-type 0 ! --rt-segsleft 1:23 ! --rt-len 42 --rt-0-res;=;OK +-m rt ! --rt-type 1 ! --rt-segsleft 12:23 ! --rt-len 42;=;OK diff --git a/extensions/libipt_MIRROR.c b/extensions/libipt_MIRROR.c deleted file mode 100644 index fb78751d..00000000 --- a/extensions/libipt_MIRROR.c +++ /dev/null @@ -1,15 +0,0 @@ -/* Shared library add-on to iptables to add MIRROR target support. */ -#include <xtables.h> - -static struct xtables_target mirror_tg_reg = { - .name = "MIRROR", - .version = XTABLES_VERSION, - .family = NFPROTO_IPV4, - .size = XT_ALIGN(0), - .userspacesize = XT_ALIGN(0), -}; - -void _init(void) -{ - xtables_register_target(&mirror_tg_reg); -} diff --git a/extensions/libipt_MIRROR.man b/extensions/libipt_MIRROR.man deleted file mode 100644 index 7b720bcb..00000000 --- a/extensions/libipt_MIRROR.man +++ /dev/null @@ -1,12 +0,0 @@ -This is an experimental demonstration target which inverts the source -and destination fields in the IP header and retransmits the packet. -It is only valid in the -.BR INPUT , -.B FORWARD -and -.B PREROUTING -chains, and user-defined chains which are only called from those -chains. Note that the outgoing packets are -.B NOT -seen by any packet filtering chains, connection tracking or NAT, to -avoid loops and other problems. diff --git a/extensions/libipt_NETMAP.t b/extensions/libipt_NETMAP.t new file mode 100644 index 00000000..31924b98 --- /dev/null +++ b/extensions/libipt_NETMAP.t @@ -0,0 +1,4 @@ +:PREROUTING,INPUT,OUTPUT,POSTROUTING +*nat +-j NETMAP --to 1.2.3.0/24;=;OK +-j NETMAP --to 1.2.3.4;=;OK diff --git a/extensions/libipt_REDIRECT.t b/extensions/libipt_REDIRECT.t new file mode 100644 index 00000000..a0fb0ed1 --- /dev/null +++ b/extensions/libipt_REDIRECT.t @@ -0,0 +1,6 @@ +:PREROUTING,OUTPUT +*nat +-p tcp -j REDIRECT --to-ports 42;=;OK +-p udp -j REDIRECT --to-ports 42-1234;=;OK +-p tcp -j REDIRECT --to-ports 42-1234 --random;=;OK +-j REDIRECT --to-ports 42;;FAIL diff --git a/extensions/libipt_SAME.c b/extensions/libipt_SAME.c deleted file mode 100644 index 5d5bf630..00000000 --- a/extensions/libipt_SAME.c +++ /dev/null @@ -1,186 +0,0 @@ -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <xtables.h> -#include <linux/netfilter/nf_nat.h> -#include <linux/netfilter_ipv4/ipt_SAME.h> - -enum { - O_TO_ADDR = 0, - O_NODST, - O_RANDOM, - F_TO_ADDR = 1 << O_TO_ADDR, - F_RANDOM = 1 << O_RANDOM, -}; - -static void SAME_help(void) -{ - printf( -"SAME target options:\n" -" --to <ipaddr>-<ipaddr>\n" -" Addresses to map source to.\n" -" May be specified more than\n" -" once for multiple ranges.\n" -" --nodst\n" -" Don't use destination-ip in\n" -" source selection\n" -" --random\n" -" Randomize source port\n"); -} - -static const struct xt_option_entry SAME_opts[] = { - {.name = "to", .id = O_TO_ADDR, .type = XTTYPE_STRING, - .flags = XTOPT_MAND}, - {.name = "nodst", .id = O_NODST, .type = XTTYPE_NONE}, - {.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE}, - XTOPT_TABLEEND, -}; - -/* Parses range of IPs */ -static void parse_to(const char *orig_arg, struct nf_nat_ipv4_range *range) -{ - char *dash, *arg; - const struct in_addr *ip; - - arg = strdup(orig_arg); - if (arg == NULL) - xtables_error(RESOURCE_PROBLEM, "strdup"); - range->flags |= NF_NAT_RANGE_MAP_IPS; - dash = strchr(arg, '-'); - - if (dash) - *dash = '\0'; - - ip = xtables_numeric_to_ipaddr(arg); - if (!ip) - xtables_error(PARAMETER_PROBLEM, "Bad IP address \"%s\"\n", - arg); - range->min_ip = ip->s_addr; - - if (dash) { - ip = xtables_numeric_to_ipaddr(dash+1); - if (!ip) - xtables_error(PARAMETER_PROBLEM, "Bad IP address \"%s\"\n", - dash+1); - } - range->max_ip = ip->s_addr; - if (dash) - if (range->min_ip > range->max_ip) - xtables_error(PARAMETER_PROBLEM, "Bad IP range \"%s-%s\"\n", - arg, dash+1); - free(arg); -} - -static void SAME_parse(struct xt_option_call *cb) -{ - struct ipt_same_info *mr = cb->data; - unsigned int count; - - xtables_option_parse(cb); - switch (cb->entry->id) { - case O_TO_ADDR: - if (mr->rangesize == IPT_SAME_MAX_RANGE) - xtables_error(PARAMETER_PROBLEM, - "Too many ranges specified, maximum " - "is %i ranges.\n", - IPT_SAME_MAX_RANGE); - parse_to(cb->arg, &mr->range[mr->rangesize]); - mr->rangesize++; - break; - case O_NODST: - mr->info |= IPT_SAME_NODST; - break; - case O_RANDOM: - for (count=0; count < mr->rangesize; count++) - mr->range[count].flags |= NF_NAT_RANGE_PROTO_RANDOM; - break; - } -} - -static void SAME_fcheck(struct xt_fcheck_call *cb) -{ - static const unsigned int f = F_TO_ADDR | F_RANDOM; - struct ipt_same_info *mr = cb->data; - unsigned int count; - - if ((cb->xflags & f) == f) - for (count = 0; count < mr->rangesize; ++count) - mr->range[count].flags |= NF_NAT_RANGE_PROTO_RANDOM; -} - -static void SAME_print(const void *ip, const struct xt_entry_target *target, - int numeric) -{ - unsigned int count; - const struct ipt_same_info *mr = (const void *)target->data; - int random_selection = 0; - - printf(" same:"); - - for (count = 0; count < mr->rangesize; count++) { - const struct nf_nat_ipv4_range *r = &mr->range[count]; - struct in_addr a; - - a.s_addr = r->min_ip; - - printf("%s", xtables_ipaddr_to_numeric(&a)); - a.s_addr = r->max_ip; - - if (r->min_ip != r->max_ip) - printf("-%s", xtables_ipaddr_to_numeric(&a)); - if (r->flags & NF_NAT_RANGE_PROTO_RANDOM) - random_selection = 1; - } - - if (mr->info & IPT_SAME_NODST) - printf(" nodst"); - - if (random_selection) - printf(" random"); -} - -static void SAME_save(const void *ip, const struct xt_entry_target *target) -{ - unsigned int count; - const struct ipt_same_info *mr = (const void *)target->data; - int random_selection = 0; - - for (count = 0; count < mr->rangesize; count++) { - const struct nf_nat_ipv4_range *r = &mr->range[count]; - struct in_addr a; - - a.s_addr = r->min_ip; - printf(" --to %s", xtables_ipaddr_to_numeric(&a)); - a.s_addr = r->max_ip; - - if (r->min_ip != r->max_ip) - printf("-%s", xtables_ipaddr_to_numeric(&a)); - if (r->flags & NF_NAT_RANGE_PROTO_RANDOM) - random_selection = 1; - } - - if (mr->info & IPT_SAME_NODST) - printf(" --nodst"); - - if (random_selection) - printf(" --random"); -} - -static struct xtables_target same_tg_reg = { - .name = "SAME", - .version = XTABLES_VERSION, - .family = NFPROTO_IPV4, - .size = XT_ALIGN(sizeof(struct ipt_same_info)), - .userspacesize = XT_ALIGN(sizeof(struct ipt_same_info)), - .help = SAME_help, - .x6_parse = SAME_parse, - .x6_fcheck = SAME_fcheck, - .print = SAME_print, - .save = SAME_save, - .x6_options = SAME_opts, -}; - -void _init(void) -{ - xtables_register_target(&same_tg_reg); -} diff --git a/extensions/libipt_SAME.man b/extensions/libipt_SAME.man deleted file mode 100644 index a99dc73f..00000000 --- a/extensions/libipt_SAME.man +++ /dev/null @@ -1,17 +0,0 @@ -Similar to SNAT/DNAT depending on chain: it takes a range of addresses -(`\-\-to 1.2.3.4\-1.2.3.7') and gives a client the same -source-/destination-address for each connection. -.PP -N.B.: The DNAT target's \fB\-\-persistent\fP option replaced the SAME target. -.TP -\fB\-\-to\fP \fIipaddr\fP[\fB\-\fP\fIipaddr\fP] -Addresses to map source to. May be specified more than once for -multiple ranges. -.TP -\fB\-\-nodst\fP -Don't use the destination-ip in the calculations when selecting the -new source-ip -.TP -\fB\-\-random\fP -Port mapping will be forcibly randomized to avoid attacks based on -port prediction (kernel >= 2.6.21). diff --git a/extensions/libipt_TTL.t b/extensions/libipt_TTL.t new file mode 100644 index 00000000..36809792 --- /dev/null +++ b/extensions/libipt_TTL.t @@ -0,0 +1,10 @@ +:PREROUTING,INPUT,FORWARD,OUTPUT,POSTROUTING +*mangle +-j TTL --ttl-set 42;=;OK +-j TTL --ttl-inc 1;=;OK +-j TTL --ttl-dec 1;=;OK +-j TTL --ttl-set 256;;FAIL +-j TTL --ttl-inc 0;;FAIL +-j TTL --ttl-dec 0;;FAIL +-j TTL --ttl-dec 1 --ttl-inc 1;;FAIL +-j TTL --ttl-set --ttl-inc 1;;FAIL diff --git a/extensions/libipt_realm.t b/extensions/libipt_realm.t new file mode 100644 index 00000000..ca666407 --- /dev/null +++ b/extensions/libipt_realm.t @@ -0,0 +1,4 @@ +:INPUT,FORWARD,OUTPUT +-m realm --realm 0x1/0x2a;=;OK +-m realm --realm 0x2a;=;OK +-m realm;;FAIL diff --git a/extensions/libipt_unclean.c b/extensions/libipt_unclean.c deleted file mode 100644 index bc4a4a08..00000000 --- a/extensions/libipt_unclean.c +++ /dev/null @@ -1,15 +0,0 @@ -/* Shared library add-on to iptables for unclean. */ -#include <xtables.h> - -static struct xtables_match unclean_mt_reg = { - .name = "unclean", - .version = XTABLES_VERSION, - .family = NFPROTO_IPV4, - .size = XT_ALIGN(0), - .userspacesize = XT_ALIGN(0), -}; - -void _init(void) -{ - xtables_register_match(&unclean_mt_reg); -} diff --git a/extensions/libipt_unclean.man b/extensions/libipt_unclean.man deleted file mode 100644 index 3fecd554..00000000 --- a/extensions/libipt_unclean.man +++ /dev/null @@ -1,2 +0,0 @@ -This module takes no options, but attempts to match packets which seem -malformed or unusual. This is regarded as experimental. diff --git a/extensions/libxt_CLASSIFY.c b/extensions/libxt_CLASSIFY.c index e04657ae..cd016d8f 100644 --- a/extensions/libxt_CLASSIFY.c +++ b/extensions/libxt_CLASSIFY.c @@ -73,20 +73,40 @@ CLASSIFY_save(const void *ip, const struct xt_entry_target *target) TC_H_MAJ(clinfo->priority)>>16, TC_H_MIN(clinfo->priority)); } -static struct xtables_target classify_target = { - .family = NFPROTO_UNSPEC, - .name = "CLASSIFY", - .version = XTABLES_VERSION, - .size = XT_ALIGN(sizeof(struct xt_classify_target_info)), - .userspacesize = XT_ALIGN(sizeof(struct xt_classify_target_info)), - .help = CLASSIFY_help, - .print = CLASSIFY_print, - .save = CLASSIFY_save, - .x6_parse = CLASSIFY_parse, - .x6_options = CLASSIFY_opts, +static void +arpCLASSIFY_print(const void *ip, const struct xt_entry_target *target, + int numeric) +{ + CLASSIFY_save(ip, target); +} + +static struct xtables_target classify_target[] = { + { + .family = NFPROTO_UNSPEC, + .name = "CLASSIFY", + .version = XTABLES_VERSION, + .size = XT_ALIGN(sizeof(struct xt_classify_target_info)), + .userspacesize = XT_ALIGN(sizeof(struct xt_classify_target_info)), + .help = CLASSIFY_help, + .print = CLASSIFY_print, + .save = CLASSIFY_save, + .x6_parse = CLASSIFY_parse, + .x6_options = CLASSIFY_opts, + }, + { + .family = NFPROTO_ARP, + .name = "CLASSIFY", + .version = XTABLES_VERSION, + .size = XT_ALIGN(sizeof(struct xt_classify_target_info)), + .userspacesize = XT_ALIGN(sizeof(struct xt_classify_target_info)), + .help = CLASSIFY_help, + .print = arpCLASSIFY_print, + .x6_parse = CLASSIFY_parse, + .x6_options = CLASSIFY_opts, + }, }; void _init(void) { - xtables_register_target(&classify_target); + xtables_register_targets(classify_target, ARRAY_SIZE(classify_target)); } diff --git a/extensions/libxt_CONNSECMARK.t b/extensions/libxt_CONNSECMARK.t new file mode 100644 index 00000000..2751b255 --- /dev/null +++ b/extensions/libxt_CONNSECMARK.t @@ -0,0 +1,5 @@ +:PREROUTING,FORWARD,OUTPUT,POSTROUTING +*mangle +-j CONNSECMARK --restore;=;OK +-j CONNSECMARK --save;=;OK +-j CONNSECMARK;;FAIL diff --git a/extensions/libxt_HMARK.t b/extensions/libxt_HMARK.t new file mode 100644 index 00000000..3bcf1dad --- /dev/null +++ b/extensions/libxt_HMARK.t @@ -0,0 +1,8 @@ +:INPUT,FORWARD,OUTPUT +-j HMARK;;FAIL +-j HMARK --hmark-src-prefix 32 --hmark-rnd 0x00000004 --hmark-mod 42;=;OK +-j HMARK --hmark-src-prefix 32 --hmark-dst-prefix 32 --hmark-sport-mask 0xffff --hmark-dport-mask 0xffff --hmark-proto-mask 0xffff --hmark-rnd 0x00000004 --hmark-mod 42 --hmark-offset 1 --hmark-tuple ct;=;OK +-j HMARK --hmark-src-prefix 32 --hmark-dst-prefix 32 --hmark-spi-mask 0x00000004 --hmark-proto-mask 0xffff --hmark-rnd 0x00000004 --hmark-mod 42 --hmark-offset 1 --hmark-tuple ct;=;OK +-j HMARK --hmark-src-prefix 1 --hmark-dst-prefix 2 --hmark-sport-mask 0x0003 --hmark-dport-mask 0x0004 --hmark-proto-mask 0x05 --hmark-rnd 0x00000004 --hmark-mod 42 --hmark-offset 1 --hmark-tuple ct;=;OK +# cannot mix in spi mask: +-j HMARK --hmark-src-prefix 32 --hmark-dst-prefix 32 --hmark-sport-mask 0xffff --hmark-dport-mask 0xffff --hmark-proto-mask 0xffff --hmark-rnd 0x00000004 --hmark-mod 42 --hmark-offset 1 --hmark-tuple ct --hmark-spi-mask 4;;FAIL diff --git a/extensions/libxt_IDLETIMER.t b/extensions/libxt_IDLETIMER.t new file mode 100644 index 00000000..6afd92c1 --- /dev/null +++ b/extensions/libxt_IDLETIMER.t @@ -0,0 +1,4 @@ +:INPUT,FORWARD,OUTPUT +-j IDLETIMER --timeout;;FAIL +-j IDLETIMER --timeout 42;;FAIL +-j IDLETIMER --timeout 42 --label foo;=;OK diff --git a/extensions/libxt_LED.t b/extensions/libxt_LED.t new file mode 100644 index 00000000..1f6705f4 --- /dev/null +++ b/extensions/libxt_LED.t @@ -0,0 +1,4 @@ +:INPUT,FORWARD,OUTPUT +-j LED;;FAIL +-j LED --led-trigger-id "foo";=;OK +-j LED --led-trigger-id "foo" --led-delay 42 --led-always-blink;=;OK diff --git a/extensions/libxt_RATEEST.t b/extensions/libxt_RATEEST.t new file mode 100644 index 00000000..c2b6bb34 --- /dev/null +++ b/extensions/libxt_RATEEST.t @@ -0,0 +1,2 @@ +:INPUT,FORWARD,OUTPUT +-j RATEEST --rateest-name RE1 --rateest-interval 250.0ms --rateest-ewmalog 500.0ms;=;OK diff --git a/extensions/libxt_SET.t b/extensions/libxt_SET.t new file mode 100644 index 00000000..30c27ca3 --- /dev/null +++ b/extensions/libxt_SET.t @@ -0,0 +1,3 @@ +:INPUT,FORWARD,OUTPUT +# fails: foo does not exist +-j SET --add-set foo src,dst;;FAIL diff --git a/extensions/libxt_SYNPROXY.t b/extensions/libxt_SYNPROXY.t new file mode 100644 index 00000000..dd8b0e76 --- /dev/null +++ b/extensions/libxt_SYNPROXY.t @@ -0,0 +1,3 @@ +:INPUT,FORWARD +-j SYNPROXY --sack-perm --timestamp --mss 1460 --wscale 9;;FAIL +-p tcp -m tcp --dport 42 -m conntrack --ctstate INVALID,UNTRACKED -j SYNPROXY --sack-perm --timestamp --wscale 9 --mss 1460;=;OK diff --git a/extensions/libxt_TCPMSS.t b/extensions/libxt_TCPMSS.t new file mode 100644 index 00000000..553a3452 --- /dev/null +++ b/extensions/libxt_TCPMSS.t @@ -0,0 +1,6 @@ +:FORWARD,OUTPUT,POSTROUTING +*mangle +-j TCPMSS;;FAIL +-p tcp -j TCPMSS --set-mss 42;;FAIL +-p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -j TCPMSS --set-mss 42;=;OK +-p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -j TCPMSS --clamp-mss-to-pmtu;=;OK diff --git a/extensions/libxt_TCPOPTSTRIP.t b/extensions/libxt_TCPOPTSTRIP.t new file mode 100644 index 00000000..b5c7a109 --- /dev/null +++ b/extensions/libxt_TCPOPTSTRIP.t @@ -0,0 +1,8 @@ +:PREROUTING,INPUT,FORWARD,OUTPUT,POSTROUTING +*mangle +-j TCPOPTSTRIP;;FAIL +-p tcp -j TCPOPTSTRIP;=;OK +-p tcp -j TCPOPTSTRIP --strip-options 2,3,4,5,6,7;=;OK +-p tcp -j TCPOPTSTRIP --strip-options 0;;FAIL +-p tcp -j TCPOPTSTRIP --strip-options 1;;FAIL +-p tcp -j TCPOPTSTRIP --strip-options 1,2;;FAIL diff --git a/extensions/libxt_TEE.c b/extensions/libxt_TEE.c index 92c7601c..66c060d3 100644 --- a/extensions/libxt_TEE.c +++ b/extensions/libxt_TEE.c @@ -99,7 +99,7 @@ static struct xtables_target tee_tg_reg[] = { .revision = 1, .family = NFPROTO_IPV4, .size = XT_ALIGN(sizeof(struct xt_tee_tginfo)), - .userspacesize = XT_ALIGN(sizeof(struct xt_tee_tginfo)), + .userspacesize = offsetof(struct xt_tee_tginfo, priv), .help = tee_tg_help, .print = tee_tg_print, .save = tee_tg_save, @@ -112,7 +112,7 @@ static struct xtables_target tee_tg_reg[] = { .revision = 1, .family = NFPROTO_IPV6, .size = XT_ALIGN(sizeof(struct xt_tee_tginfo)), - .userspacesize = XT_ALIGN(sizeof(struct xt_tee_tginfo)), + .userspacesize = offsetof(struct xt_tee_tginfo, priv), .help = tee_tg_help, .print = tee_tg6_print, .save = tee_tg6_save, diff --git a/extensions/libxt_TPROXY.t b/extensions/libxt_TPROXY.t new file mode 100644 index 00000000..12f82b1f --- /dev/null +++ b/extensions/libxt_TPROXY.t @@ -0,0 +1,5 @@ +:PREROUTING +*mangle +-j TPROXY --on-port 12345 --on-ip 10.0.0.1 --tproxy-mark 0x23/0xff;;FAIL +-p udp -j TPROXY --on-port 12345 --on-ip 10.0.0.1 --tproxy-mark 0x23/0xff;=;OK +-p tcp -m tcp --dport 2342 -j TPROXY --on-port 12345 --on-ip 10.0.0.1 --tproxy-mark 0x23/0xff;=;OK diff --git a/extensions/libxt_bpf.t b/extensions/libxt_bpf.t new file mode 100644 index 00000000..80361ad5 --- /dev/null +++ b/extensions/libxt_bpf.t @@ -0,0 +1,2 @@ +:INPUT,FORWARD,OUTPUT +-m bpf --bytecode "4,48 0 0 9,21 0 1 6,6 0 0 1,6 0 0 0";=;OK diff --git a/extensions/libxt_cgroup.man b/extensions/libxt_cgroup.man index 456a0311..d0eb09b2 100644 --- a/extensions/libxt_cgroup.man +++ b/extensions/libxt_cgroup.man @@ -2,13 +2,21 @@ [\fB!\fP] \fB\-\-cgroup\fP \fIfwid\fP Match corresponding cgroup for this packet. -Can be used to assign particular firewall policies for aggregated -task/jobs on the system. This allows for more fine-grained firewall -policies that only match for a subset of the system's processes. -fwid is the maker set through the net_cls cgroup's id. +Can be used in the OUTPUT chain to assign particular firewall +policies for aggregated task/jobs on the system. This allows +for more fine-grained firewall policies that only match for a +subset of the system's processes. fwid is the maker set through +the net_cls cgroup's id. + +\fBIMPORTANT\fP: when being used in the INPUT chain, the cgroup +matcher is currently only of limited functionality, meaning it +will only match on packets that are processed for local sockets +through early socket demuxing. Therefore, general usage on the +INPUT chain is disadviced unless the implications are well +understood. .PP Example: -.PP +.IP iptables \-A OUTPUT \-p tcp \-\-sport 80 \-m cgroup ! \-\-cgroup 1 \-j DROP .PP diff --git a/extensions/libxt_ecn.t b/extensions/libxt_ecn.t new file mode 100644 index 00000000..b32aea30 --- /dev/null +++ b/extensions/libxt_ecn.t @@ -0,0 +1,5 @@ +:INPUT,FORWARD,OUTPUT +-m ecn --ecn-tcp-cwr;;FAIL +-p tcp -m ecn --ecn-tcp-cwr;=;OK +-p tcp -m ecn --ecn-tcp-ece --ecn-tcp-cwr --ecn-ip-ect 2;=;OK +-p tcp -m ecn ! --ecn-tcp-ece ! --ecn-tcp-cwr ! --ecn-ip-ect 2;=;OK diff --git a/extensions/libxt_mac.t b/extensions/libxt_mac.t new file mode 100644 index 00000000..a5ec81d8 --- /dev/null +++ b/extensions/libxt_mac.t @@ -0,0 +1,5 @@ +:INPUT,FORWARD +-m mac --mac-source 42:01:02:03:04:05;=;OK +-m mac --mac-source 42:01:02:03:04;=;FAIL +-m mac --mac-source 42:01:02:03:04:05:06;=;FAIL +-m mac;;FAIL diff --git a/extensions/libxt_osf.t b/extensions/libxt_osf.t new file mode 100644 index 00000000..ede6d32c --- /dev/null +++ b/extensions/libxt_osf.t @@ -0,0 +1,4 @@ +:INPUT,FORWARD +-m osf --genre linux --ttl 0 --log 0;;FAIL +-p tcp -m osf --genre linux --ttl 0 --log 0;=;OK +-p tcp -m osf --genre linux --ttl 3 --log 0;;FAIL diff --git a/extensions/libxt_physdev.man b/extensions/libxt_physdev.man index 53beb2e5..06b778af 100644 --- a/extensions/libxt_physdev.man +++ b/extensions/libxt_physdev.man @@ -15,21 +15,13 @@ interface which begins with this name will match. If the packet didn't arrive through a bridge device, this packet won't match this option, unless '!' is used. .TP [\fB!\fP] \fB\-\-physdev\-out\fP \fIname\fP -Name of a bridge port via which a packet is going to be sent (for packets +Name of a bridge port via which a packet is going to be sent (for bridged packets entering the -.BR FORWARD , -.B OUTPUT +.BR FORWARD and .B POSTROUTING chains). If the interface name ends in a "+", then any -interface which begins with this name will match. Note that in the -.BR nat " and " mangle -.B OUTPUT -chains one cannot match on the bridge output port, however one can in the -.B "filter OUTPUT" -chain. If the packet won't leave by a bridge device or if it is yet unknown what -the output device will be, then the packet won't match this option, -unless '!' is used. +interface which begins with this name will match. .TP [\fB!\fP] \fB\-\-physdev\-is\-in\fP Matches if the packet has entered through a bridge interface. diff --git a/extensions/libxt_policy.t b/extensions/libxt_policy.t new file mode 100644 index 00000000..24a3e2f4 --- /dev/null +++ b/extensions/libxt_policy.t @@ -0,0 +1,5 @@ +:INPUT,FORWARD +-m policy --dir in --pol ipsec;=;OK +-m policy --dir in --pol ipsec --strict;;FAIL +-m policy --dir in --pol ipsec --strict --reqid 1 --spi 0x1 --proto esp --mode tunnel --tunnel-dst 10.0.0.0/8 --tunnel-src 10.0.0.0/8 --next --reqid 2;=;OK +-m policy --dir in --pol ipsec --strict --reqid 1 --spi 0x1 --proto esp --tunnel-dst 10.0.0.0/8;;FAIL diff --git a/extensions/libxt_quota.c b/extensions/libxt_quota.c index ff498da7..ff7dd2a3 100644 --- a/extensions/libxt_quota.c +++ b/extensions/libxt_quota.c @@ -37,7 +37,7 @@ quota_save(const void *ip, const struct xt_entry_match *match) const struct xt_quota_info *q = (const void *)match->data; if (q->flags & XT_QUOTA_INVERT) - printf("! "); + printf(" !"); printf(" --quota %llu", (unsigned long long) q->quota); } diff --git a/extensions/libxt_quota.t b/extensions/libxt_quota.t index 76f0ee95..c5684279 100644 --- a/extensions/libxt_quota.t +++ b/extensions/libxt_quota.t @@ -1,10 +1,7 @@ :INPUT,FORWARD,OUTPUT -m quota --quota 0;=;OK -# iptables-save shows wrong output -# ERROR: cannot find: iptables -I INPUT -m quota ! --quota 0) -#-m quota ! --quota 0;=;OK +-m quota ! --quota 0;=;OK -m quota --quota 18446744073709551615;=;OK -# ERROR: cannot find: iptables -I INPUT -m quota ! --quota 18446744073709551615 -#-m quota ! --quota 18446744073709551615;=;OK +-m quota ! --quota 18446744073709551615;=;OK -m quota --quota 18446744073709551616;;FAIL -m quota;;FAIL diff --git a/extensions/libxt_recent.t b/extensions/libxt_recent.t new file mode 100644 index 00000000..9a83918e --- /dev/null +++ b/extensions/libxt_recent.t @@ -0,0 +1,11 @@ +:INPUT,FORWARD,OUTPUT +-m recent --set;=;OK +-m recent --rcheck --hitcount 8 --name foo --mask 255.255.255.255 --rsource;=;OK +-m recent --rcheck --hitcount 12 --name foo --mask 255.255.255.255 --rsource;=;OK +-m recent --update --rttl;=;OK +-m recent --set --rttl;;FAIL +-m recent --rcheck --hitcount 999 --name foo --mask 255.255.255.255 --rsource;;FAIL +# nonsensical, but all should load successfully: +-m recent --rcheck --hitcount 3 --name foo --mask 255.255.255.255 --rsource -m recent --rcheck --hitcount 4 --name foo --mask 255.255.255.255 --rsource;=;OK +-m recent --rcheck --hitcount 4 --name foo --mask 255.255.255.255 --rsource -m recent --rcheck --hitcount 4 --name foo --mask 255.255.255.255 --rsource;=;OK +-m recent --rcheck --hitcount 8 --name foo --mask 255.255.255.255 --rsource -m recent --rcheck --hitcount 12 --name foo --mask 255.255.255.255 --rsource;=;OK diff --git a/extensions/libxt_rpfilter.t b/extensions/libxt_rpfilter.t new file mode 100644 index 00000000..390268f3 --- /dev/null +++ b/extensions/libxt_rpfilter.t @@ -0,0 +1,4 @@ +:PREROUTING +*mangle +-m rpfilter;=;OK +-m rpfilter --loose --validmark --accept-local --invert;=;OK diff --git a/extensions/libxt_set.t b/extensions/libxt_set.t new file mode 100644 index 00000000..dd9e9f17 --- /dev/null +++ b/extensions/libxt_set.t @@ -0,0 +1,4 @@ +:INPUT,FORWARD,OUTPUT +-m set --match-set foo;;FAIL +# fails: foo does not exist +-m set --match-set foo src,dst;;FAIL diff --git a/extensions/libxt_socket.t b/extensions/libxt_socket.t new file mode 100644 index 00000000..8c0036e2 --- /dev/null +++ b/extensions/libxt_socket.t @@ -0,0 +1,4 @@ +:PREROUTING,INPUT +*mangle +-m socket;=;OK +-m socket --transparent --nowildcard;=;OK diff --git a/extensions/libxt_statistic.t b/extensions/libxt_statistic.t new file mode 100644 index 00000000..bb6673da --- /dev/null +++ b/extensions/libxt_statistic.t @@ -0,0 +1,8 @@ +:INPUT,FORWARD,OUTPUT +-m statistic;;FAIL +-m statistic --mode random ! --probability 0.50000000000;=;OK +-m statistic --mode random ! --probability 1.1;;FAIL +-m statistic --probability 1;;FAIL +-m statistic --mode nth ! --every 5 --packet 2;=;OK +-m statistic --mode nth ! --every 5;;FAIL +-m statistic --mode nth ! --every 5 --packet 5;;FAIL diff --git a/extensions/libxt_string.man b/extensions/libxt_string.man index adc9c180..54c03a3a 100644 --- a/extensions/libxt_string.man +++ b/extensions/libxt_string.man @@ -17,6 +17,9 @@ Matches the given pattern. [\fB!\fP] \fB\-\-hex\-string\fP \fIpattern\fP Matches the given pattern in hex notation. .TP +\fB\-\-icase\fP +Ignore case when searching. +.TP Examples: .IP # The string pattern can be used for simple text characters. diff --git a/extensions/libxt_tcp.man b/extensions/libxt_tcp.man index 7a16118b..80194617 100644 --- a/extensions/libxt_tcp.man +++ b/extensions/libxt_tcp.man @@ -7,7 +7,6 @@ name or a port number. An inclusive range can also be specified, using the format \fIfirst\fP\fB:\fP\fIlast\fP. If the first port is omitted, "0" is assumed; if the last is omitted, "65535" is assumed. -If the first port is greater than the second one they will be swapped. The flag \fB\-\-sport\fP is a convenient alias for this option. diff --git a/extensions/libxt_tcpmss.t b/extensions/libxt_tcpmss.t new file mode 100644 index 00000000..3181e49d --- /dev/null +++ b/extensions/libxt_tcpmss.t @@ -0,0 +1,5 @@ +:INPUT,FORWARD,OUTPUT +-m tcpmss --mss 42;;FAIL +-p tcp -m tcpmss --mss 42;=;OK +-p tcp -m tcpmss --mss 42:12345;=;OK +-p tcp -m tcpmss --mss 42:65536;;FAIL diff --git a/extensions/libxt_u32.t b/extensions/libxt_u32.t new file mode 100644 index 00000000..0d9be47a --- /dev/null +++ b/extensions/libxt_u32.t @@ -0,0 +1,2 @@ +:INPUT,FORWARD,OUTPUT +-m u32 --u32 "0x0=0x0&&0x0=0x1";=;OK |