Commit fe62f28a authored by Arturo Borrero Gonzalez's avatar Arturo Borrero Gonzalez
Browse files

Merge tag 'upstream/1.8.0'

Upstream version 1.8.0
parents 0b132590 278668fa
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for iptables 1.6.2.
# Generated by GNU Autoconf 2.69 for iptables 1.8.0.
#
#
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
......@@ -587,8 +587,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='iptables'
PACKAGE_TARNAME='iptables'
PACKAGE_VERSION='1.6.2'
PACKAGE_STRING='iptables 1.6.2'
PACKAGE_VERSION='1.8.0'
PACKAGE_STRING='iptables 1.8.0'
PACKAGE_BUGREPORT=''
PACKAGE_URL=''
......@@ -1413,7 +1413,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
\`configure' configures iptables 1.6.2 to adapt to many kinds of systems.
\`configure' configures iptables 1.8.0 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
......@@ -1484,7 +1484,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of iptables 1.6.2:";;
short | recursive ) echo "Configuration of iptables 1.8.0:";;
esac
cat <<\_ACEOF
......@@ -1641,7 +1641,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
iptables configure 1.6.2
iptables configure 1.8.0
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
......@@ -2189,7 +2189,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by iptables $as_me 1.6.2, which was
It was created by iptables $as_me 1.8.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
......@@ -3060,7 +3060,7 @@ fi
# Define the identity of the package.
PACKAGE='iptables'
VERSION='1.6.2'
VERSION='1.8.0'
cat >>confdefs.h <<_ACEOF
......@@ -13114,12 +13114,12 @@ if test -n "$libnftnl_CFLAGS"; then
pkg_cv_libnftnl_CFLAGS="$libnftnl_CFLAGS"
elif test -n "$PKG_CONFIG"; then
if test -n "$PKG_CONFIG" && \
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libnftnl >= 1.0.5\""; } >&5
($PKG_CONFIG --exists --print-errors "libnftnl >= 1.0.5") 2>&5
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libnftnl >= 1.1.1\""; } >&5
($PKG_CONFIG --exists --print-errors "libnftnl >= 1.1.1") 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
pkg_cv_libnftnl_CFLAGS=`$PKG_CONFIG --cflags "libnftnl >= 1.0.5" 2>/dev/null`
pkg_cv_libnftnl_CFLAGS=`$PKG_CONFIG --cflags "libnftnl >= 1.1.1" 2>/dev/null`
test "x$?" != "x0" && pkg_failed=yes
else
pkg_failed=yes
......@@ -13131,12 +13131,12 @@ if test -n "$libnftnl_LIBS"; then
pkg_cv_libnftnl_LIBS="$libnftnl_LIBS"
elif test -n "$PKG_CONFIG"; then
if test -n "$PKG_CONFIG" && \
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libnftnl >= 1.0.5\""; } >&5
($PKG_CONFIG --exists --print-errors "libnftnl >= 1.0.5") 2>&5
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libnftnl >= 1.1.1\""; } >&5
($PKG_CONFIG --exists --print-errors "libnftnl >= 1.1.1") 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
pkg_cv_libnftnl_LIBS=`$PKG_CONFIG --libs "libnftnl >= 1.0.5" 2>/dev/null`
pkg_cv_libnftnl_LIBS=`$PKG_CONFIG --libs "libnftnl >= 1.1.1" 2>/dev/null`
test "x$?" != "x0" && pkg_failed=yes
else
pkg_failed=yes
......@@ -13157,9 +13157,9 @@ else
_pkg_short_errors_supported=no
fi
if test $_pkg_short_errors_supported = yes; then
libnftnl_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libnftnl >= 1.0.5" 2>&1`
libnftnl_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libnftnl >= 1.1.1" 2>&1`
else
libnftnl_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libnftnl >= 1.0.5" 2>&1`
libnftnl_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libnftnl >= 1.1.1" 2>&1`
fi
# Put the nasty error message in config.log where it belongs
echo "$libnftnl_PKG_ERRORS" >&5
......@@ -13528,6 +13528,7 @@ fi
regular_CFLAGS="-Wall -Waggregate-return -Wmissing-declarations \
-Wmissing-prototypes -Wredundant-decls -Wshadow -Wstrict-prototypes \
-Wlogical-op \
-Winline -pipe";
regular_CPPFLAGS="${largefile_cppflags} -D_REENTRANT \
-DXTABLES_LIBDIR=\\\"\${xtlibdir}\\\" -DXTABLES_INTERNAL";
......@@ -13561,7 +13562,7 @@ cat >>confdefs.h <<_ACEOF
_ACEOF
ac_config_files="$ac_config_files Makefile extensions/GNUmakefile include/Makefile iptables/Makefile iptables/xtables.pc iptables/iptables.8 iptables/iptables-extensions.8.tmpl iptables/iptables-save.8 iptables/iptables-restore.8 iptables/iptables-apply.8 iptables/iptables-xml.1 libipq/Makefile libipq/libipq.pc libiptc/Makefile libiptc/libiptc.pc libiptc/libip4tc.pc libiptc/libip6tc.pc libxtables/Makefile utils/Makefile include/xtables-version.h include/iptables/internal.h utils/nfnl_osf.8"
ac_config_files="$ac_config_files Makefile extensions/GNUmakefile include/Makefile iptables/Makefile iptables/xtables.pc iptables/iptables.8 iptables/iptables-extensions.8.tmpl iptables/iptables-save.8 iptables/iptables-restore.8 iptables/iptables-apply.8 iptables/iptables-xml.1 libipq/Makefile libipq/libipq.pc libiptc/Makefile libiptc/libiptc.pc libiptc/libip4tc.pc libiptc/libip6tc.pc libxtables/Makefile utils/Makefile include/xtables-version.h include/iptables/internal.h iptables/xtables-monitor.8 utils/nfnl_osf.8"
cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure
......@@ -14153,7 +14154,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by iptables $as_me 1.6.2, which was
This file was extended by iptables $as_me 1.8.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
......@@ -14219,7 +14220,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
iptables config.status 1.6.2
iptables config.status 1.8.0
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
......@@ -14655,6 +14656,7 @@ do
"utils/Makefile") CONFIG_FILES="$CONFIG_FILES utils/Makefile" ;;
"include/xtables-version.h") CONFIG_FILES="$CONFIG_FILES include/xtables-version.h" ;;
"include/iptables/internal.h") CONFIG_FILES="$CONFIG_FILES include/iptables/internal.h" ;;
"iptables/xtables-monitor.8") CONFIG_FILES="$CONFIG_FILES iptables/xtables-monitor.8" ;;
"utils/nfnl_osf.8") CONFIG_FILES="$CONFIG_FILES utils/nfnl_osf.8" ;;
*) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
......
AC_INIT([iptables], [1.6.2])
AC_INIT([iptables], [1.8.0])
# See libtool.info "Libtool's versioning system"
libxtables_vcurrent=12
......@@ -136,7 +136,7 @@ if test "x$enable_nftables" = "xyes"; then
exit 1
fi
PKG_CHECK_MODULES([libnftnl], [libnftnl >= 1.0.5], [nftables=1], [nftables=0])
PKG_CHECK_MODULES([libnftnl], [libnftnl >= 1.1.1], [nftables=1], [nftables=0])
if test "$nftables" = 0;
then
......@@ -197,6 +197,7 @@ AC_SUBST([blacklist_6_modules])
regular_CFLAGS="-Wall -Waggregate-return -Wmissing-declarations \
-Wmissing-prototypes -Wredundant-decls -Wshadow -Wstrict-prototypes \
-Wlogical-op \
-Winline -pipe";
regular_CPPFLAGS="${largefile_cppflags} -D_REENTRANT \
-DXTABLES_LIBDIR=\\\"\${xtlibdir}\\\" -DXTABLES_INTERNAL";
......@@ -250,6 +251,7 @@ AC_CONFIG_FILES([Makefile extensions/GNUmakefile include/Makefile
libiptc/libip4tc.pc libiptc/libip6tc.pc
libxtables/Makefile utils/Makefile
include/xtables-version.h include/iptables/internal.h
iptables/xtables-monitor.8
utils/nfnl_osf.8])
AC_OUTPUT
......
......@@ -20,8 +20,8 @@ family ipv4 {
table nat {
chain PREROUTING hook NF_INET_PRE_ROUTING prio -100
chain INPUT hook NF_INET_LOCAL_IN prio -100
chain OUTPUT hook NF_INET_LOCAL_OUT prio 100
chain INPUT hook NF_INET_LOCAL_IN prio 100
chain OUTPUT hook NF_INET_LOCAL_OUT prio -100
chain POSTROUTING hook NF_INET_POST_ROUTING prio 100
}
......@@ -54,8 +54,8 @@ family ipv6 {
table nat {
chain PREROUTING hook NF_INET_PRE_ROUTING prio -100
chain INPUT hook NF_INET_LOCAL_IN prio -100
chain OUTPUT hook NF_INET_LOCAL_OUT prio 100
chain INPUT hook NF_INET_LOCAL_IN prio 100
chain OUTPUT hook NF_INET_LOCAL_OUT prio -100
chain POSTROUTING hook NF_INET_POST_ROUTING prio 100
}
......@@ -69,7 +69,6 @@ family ipv6 {
family arp {
table filter {
chain INPUT hook NF_ARP_IN prio 0
chain FORWARD hook NF_ARP_FORWARD prio 0
chain OUTPUT hook NF_ARP_OUT prio 0
}
}
......@@ -3,3 +3,18 @@ nft insert rule ip filter OUTPUT ip protocol udp ip daddr 8.8.8.8 counter accept
iptables-translate -F -t nat
nft flush table ip nat
iptables-translate -I INPUT -i iifname -s 10.0.0.0/8
nft insert rule ip filter INPUT iifname "iifname" ip saddr 10.0.0.0/8 counter
iptables-translate -A INPUT -i iif+ ! -d 10.0.0.0/8
nft add rule ip filter INPUT iifname "iif*" ip daddr != 10.0.0.0/8 counter
ebtables-translate -I INPUT -i iname --logical-in ilogname -s 0:0:0:0:0:0
nft insert rule bridge filter INPUT iifname "iname" meta ibrname "ilogname" ether saddr 00:00:00:00:00:00 counter
ebtables-translate -A FORWARD ! -i iname --logical-in ilogname -o out+ --logical-out lout+ -d 1:2:3:4:de:af
nft add rule bridge filter FORWARD iifname != "iname" meta ibrname "ilogname" oifname "out*" meta obrname "lout*" ether daddr 01:02:03:04:de:af counter
ebtables-translate -I INPUT -p ip -d 1:2:3:4:5:6/ff:ff:ff:ff:00:00
nft insert rule bridge filter INPUT ether type 0x800 ether daddr 01:02:03:04:00:00 and ff:ff:ff:ff:00:00 == 01:02:03:04:00:00 counter
......@@ -32,7 +32,7 @@ static void arpmangle_print_help(void)
#define MANGLE_DEVT '4'
#define MANGLE_TARGET '5'
static struct option arpmangle_opts[] = {
static const 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 },
......
/* ebt_arp
*
* Authors:
* Bart De Schuymer <bdschuym@pandora.be>
* Tim Gardner <timg@tpi.com>
*
* April, 2002
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <getopt.h>
#include <xtables.h>
#include <netinet/ether.h>
#include <ebtables/ethernetdb.h>
#include <net/if_arp.h>
#include <linux/netfilter_bridge/ebt_arp.h>
#include "iptables/nft.h"
#include "iptables/nft-bridge.h"
#define ARP_OPCODE '1'
#define ARP_HTYPE '2'
#define ARP_PTYPE '3'
#define ARP_IP_S '4'
#define ARP_IP_D '5'
#define ARP_MAC_S '6'
#define ARP_MAC_D '7'
#define ARP_GRAT '8'
static const struct option brarp_opts[] = {
{ "arp-opcode" , required_argument, 0, ARP_OPCODE },
{ "arp-op" , required_argument, 0, ARP_OPCODE },
{ "arp-htype" , required_argument, 0, ARP_HTYPE },
{ "arp-ptype" , required_argument, 0, ARP_PTYPE },
{ "arp-ip-src" , required_argument, 0, ARP_IP_S },
{ "arp-ip-dst" , required_argument, 0, ARP_IP_D },
{ "arp-mac-src" , required_argument, 0, ARP_MAC_S },
{ "arp-mac-dst" , required_argument, 0, ARP_MAC_D },
{ "arp-gratuitous", no_argument, 0, ARP_GRAT },
XT_GETOPT_TABLEEND,
};
/* a few names */
static char *opcodes[] =
{
"Request",
"Reply",
"Request_Reverse",
"Reply_Reverse",
"DRARP_Request",
"DRARP_Reply",
"DRARP_Error",
"InARP_Request",
"ARP_NAK",
};
static void brarp_print_help(void)
{
int i;
printf(
"arp options:\n"
"--arp-opcode [!] opcode : ARP opcode (integer or string)\n"
"--arp-htype [!] type : ARP hardware type (integer or string)\n"
"--arp-ptype [!] type : ARP protocol type (hexadecimal or string)\n"
"--arp-ip-src [!] address[/mask]: ARP IP source specification\n"
"--arp-ip-dst [!] address[/mask]: ARP IP target specification\n"
"--arp-mac-src [!] address[/mask]: ARP MAC source specification\n"
"--arp-mac-dst [!] address[/mask]: ARP MAC target specification\n"
"[!] --arp-gratuitous : ARP gratuitous packet\n"
" opcode strings: \n");
for (i = 0; i < ARRAY_SIZE(opcodes); i++)
printf(" %d = %s\n", i + 1, opcodes[i]);
printf(
" hardware type string: 1 = Ethernet\n"
" protocol type string: see "_PATH_ETHERTYPES"\n");
}
#define OPT_OPCODE 0x01
#define OPT_HTYPE 0x02
#define OPT_PTYPE 0x04
#define OPT_IP_S 0x08
#define OPT_IP_D 0x10
#define OPT_MAC_S 0x20
#define OPT_MAC_D 0x40
#define OPT_GRAT 0x80
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 brarp_get_mac_and_mask(const char *from, unsigned char *to, unsigned char *mask)
{
char *p;
int i;
struct ether_addr *addr = NULL;
static const unsigned char mac_type_unicast[ETH_ALEN];
static const unsigned char msk_type_unicast[ETH_ALEN] = {1,0,0,0,0,0};
static const unsigned char mac_type_multicast[ETH_ALEN] = {1,0,0,0,0,0};
static const unsigned char mac_type_broadcast[ETH_ALEN] = {255,255,255,255,255,255};
static const unsigned char mac_type_bridge_group[ETH_ALEN] = {0x01,0x80,0xc2,0,0,0};
static const unsigned char msk_type_bridge_group[ETH_ALEN] = {255,255,255,255,255,255};
if (strcasecmp(from, "Unicast") == 0) {
memcpy(to, mac_type_unicast, ETH_ALEN);
memcpy(mask, msk_type_unicast, ETH_ALEN);
return 0;
}
if (strcasecmp(from, "Multicast") == 0) {
memcpy(to, mac_type_multicast, ETH_ALEN);
memcpy(mask, mac_type_multicast, ETH_ALEN);
return 0;
}
if (strcasecmp(from, "Broadcast") == 0) {
memcpy(to, mac_type_broadcast, ETH_ALEN);
memcpy(mask, mac_type_broadcast, ETH_ALEN);
return 0;
}
if (strcasecmp(from, "BGA") == 0) {
memcpy(to, mac_type_bridge_group, ETH_ALEN);
memcpy(mask, msk_type_bridge_group, ETH_ALEN);
return 0;
}
if ( (p = strrchr(from, '/')) != NULL) {
*p = '\0';
if (!(addr = ether_aton(p + 1)))
return -1;
memcpy(mask, addr, ETH_ALEN);
} else
memset(mask, 0xff, ETH_ALEN);
if (!(addr = ether_aton(from)))
return -1;
memcpy(to, addr, ETH_ALEN);
for (i = 0; i < ETH_ALEN; i++)
to[i] &= mask[i];
return 0;
}
static struct ethertypeent *brarp_getethertypeent(FILE *etherf, const char *name)
{
static struct ethertypeent et_ent;
char *e, *found_name;
char line[1024];
while ((e = fgets(line, sizeof(line), etherf))) {
char *endptr, *cp;
if (*e == '#')
continue;
cp = strpbrk(e, "#\n");
if (cp == NULL)
continue;
*cp = '\0';
found_name = e;
cp = strpbrk(e, " \t");
if (cp == NULL)
continue;
*cp++ = '\0';
while (*cp == ' ' || *cp == '\t')
cp++;
e = strpbrk(cp, " \t");
if (e != NULL)
*e++ = '\0';
et_ent.e_ethertype = strtol(cp, &endptr, 16);
if (*endptr != '\0' ||
(et_ent.e_ethertype < ETH_ZLEN || et_ent.e_ethertype > 0xFFFF))
continue;
if (strcasecmp(found_name, name) == 0)
return (&et_ent);
if (e != NULL) {
cp = e;
while (cp && *cp) {
if (*cp == ' ' || *cp == '\t') {
cp++;
continue;
}
e = cp;
cp = strpbrk(cp, " \t");
if (cp != NULL)
*cp++ = '\0';
if (strcasecmp(e, name) == 0)
return (&et_ent);
e = cp;
}
}
}
return NULL;
}
static struct ethertypeent *brarp_getethertypebyname(const char *name)
{
struct ethertypeent *e;
FILE *etherf;
etherf = fopen(_PATH_ETHERTYPES, "r");
e = brarp_getethertypeent(etherf, name);
fclose(etherf);
return (e);
}
static int
brarp_parse(int c, char **argv, int invert, unsigned int *flags,
const void *entry, struct xt_entry_match **match)
{
struct ebt_arp_info *arpinfo = (struct ebt_arp_info *)(*match)->data;
long int i;
char *end;
uint32_t *addr;
uint32_t *mask;
unsigned char *maddr;
unsigned char *mmask;
switch (c) {
case ARP_OPCODE:
EBT_CHECK_OPTION(flags, OPT_OPCODE);
if (invert)
arpinfo->invflags |= EBT_ARP_OPCODE;
i = strtol(optarg, &end, 10);
if (i < 0 || i >= (0x1 << 16) || *end !='\0') {
for (i = 0; i < ARRAY_SIZE(opcodes); i++)
if (!strcasecmp(opcodes[i], optarg))
break;
if (i == ARRAY_SIZE(opcodes))
xtables_error(PARAMETER_PROBLEM, "Problem with specified ARP opcode");
i++;
}
arpinfo->opcode = htons(i);
arpinfo->bitmask |= EBT_ARP_OPCODE;
break;
case ARP_HTYPE:
EBT_CHECK_OPTION(flags, OPT_HTYPE);
if (invert)
arpinfo->invflags |= EBT_ARP_HTYPE;
i = strtol(optarg, &end, 10);
if (i < 0 || i >= (0x1 << 16) || *end !='\0') {
if (!strcasecmp("Ethernet", argv[optind - 1]))
i = 1;
else
xtables_error(PARAMETER_PROBLEM, "Problem with specified ARP hardware type");
}
arpinfo->htype = htons(i);
arpinfo->bitmask |= EBT_ARP_HTYPE;
break;
case ARP_PTYPE: {
uint16_t proto;
EBT_CHECK_OPTION(flags, OPT_PTYPE);
if (invert)
arpinfo->invflags |= EBT_ARP_PTYPE;
i = strtol(optarg, &end, 16);
if (i < 0 || i >= (0x1 << 16) || *end !='\0') {
struct ethertypeent *ent;
ent = brarp_getethertypebyname(argv[optind - 1]);
if (!ent)
xtables_error(PARAMETER_PROBLEM, "Problem with specified ARP "
"protocol type");
proto = ent->e_ethertype;
} else
proto = i;
arpinfo->ptype = htons(proto);
arpinfo->bitmask |= EBT_ARP_PTYPE;
break;
}
case ARP_IP_S:
case ARP_IP_D:
if (c == ARP_IP_S) {
EBT_CHECK_OPTION(flags, OPT_IP_S);
addr = &arpinfo->saddr;
mask = &arpinfo->smsk;
arpinfo->bitmask |= EBT_ARP_SRC_IP;
} else {
EBT_CHECK_OPTION(flags, OPT_IP_D);
addr = &arpinfo->daddr;
mask = &arpinfo->dmsk;
arpinfo->bitmask |= EBT_ARP_DST_IP;
}
if (invert) {
if (c == ARP_IP_S)
arpinfo->invflags |= EBT_ARP_SRC_IP;
else
arpinfo->invflags |= EBT_ARP_DST_IP;
}
ebt_parse_ip_address(optarg, addr, mask);
break;
case ARP_MAC_S:
case ARP_MAC_D:
if (c == ARP_MAC_S) {
EBT_CHECK_OPTION(flags, OPT_MAC_S);
maddr = arpinfo->smaddr;
mmask = arpinfo->smmsk;
arpinfo->bitmask |= EBT_ARP_SRC_MAC;
} else {
EBT_CHECK_OPTION(flags, OPT_MAC_D);
maddr = arpinfo->dmaddr;
mmask = arpinfo->dmmsk;
arpinfo->bitmask |= EBT_ARP_DST_MAC;
}
if (invert) {
if (c == ARP_MAC_S)
arpinfo->invflags |= EBT_ARP_SRC_MAC;
else
arpinfo->invflags |= EBT_ARP_DST_MAC;
}
if (brarp_get_mac_and_mask(optarg, maddr, mmask))
xtables_error(PARAMETER_PROBLEM, "Problem with ARP MAC address argument");
break;
case ARP_GRAT:
EBT_CHECK_OPTION(flags, OPT_GRAT);
arpinfo->bitmask |= EBT_ARP_GRAT;
if (invert)
arpinfo->invflags |= EBT_ARP_GRAT;
break;
default:
return 0;
}
return 1;
}
static void brarp_print_mac_and_mask(const unsigned char *mac, const unsigned char *mask)
{
char hlpmsk[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
printf("%s", ether_ntoa((struct ether_addr *) mac));
if (memcmp(mask, hlpmsk, 6))
printf("/%s", ether_ntoa((struct ether_addr *) mask));
}
static void brarp_print(const void *ip, const struct xt_entry_match *match, int numeric)
{
const struct ebt_arp_info *arpinfo = (struct ebt_arp_info *)match->data;
if (arpinfo->bitmask & EBT_ARP_OPCODE) {
int opcode = ntohs(arpinfo->opcode);
printf("--arp-op ");
if (arpinfo->invflags & EBT_ARP_OPCODE)
printf("! ");
if (opcode > 0 && opcode <= ARRAY_SIZE(opcodes))
printf("%s ", opcodes[opcode - 1]);
else
printf("%d ", opcode);
}
if (arpinfo->bitmask & EBT_ARP_HTYPE) {
printf("--arp-htype ");
if (arpinfo->invflags & EBT_ARP_HTYPE)
printf("! ");
printf("%d ", ntohs(arpinfo->htype));
}
if (arpinfo->bitmask & EBT_ARP_PTYPE) {
printf("--arp-ptype ");
if (arpinfo->invflags & EBT_ARP_PTYPE)
printf("! ");
printf("0x%x ", ntohs(arpinfo->ptype));
}
if (arpinfo->bitmask & EBT_ARP_SRC_IP) {
printf("--arp-ip-src ");
if (arpinfo->invflags & EBT_ARP_SRC_IP)
printf("! ");
printf("%s%s ", xtables_ipaddr_to_numeric((const struct in_addr*) &arpinfo->saddr),
xtables_ipmask_to_numeric((const struct in_addr*)&arpinfo->smsk));
}
if (arpinfo->bitmask & EBT_ARP_DST_IP) {
printf("--arp-ip-dst ");
if (arpinfo->invflags & EBT_ARP_DST_IP)
printf("! ");
printf("%s%s ", xtables_ipaddr_to_numeric((const struct in_addr*) &arpinfo->daddr),
xtables_ipmask_to_numeric((const struct in_addr*)&arpinfo->dmsk));
}
if (arpinfo->bitmask & EBT_ARP_SRC_MAC) {
printf("--arp-mac-src ");
if (arpinfo->invflags & EBT_ARP_SRC_MAC)
printf("! ");
brarp_print_mac_and_mask(arpinfo->smaddr, arpinfo->smmsk);
printf(" ");
}
if (arpinfo->bitmask & EBT_ARP_DST_MAC) {
printf("--arp-mac-dst ");
if (arpinfo->invflags & EBT_ARP_DST_MAC)
printf("! ");
brarp_print_mac_and_mask(arpinfo->dmaddr, arpinfo->dmmsk);
printf(" ");
}
if (arpinfo->bitmask & EBT_ARP_GRAT) {
if (arpinfo->invflags & EBT_ARP_GRAT)
printf("! ");
printf("--arp-gratuitous ");
}
}
static struct xtables_match brarp_match = {
.name = "arp",
.version = XTABLES_VERSION,
.family = NFPROTO_BRIDGE,
.size = XT_ALIGN(sizeof(struct ebt_arp_info)),
.userspacesize = XT_ALIGN(sizeof(struct ebt_arp_info)),
.help = brarp_print_help,
.parse = brarp_parse,
.print = brarp_print,
.extra_opts = brarp_opts,
};
void _init(void)
{
xtables_register_match(&brarp_match);
}
/* ebt_nat
*
* Authors:
* Bart De Schuymer <bdschuym@pandora.be>
*
* June, 2002
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <netinet/ether.h>
#include <xtables.h>
#include <linux/netfilter_bridge/ebt_nat.h>
#include "iptables/nft.h"
#include "iptables/nft-bridge.h"
#define NAT_D '1'
#define NAT_D_TARGET '2'
static const struct option brdnat_opts[] =
{
{ "to-destination", required_argument, 0, NAT_D },
{ "to-dst" , required_argument, 0, NAT_D },
{ "dnat-target" , required_argument, 0, NAT_D_TARGET },
{ 0 }
};
static void brdnat_print_help(void)
{
printf(
"dnat options:\n"
" --to-dst address : MAC address to map destination to\n"
" --dnat-target target : ACCEPT, DROP, RETURN or CONTINUE\n");
}
static void brdnat_init(struct xt_entry_target *target)
{
struct ebt_nat_info *natinfo = (struct ebt_nat_info *)target->data;
natinfo->target = EBT_ACCEPT;
}
#define OPT_DNAT 0x01
#define OPT_DNAT_TARGET 0x02
static int brdnat_parse(int c, char **argv, int invert, unsigned int *flags,
const void *entry, struct xt_entry_target **target)
{
struct ebt_nat_info *natinfo = (struct ebt_nat_info *)(*target)->data;
struct ether_addr *addr;
switch (c) {
case NAT_D:
EBT_CHECK_OPTION(flags, OPT_DNAT);
if (!(addr = ether_aton(optarg)))
xtables_error(PARAMETER_PROBLEM, "Problem with specified --to-destination mac");
memcpy(natinfo->mac, addr, ETH_ALEN);
break;
case NAT_D_TARGET:
EBT_CHECK_OPTION(flags, OPT_DNAT_TARGET);
if (ebt_fill_target(optarg, (unsigned int *)&natinfo->target))
xtables_error(PARAMETER_PROBLEM, "Illegal --dnat-target target");
break;
default:
return 0;
}
return 1;
}
static void brdnat_final_check(unsigned int flags)
{
if (!flags)
xtables_error(PARAMETER_PROBLEM,
"You must specify proper arguments");
}
static void ebt_print_mac(const unsigned char *mac)
{
printf("%s", ether_ntoa((struct ether_addr *) mac));
}
static void brdnat_print(const void *ip, const struct xt_entry_target *target, int numeric)
{
struct ebt_nat_info *natinfo = (struct ebt_nat_info *)target->data;
printf("--to-dst ");
ebt_print_mac(natinfo->mac);
printf(" --dnat-target %s", ebt_target_name(natinfo->target));
}
static const char* brdnat_verdict(int verdict)
{
switch (verdict) {
case EBT_ACCEPT: return "accept";
case EBT_DROP: return "drop";
case EBT_CONTINUE: return "continue";
case EBT_RETURN: return "return";
}
return "";
}
static int brdnat_xlate(struct xt_xlate *xl,
const struct xt_xlate_tg_params *params)
{
const struct ebt_nat_info *natinfo = (const void*)params->target->data;
xt_xlate_add(xl, "ether daddr set %s %s ",
ether_ntoa((struct ether_addr *)natinfo->mac),
brdnat_verdict(natinfo->target));
return 1;
}
static struct xtables_target brdnat_target =
{
.name = "dnat",
.version = XTABLES_VERSION,
.family = NFPROTO_BRIDGE,
.size = XT_ALIGN(sizeof(struct ebt_nat_info)),
.userspacesize = XT_ALIGN(sizeof(struct ebt_nat_info)),
.help = brdnat_print_help,
.init = brdnat_init,
.parse = brdnat_parse,
.final_check = brdnat_final_check,
.print = brdnat_print,
.xlate = brdnat_xlate,
.extra_opts = brdnat_opts,
};
void _init(void)
{
xtables_register_target(&brdnat_target);
}
ebtables-translate -t nat -A PREROUTING -i someport --to-dst de:ad:00:be:ee:ff
nft add rule bridge nat PREROUTING iifname "someport" ether daddr set de:ad:0:be:ee:ff accept counter
ebtables-translate -t nat -A PREROUTING -i someport --to-dst de:ad:00:be:ee:ff --dnat-target ACCEPT
nft add rule bridge nat PREROUTING iifname "someport" ether daddr set de:ad:0:be:ee:ff accept counter
ebtables-translate -t nat -A PREROUTING -i someport --to-dst de:ad:00:be:ee:ff --dnat-target CONTINUE
nft add rule bridge nat PREROUTING iifname "someport" ether daddr set de:ad:0:be:ee:ff continue counter
......@@ -18,8 +18,41 @@
#include <string.h>
#include <getopt.h>
#include <netdb.h>
#include <inttypes.h>
#include <xtables.h>
#include <linux/netfilter_bridge/ebt_ip.h>
#include "libxt_icmp.h"
#define EBT_IP_SOURCE 0x01
#define EBT_IP_DEST 0x02
#define EBT_IP_TOS 0x04
#define EBT_IP_PROTO 0x08
#define EBT_IP_SPORT 0x10
#define EBT_IP_DPORT 0x20
#define EBT_IP_ICMP 0x40
#define EBT_IP_IGMP 0x80
#define EBT_IP_MASK (EBT_IP_SOURCE | EBT_IP_DEST | EBT_IP_TOS | EBT_IP_PROTO |\
EBT_IP_SPORT | EBT_IP_DPORT | EBT_IP_ICMP | EBT_IP_IGMP)
struct ebt_ip_info {
__be32 saddr;
__be32 daddr;
__be32 smsk;
__be32 dmsk;
__u8 tos;
__u8 protocol;
__u8 bitmask;
__u8 invflags;
union {
__u16 sport[2];
__u8 icmp_type[2];
__u8 igmp_type[2];
};
union {
__u16 dport[2];
__u8 icmp_code[2];
};
};
#define IP_SOURCE '1'
#define IP_DEST '2'
......@@ -27,6 +60,8 @@
#define IP_PROTO '4'
#define IP_SPORT '5'
#define IP_DPORT '6'
#define IP_EBT_ICMP '7'
#define IP_EBT_IGMP '8'
static const struct option brip_opts[] = {
{ .name = "ip-source", .has_arg = true, .val = IP_SOURCE },
......@@ -40,9 +75,73 @@ static const struct option brip_opts[] = {
{ .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 },
{ .name = "ip-icmp-type", .has_arg = true, .val = IP_EBT_ICMP },
{ .name = "ip-igmp-type", .has_arg = true, .val = IP_EBT_IGMP },
XT_GETOPT_TABLEEND,
};
static const struct xt_icmp_names icmp_codes[] = {
{ "echo-reply", 0, 0, 0xFF },
/* Alias */ { "pong", 0, 0, 0xFF },
{ "destination-unreachable", 3, 0, 0xFF },
{ "network-unreachable", 3, 0, 0 },
{ "host-unreachable", 3, 1, 1 },
{ "protocol-unreachable", 3, 2, 2 },
{ "port-unreachable", 3, 3, 3 },
{ "fragmentation-needed", 3, 4, 4 },
{ "source-route-failed", 3, 5, 5 },
{ "network-unknown", 3, 6, 6 },
{ "host-unknown", 3, 7, 7 },
{ "network-prohibited", 3, 9, 9 },
{ "host-prohibited", 3, 10, 10 },
{ "TOS-network-unreachable", 3, 11, 11 },
{ "TOS-host-unreachable", 3, 12, 12 },
{ "communication-prohibited", 3, 13, 13 },
{ "host-precedence-violation", 3, 14, 14 },
{ "precedence-cutoff", 3, 15, 15 },
{ "source-quench", 4, 0, 0xFF },
{ "redirect", 5, 0, 0xFF },
{ "network-redirect", 5, 0, 0 },
{ "host-redirect", 5, 1, 1 },
{ "TOS-network-redirect", 5, 2, 2 },
{ "TOS-host-redirect", 5, 3, 3 },
{ "echo-request", 8, 0, 0xFF },
/* Alias */ { "ping", 8, 0, 0xFF },
{ "router-advertisement", 9, 0, 0xFF },
{ "router-solicitation", 10, 0, 0xFF },
{ "time-exceeded", 11, 0, 0xFF },
/* Alias */ { "ttl-exceeded", 11, 0, 0xFF },
{ "ttl-zero-during-transit", 11, 0, 0 },
{ "ttl-zero-during-reassembly", 11, 1, 1 },
{ "parameter-problem", 12, 0, 0xFF },
{ "ip-header-bad", 12, 0, 0 },
{ "required-option-missing", 12, 1, 1 },
{ "timestamp-request", 13, 0, 0xFF },
{ "timestamp-reply", 14, 0, 0xFF },
{ "address-mask-request", 17, 0, 0xFF },
{ "address-mask-reply", 18, 0, 0xFF }
};
static const struct xt_icmp_names igmp_types[] = {
{ "membership-query", 0x11 },
{ "membership-report-v1", 0x12 },
{ "membership-report-v2", 0x16 },
{ "leave-group", 0x17 },
{ "membership-report-v3", 0x22 },
};
static void brip_print_help(void)
{
printf(
......@@ -52,7 +151,14 @@ static void brip_print_help(void)
"--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");
"--ip-dport [!] port[:port] : tcp/udp destination port or port range\n"
"--ip-icmp-type [!] type[[:type]/code[:code]] : icmp type/code or type/code range\n"
"--ip-igmp-type [!] type[:type] : igmp type or type range\n");
printf("\nValid ICMP Types:\n");
xt_print_icmp_types(icmp_codes, ARRAY_SIZE(icmp_codes));
printf("\nValid IGMP Types:\n");
xt_print_icmp_types(igmp_types, ARRAY_SIZE(igmp_types));
}
static void brip_init(struct xt_entry_match *match)
......@@ -161,6 +267,118 @@ static void ebt_parse_ip_address(char *address, uint32_t *addr, uint32_t *msk)
*addr = *addr & *msk;
}
static char *parse_range(const char *str, unsigned int res[])
{
char *next;
if (!xtables_strtoui(str, &next, &res[0], 0, 255))
return NULL;
res[1] = res[0];
if (*next == ':') {
str = next + 1;
if (!xtables_strtoui(str, &next, &res[1], 0, 255))
return NULL;
}
return next;
}
static int ebt_parse_icmp(const struct xt_icmp_names *codes, size_t n_codes,
const char *icmptype, uint8_t type[], uint8_t code[])
{
unsigned int match = n_codes;
unsigned int i, number[2];
for (i = 0; i < n_codes; i++) {
if (strncasecmp(codes[i].name, icmptype, strlen(icmptype)))
continue;
if (match != n_codes)
xtables_error(PARAMETER_PROBLEM, "Ambiguous ICMP type `%s':"
" `%s' or `%s'?",
icmptype, codes[match].name,
codes[i].name);
match = i;
}
if (match < n_codes) {
type[0] = type[1] = codes[match].type;
if (code) {
code[0] = codes[match].code_min;
code[1] = codes[match].code_max;
}
} else {
char *next = parse_range(icmptype, number);
if (!next) {
xtables_error(PARAMETER_PROBLEM, "Unknown ICMP type `%s'",
icmptype);
return -1;
}
type[0] = (uint8_t) number[0];
type[1] = (uint8_t) number[1];
switch (*next) {
case 0:
if (code) {
code[0] = 0;
code[1] = 255;
}
return 0;
case '/':
if (code) {
next = parse_range(next+1, number);
code[0] = (uint8_t) number[0];
code[1] = (uint8_t) number[1];
if (next == NULL)
return -1;
if (next && *next == 0)
return 0;
}
/* fallthrough */
default:
xtables_error(PARAMETER_PROBLEM, "unknown character %c", *next);
return -1;
}
}
return 0;
}
static void print_icmp_code(uint8_t *code)
{
if (!code)
return;
if (code[0] == code[1])
printf("/%"PRIu8 " ", code[0]);
else
printf("/%"PRIu8":%"PRIu8 " ", code[0], code[1]);
}
static void ebt_print_icmp_type(const struct xt_icmp_names *codes,
size_t n_codes, uint8_t *type, uint8_t *code)
{
unsigned int i;
if (type[0] != type[1]) {
printf("%"PRIu8 ":%" PRIu8, type[0], type[1]);
print_icmp_code(code);
return;
}
for (i = 0; i < n_codes; i++) {
if (codes[i].type != type[0])
continue;
if (!code || (codes[i].code_min == code[0] &&
codes[i].code_max == code[1])) {
printf("%s ", codes[i].name);
return;
}
}
printf("%"PRIu8, type[0]);
print_icmp_code(code);
}
static int
brip_parse(int c, char **argv, int invert, unsigned int *flags,
const void *entry, struct xt_entry_match **match)
......@@ -192,6 +410,20 @@ brip_parse(int c, char **argv, int invert, unsigned int *flags,
parse_port_range(NULL, optarg, info->dport);
info->bitmask |= EBT_IP_DPORT;
break;
case IP_EBT_ICMP:
if (invert)
info->invflags |= EBT_IP_ICMP;
ebt_parse_icmp(icmp_codes, ARRAY_SIZE(icmp_codes), optarg,
info->icmp_type, info->icmp_code);
info->bitmask |= EBT_IP_ICMP;
break;
case IP_EBT_IGMP:
if (invert)
info->invflags |= EBT_IP_IGMP;
ebt_parse_icmp(igmp_types, ARRAY_SIZE(igmp_types), optarg,
info->igmp_type, NULL);
info->bitmask |= EBT_IP_IGMP;
break;
case IP_EBT_TOS:
if (invert)
info->invflags |= EBT_IP_TOS;
......@@ -289,6 +521,194 @@ static void brip_print(const void *ip, const struct xt_entry_match *match,
printf("! ");
print_port_range(info->dport);
}
if (info->bitmask & EBT_IP_ICMP) {
printf("--ip-icmp-type ");
if (info->invflags & EBT_IP_ICMP)
printf("! ");
ebt_print_icmp_type(icmp_codes, ARRAY_SIZE(icmp_codes),
info->icmp_type, info->icmp_code);
}
if (info->bitmask & EBT_IP_IGMP) {
printf("--ip-igmp-type ");
if (info->invflags & EBT_IP_IGMP)
printf("! ");
ebt_print_icmp_type(igmp_types, ARRAY_SIZE(igmp_types),
info->igmp_type, NULL);
}
}
static const char *brip_xlate_proto_to_name(uint8_t proto)
{
switch (proto) {
case IPPROTO_TCP:
return "tcp";
case IPPROTO_UDP:
return "udp";
case IPPROTO_UDPLITE:
return "udplite";
case IPPROTO_SCTP:
return "sctp";
case IPPROTO_DCCP:
return "dccp";
default:
return NULL;
}
}
static void brip_xlate_icmp(struct xt_xlate *xl,
const struct ebt_ip_info *info, int bit)
{
if ((info->bitmask & bit) == 0)
return;
xt_xlate_add(xl, "icmp type ");
if (info->invflags & bit)
xt_xlate_add(xl, "!= ");
if (info->icmp_type[0] == info->icmp_type[1])
xt_xlate_add(xl, "%d ", info->icmp_type[0]);
else
xt_xlate_add(xl, "%d-%d ", info->icmp_type[0],
info->icmp_type[1]);
if (info->icmp_code[0] == 0 &&
info->icmp_code[1] == 0xff)
return;
xt_xlate_add(xl, "icmp code ");
if (info->invflags & bit)
xt_xlate_add(xl, "!= ");
if (info->icmp_code[0] == info->icmp_code[1])
xt_xlate_add(xl, "%d ", info->icmp_code[0]);
else
xt_xlate_add(xl, "%d-%d ", info->icmp_code[0],
info->icmp_code[1]);
}
static void brip_xlate_igmp(struct xt_xlate *xl,
const struct ebt_ip_info *info, int bit)
{
if ((info->bitmask & bit) == 0)
return;
xt_xlate_add(xl, "@th,0,8 ");
if (info->invflags & bit)
xt_xlate_add(xl, "!= ");
if (info->icmp_type[0] == info->icmp_type[1])
xt_xlate_add(xl, "%d ", info->icmp_type[0]);
else
xt_xlate_add(xl, "%d-%d ", info->icmp_type[0],
info->icmp_type[1]);
}
static void brip_xlate_th(struct xt_xlate *xl,
const struct ebt_ip_info *info, int bit,
const char *pname)
{
const uint16_t *ports;
if ((info->bitmask & bit) == 0)
return;
switch (bit) {
case EBT_IP_SPORT:
if (pname)
xt_xlate_add(xl, "%s sport ", pname);
else
xt_xlate_add(xl, "@th,0,16 ");
ports = info->sport;
break;
case EBT_IP_DPORT:
if (pname)
xt_xlate_add(xl, "%s dport ", pname);
else
xt_xlate_add(xl, "@th,16,16 ");
ports = info->dport;
break;
default:
return;
}
if (info->invflags & bit)
xt_xlate_add(xl, "!= ");
if (ports[0] == ports[1])
xt_xlate_add(xl, "%d ", ports[0]);
else
xt_xlate_add(xl, "%d-%d ", ports[0], ports[1]);
}
static void brip_xlate_nh(struct xt_xlate *xl,
const struct ebt_ip_info *info, int bit)
{
struct in_addr *addrp, *maskp;
if ((info->bitmask & bit) == 0)
return;
switch (bit) {
case EBT_IP_SOURCE:
xt_xlate_add(xl, "ip saddr ");
addrp = (struct in_addr *)&info->saddr;
maskp = (struct in_addr *)&info->smsk;
break;
case EBT_IP_DEST:
xt_xlate_add(xl, "ip daddr ");
addrp = (struct in_addr *)&info->daddr;
maskp = (struct in_addr *)&info->dmsk;
break;
default:
return;
}
if (info->invflags & bit)
xt_xlate_add(xl, "!= ");
xt_xlate_add(xl, "%s%s ", xtables_ipaddr_to_numeric(addrp),
xtables_ipmask_to_numeric(maskp));
}
static int brip_xlate(struct xt_xlate *xl,
const struct xt_xlate_mt_params *params)
{
const struct ebt_ip_info *info = (const void *)params->match->data;
const char *pname = NULL;
brip_xlate_nh(xl, info, EBT_IP_SOURCE);
brip_xlate_nh(xl, info, EBT_IP_DEST);
if (info->bitmask & EBT_IP_TOS) {
xt_xlate_add(xl, "ip dscp ");
if (info->invflags & EBT_IP_TOS)
xt_xlate_add(xl, "!= ");
xt_xlate_add(xl, "0x%02x ", info->tos & 0x3f); /* remove ECN bits */
}
if (info->bitmask & EBT_IP_PROTO) {
struct protoent *pe;
if (info->bitmask & (EBT_IP_SPORT|EBT_IP_DPORT|EBT_IP_ICMP) &&
(info->invflags & EBT_IP_PROTO) == 0) {
/* port number or icmp given and not inverted, no need to print this */
pname = brip_xlate_proto_to_name(info->protocol);
} else {
xt_xlate_add(xl, "ip protocol ");
if (info->invflags & EBT_IP_PROTO)
xt_xlate_add(xl, "!= ");
pe = getprotobynumber(info->protocol);
if (pe == NULL)
xt_xlate_add(xl, "%d ", info->protocol);
else
xt_xlate_add(xl, "%s ", pe->p_name);
}
}
brip_xlate_th(xl, info, EBT_IP_SPORT, pname);
brip_xlate_th(xl, info, EBT_IP_DPORT, pname);
brip_xlate_icmp(xl, info, EBT_IP_ICMP);
brip_xlate_igmp(xl, info, EBT_IP_IGMP);
return 1;
}
static struct xtables_match brip_match = {
......@@ -303,6 +723,7 @@ static struct xtables_match brip_match = {
.parse = brip_parse,
.final_check = brip_final_check,
.print = brip_print,
.xlate = brip_xlate,
.extra_opts = brip_opts,
};
......
ebtables-translate -A FORWARD -p ip --ip-src ! 192.168.0.0/24 -j ACCEPT
nft add rule bridge filter FORWARD ip saddr != 192.168.0.0/24 counter accept
ebtables-translate -I FORWARD -p ip --ip-dst 10.0.0.1
nft insert rule bridge filter FORWARD ip daddr 10.0.0.1 counter
ebtables-translate -I OUTPUT 3 -p ip -o eth0 --ip-tos 0xff
nft insert rule bridge filter OUTPUT oifname "eth0" ip dscp 0x3f counter
ebtables-translate -A FORWARD -p ip --ip-proto tcp --ip-dport 22
nft add rule bridge filter FORWARD tcp dport 22 counter
ebtables-translate -A FORWARD -p ip --ip-proto udp --ip-sport 1024:65535
nft add rule bridge filter FORWARD udp sport 1024-65535 counter
ebtables-translate -A FORWARD -p ip --ip-proto 253
nft add rule bridge filter FORWARD ip protocol 253 counter
ebtables-translate -A FORWARD -p ip --ip-protocol icmp --ip-icmp-type "echo-request"
nft add rule bridge filter FORWARD icmp type 8 counter
ebtables-translate -A FORWARD -p ip --ip-proto icmp --ip-icmp-type 1/1
nft add rule bridge filter FORWARD icmp type 1 icmp code 1 counter
ebtables-translate -A FORWARD -p ip --ip-protocol icmp --ip-icmp-type ! 1:10
nft add rule bridge filter FORWARD icmp type != 1-10 counter
/* ebt_ip6
*
* Authors:
* Kuo-Lang Tseng <kuo-lang.tseng@intel.com>
* Manohar Castelino <manohar.castelino@intel.com>
*
* Summary:
* This is just a modification of the IPv4 code written by
* Bart De Schuymer <bdschuym@pandora.be>
* with the changes required to support IPv6
*
*/
#include <errno.h>
#include <arpa/inet.h>
#include <inttypes.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <netdb.h>
#include <xtables.h>
#include <linux/netfilter_bridge/ebt_ip6.h>
#include "libxt_icmp.h"
#define IP_SOURCE '1'
#define IP_DEST '2'
#define IP_TCLASS '3'
#define IP_PROTO '4'
#define IP_SPORT '5'
#define IP_DPORT '6'
#define IP_ICMP6 '7'
static const struct option brip6_opts[] = {
{ .name = "ip6-source", .has_arg = true, .val = IP_SOURCE },
{ .name = "ip6-src", .has_arg = true, .val = IP_SOURCE },
{ .name = "ip6-destination", .has_arg = true, .val = IP_DEST },
{ .name = "ip6-dst", .has_arg = true, .val = IP_DEST },
{ .name = "ip6-tclass", .has_arg = true, .val = IP_TCLASS },
{ .name = "ip6-protocol", .has_arg = true, .val = IP_PROTO },
{ .name = "ip6-proto", .has_arg = true, .val = IP_PROTO },
{ .name = "ip6-source-port", .has_arg = true, .val = IP_SPORT },
{ .name = "ip6-sport", .has_arg = true, .val = IP_SPORT },
{ .name = "ip6-destination-port",.has_arg = true,.val = IP_DPORT },
{ .name = "ip6-dport", .has_arg = true, .val = IP_DPORT },
{ .name = "ip6-icmp-type", .has_arg = true, .val = IP_ICMP6 },
XT_GETOPT_TABLEEND,
};
static const struct xt_icmp_names icmpv6_codes[] = {
{ "destination-unreachable", 1, 0, 0xFF },
{ "no-route", 1, 0, 0 },
{ "communication-prohibited", 1, 1, 1 },
{ "address-unreachable", 1, 3, 3 },
{ "port-unreachable", 1, 4, 4 },
{ "packet-too-big", 2, 0, 0xFF },
{ "time-exceeded", 3, 0, 0xFF },
/* Alias */ { "ttl-exceeded", 3, 0, 0xFF },
{ "ttl-zero-during-transit", 3, 0, 0 },
{ "ttl-zero-during-reassembly", 3, 1, 1 },
{ "parameter-problem", 4, 0, 0xFF },
{ "bad-header", 4, 0, 0 },
{ "unknown-header-type", 4, 1, 1 },
{ "unknown-option", 4, 2, 2 },
{ "echo-request", 128, 0, 0xFF },
/* Alias */ { "ping", 128, 0, 0xFF },
{ "echo-reply", 129, 0, 0xFF },
/* Alias */ { "pong", 129, 0, 0xFF },
{ "router-solicitation", 133, 0, 0xFF },
{ "router-advertisement", 134, 0, 0xFF },
{ "neighbour-solicitation", 135, 0, 0xFF },
/* Alias */ { "neighbor-solicitation", 135, 0, 0xFF },
{ "neighbour-advertisement", 136, 0, 0xFF },
/* Alias */ { "neighbor-advertisement", 136, 0, 0xFF },
{ "redirect", 137, 0, 0xFF },
};
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);
}
static char *parse_range(const char *str, unsigned int res[])
{
char *next;
if (!xtables_strtoui(str, &next, &res[0], 0, 255))
return NULL;
res[1] = res[0];
if (*next == ':') {
str = next + 1;
if (!xtables_strtoui(str, &next, &res[1], 0, 255))
return NULL;
}
return next;
}
static int
parse_icmpv6(const char *icmpv6type, uint8_t type[], uint8_t code[])
{
static const unsigned int limit = ARRAY_SIZE(icmpv6_codes);
unsigned int match = limit;
unsigned int i, number[2];
for (i = 0; i < limit; i++) {
if (strncasecmp(icmpv6_codes[i].name, icmpv6type, strlen(icmpv6type)))
continue;
if (match != limit)
xtables_error(PARAMETER_PROBLEM, "Ambiguous ICMPv6 type `%s':"
" `%s' or `%s'?",
icmpv6type, icmpv6_codes[match].name,
icmpv6_codes[i].name);
match = i;
}
if (match < limit) {
type[0] = type[1] = icmpv6_codes[match].type;
code[0] = icmpv6_codes[match].code_min;
code[1] = icmpv6_codes[match].code_max;
} else {
char *next = parse_range(icmpv6type, number);
if (!next) {
xtables_error(PARAMETER_PROBLEM, "Unknown ICMPv6 type `%s'",
icmpv6type);
return -1;
}
type[0] = (uint8_t) number[0];
type[1] = (uint8_t) number[1];
switch (*next) {
case 0:
code[0] = 0;
code[1] = 255;
return 0;
case '/':
next = parse_range(next+1, number);
code[0] = (uint8_t) number[0];
code[1] = (uint8_t) number[1];
if (next == NULL)
return -1;
if (next && *next == 0)
return 0;
/* fallthrough */
default:
xtables_error(PARAMETER_PROBLEM, "unknown character %c", *next);
return -1;
}
}
return 0;
}
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 print_icmp_code(uint8_t *code)
{
if (code[0] == code[1])
printf("/%"PRIu8 " ", code[0]);
else
printf("/%"PRIu8":%"PRIu8 " ", code[0], code[1]);
}
static void print_icmp_type(uint8_t *type, uint8_t *code)
{
unsigned int i;
if (type[0] != type[1]) {
printf("%"PRIu8 ":%" PRIu8, type[0], type[1]);
print_icmp_code(code);
return;
}
for (i = 0; i < ARRAY_SIZE(icmpv6_codes); i++) {
if (icmpv6_codes[i].type != type[0])
continue;
if (icmpv6_codes[i].code_min == code[0] &&
icmpv6_codes[i].code_max == code[1]) {
printf("%s ", icmpv6_codes[i].name);
return;
}
}
printf("%"PRIu8, type[0]);
print_icmp_code(code);
}
static void brip6_print_help(void)
{
printf(
"ip6 options:\n"
"--ip6-src [!] address[/mask]: ipv6 source specification\n"
"--ip6-dst [!] address[/mask]: ipv6 destination specification\n"
"--ip6-tclass [!] tclass : ipv6 traffic class specification\n"
"--ip6-proto [!] protocol : ipv6 protocol specification\n"
"--ip6-sport [!] port[:port] : tcp/udp source port or port range\n"
"--ip6-dport [!] port[:port] : tcp/udp destination port or port range\n"
"--ip6-icmp-type [!] type[[:type]/code[:code]] : ipv6-icmp type/code or type/code range\n");
printf("Valid ICMPv6 Types:");
xt_print_icmp_types(icmpv6_codes, ARRAY_SIZE(icmpv6_codes));
}
static void brip6_init(struct xt_entry_match *match)
{
struct ebt_ip6_info *ipinfo = (struct ebt_ip6_info *)match->data;
ipinfo->invflags = 0;
ipinfo->bitmask = 0;
memset(ipinfo->saddr.s6_addr, 0, sizeof(ipinfo->saddr.s6_addr));
memset(ipinfo->smsk.s6_addr, 0, sizeof(ipinfo->smsk.s6_addr));
memset(ipinfo->daddr.s6_addr, 0, sizeof(ipinfo->daddr.s6_addr));
memset(ipinfo->dmsk.s6_addr, 0, sizeof(ipinfo->dmsk.s6_addr));
}
static struct in6_addr *numeric_to_addr(const char *num)
{
static struct in6_addr ap;
int err;
if ((err=inet_pton(AF_INET6, num, &ap)) == 1)
return &ap;
return (struct in6_addr *)NULL;
}
static struct in6_addr *parse_ip6_mask(char *mask)
{
static struct in6_addr maskaddr;
struct in6_addr *addrp;
unsigned int bits;
if (mask == NULL) {
/* no mask at all defaults to 128 bits */
memset(&maskaddr, 0xff, sizeof maskaddr);
return &maskaddr;
}
if ((addrp = numeric_to_addr(mask)) != NULL)
return addrp;
if (!xtables_strtoui(mask, NULL, &bits, 0, 128))
xtables_error(PARAMETER_PROBLEM, "Invalid IPv6 Mask '%s' specified", mask);
if (bits != 0) {
char *p = (char *)&maskaddr;
memset(p, 0xff, bits / 8);
memset(p + (bits / 8) + 1, 0, (128 - bits) / 8);
p[bits / 8] = 0xff << (8 - (bits & 7));
return &maskaddr;
}
memset(&maskaddr, 0, sizeof maskaddr);
return &maskaddr;
}
/* Set the ipv6 mask and address. Callers should check ebt_errormsg[0].
* The string pointed to by address can be altered. */
static void ebt_parse_ip6_address(char *address, struct in6_addr *addr, struct in6_addr *msk)
{
struct in6_addr *tmp_addr;
char buf[256];
char *p;
int i;
int err;
strncpy(buf, address, sizeof(buf) - 1);
/* first the mask */
buf[sizeof(buf) - 1] = '\0';
if ((p = strrchr(buf, '/')) != NULL) {
*p = '\0';
tmp_addr = parse_ip6_mask(p + 1);
} else
tmp_addr = parse_ip6_mask(NULL);
*msk = *tmp_addr;
/* if a null mask is given, the name is ignored, like in "any/0" */
if (!memcmp(msk, &in6addr_any, sizeof(in6addr_any)))
strcpy(buf, "::");
if ((err=inet_pton(AF_INET6, buf, addr)) < 1) {
xtables_error(PARAMETER_PROBLEM, "Invalid IPv6 Address '%s' specified", buf);
return;
}
for (i = 0; i < 4; i++)
addr->s6_addr32[i] &= msk->s6_addr32[i];
}
#define OPT_SOURCE 0x01
#define OPT_DEST 0x02
#define OPT_TCLASS 0x04
#define OPT_PROTO 0x08
#define OPT_SPORT 0x10
#define OPT_DPORT 0x20
static int
brip6_parse(int c, char **argv, int invert, unsigned int *flags,
const void *entry, struct xt_entry_match **match)
{
struct ebt_ip6_info *info = (struct ebt_ip6_info *)(*match)->data;
unsigned int i;
char *end;
switch (c) {
case IP_SOURCE:
if (invert)
info->invflags |= EBT_IP6_SOURCE;
ebt_parse_ip6_address(optarg, &info->saddr, &info->smsk);
info->bitmask |= EBT_IP6_SOURCE;
break;
case IP_DEST:
if (invert)
info->invflags |= EBT_IP6_DEST;
ebt_parse_ip6_address(optarg, &info->daddr, &info->dmsk);
info->bitmask |= EBT_IP6_DEST;
break;
case IP_SPORT:
if (invert)
info->invflags |= EBT_IP6_SPORT;
parse_port_range(NULL, optarg, info->sport);
info->bitmask |= EBT_IP6_SPORT;
break;
case IP_DPORT:
if (invert)
info->invflags |= EBT_IP6_DEST;
parse_port_range(NULL, optarg, info->dport);
info->bitmask |= EBT_IP6_DPORT;
break;
case IP_ICMP6:
if (invert)
info->invflags |= EBT_IP6_ICMP6;
if (parse_icmpv6(optarg, info->icmpv6_type, info->icmpv6_code))
return 0;
info->bitmask |= EBT_IP6_ICMP6;
break;
case IP_TCLASS:
if (invert)
info->invflags |= EBT_IP6_TCLASS;
if (!xtables_strtoui(optarg, &end, &i, 0, 255))
xtables_error(PARAMETER_PROBLEM, "Problem with specified IPv6 traffic class '%s'", optarg);
info->tclass = i;
info->bitmask |= EBT_IP6_TCLASS;
break;
case IP_PROTO:
if (invert)
info->invflags |= EBT_IP6_PROTO;
info->protocol = xtables_parse_protocol(optarg);
if (info->protocol == -1)
xtables_error(PARAMETER_PROBLEM,
"Unknown specified IP protocol - %s",
optarg);
info->bitmask |= EBT_IP6_PROTO;
break;
default:
return 0;
}
*flags |= info->bitmask;
return 1;
}
static void brip6_final_check(unsigned int flags)
{
if (!flags)
xtables_error(PARAMETER_PROBLEM,
"You must specify proper arguments");
}
static void brip6_print(const void *ip, const struct xt_entry_match *match,
int numeric)
{
struct ebt_ip6_info *ipinfo = (struct ebt_ip6_info *)match->data;
if (ipinfo->bitmask & EBT_IP6_SOURCE) {
printf("--ip6-src ");
if (ipinfo->invflags & EBT_IP6_SOURCE)
printf("! ");
printf("%s", xtables_ip6addr_to_numeric(&ipinfo->saddr));
printf("%s ", xtables_ip6mask_to_numeric(&ipinfo->smsk));
}
if (ipinfo->bitmask & EBT_IP6_DEST) {
printf("--ip6-dst ");
if (ipinfo->invflags & EBT_IP6_DEST)
printf("! ");
printf("%s", xtables_ip6addr_to_numeric(&ipinfo->daddr));
printf("%s ", xtables_ip6mask_to_numeric(&ipinfo->dmsk));
}
if (ipinfo->bitmask & EBT_IP6_TCLASS) {
printf("--ip6-tclass ");
if (ipinfo->invflags & EBT_IP6_TCLASS)
printf("! ");
printf("0x%02X ", ipinfo->tclass);
}
if (ipinfo->bitmask & EBT_IP6_PROTO) {
struct protoent *pe;
printf("--ip6-proto ");
if (ipinfo->invflags & EBT_IP6_PROTO)
printf("! ");
pe = getprotobynumber(ipinfo->protocol);
if (pe == NULL) {
printf("%d ", ipinfo->protocol);
} else {
printf("%s ", pe->p_name);
}
}
if (ipinfo->bitmask & EBT_IP6_SPORT) {
printf("--ip6-sport ");
if (ipinfo->invflags & EBT_IP6_SPORT)
printf("! ");
print_port_range(ipinfo->sport);
}
if (ipinfo->bitmask & EBT_IP6_DPORT) {
printf("--ip6-dport ");
if (ipinfo->invflags & EBT_IP6_DPORT)
printf("! ");
print_port_range(ipinfo->dport);
}
if (ipinfo->bitmask & EBT_IP6_ICMP6) {
printf("--ip6-icmp-type ");
if (ipinfo->invflags & EBT_IP6_ICMP6)
printf("! ");
print_icmp_type(ipinfo->icmpv6_type, ipinfo->icmpv6_code);
}
}
static void brip_xlate_th(struct xt_xlate *xl,
const struct ebt_ip6_info *info, int bit,
const char *pname)
{
const uint16_t *ports;
if ((info->bitmask & bit) == 0)
return;
switch (bit) {
case EBT_IP6_SPORT:
if (pname)
xt_xlate_add(xl, "%s sport ", pname);
else
xt_xlate_add(xl, "@th,0,16 ");
ports = info->sport;
break;
case EBT_IP6_DPORT:
if (pname)
xt_xlate_add(xl, "%s dport ", pname);
else
xt_xlate_add(xl, "@th,16,16 ");
ports = info->dport;
break;
default:
return;
}
if (info->invflags & bit)
xt_xlate_add(xl, "!= ");
if (ports[0] == ports[1])
xt_xlate_add(xl, "%d ", ports[0]);
else
xt_xlate_add(xl, "%d-%d ", ports[0], ports[1]);
}
static void brip_xlate_nh(struct xt_xlate *xl,
const struct ebt_ip6_info *info, int bit)
{
struct in6_addr *addrp, *maskp;
if ((info->bitmask & bit) == 0)
return;
switch (bit) {
case EBT_IP6_SOURCE:
xt_xlate_add(xl, "ip6 saddr ");
addrp = (struct in6_addr *)&info->saddr;
maskp = (struct in6_addr *)&info->smsk;
break;
case EBT_IP6_DEST:
xt_xlate_add(xl, "ip6 daddr ");
addrp = (struct in6_addr *)&info->daddr;
maskp = (struct in6_addr *)&info->dmsk;
break;
default:
return;
}
if (info->invflags & bit)
xt_xlate_add(xl, "!= ");
xt_xlate_add(xl, "%s%s ", xtables_ip6addr_to_numeric(addrp),
xtables_ip6mask_to_numeric(maskp));
}
static const char *brip6_xlate_proto_to_name(uint8_t proto)
{
switch (proto) {
case IPPROTO_TCP:
return "tcp";
case IPPROTO_UDP:
return "udp";
case IPPROTO_UDPLITE:
return "udplite";
case IPPROTO_SCTP:
return "sctp";
case IPPROTO_DCCP:
return "dccp";
default:
return NULL;
}
}
static int brip6_xlate(struct xt_xlate *xl,
const struct xt_xlate_mt_params *params)
{
const struct ebt_ip6_info *info = (const void *)params->match->data;
const char *pname = NULL;
if ((info->bitmask & (EBT_IP6_SOURCE|EBT_IP6_DEST|EBT_IP6_ICMP6|EBT_IP6_TCLASS)) == 0)
xt_xlate_add(xl, "ether type ip6 ");
brip_xlate_nh(xl, info, EBT_IP6_SOURCE);
brip_xlate_nh(xl, info, EBT_IP6_DEST);
if (info->bitmask & EBT_IP6_TCLASS) {
xt_xlate_add(xl, "ip6 dscp ");
if (info->invflags & EBT_IP6_TCLASS)
xt_xlate_add(xl, "!= ");
xt_xlate_add(xl, "0x%02x ", info->tclass & 0x3f); /* remove ECN bits */
}
if (info->bitmask & EBT_IP6_PROTO) {
struct protoent *pe;
if (info->bitmask & (EBT_IP6_SPORT|EBT_IP6_DPORT|EBT_IP6_ICMP6) &&
(info->invflags & EBT_IP6_PROTO) == 0) {
/* port number given and not inverted, no need to
* add explicit 'meta l4proto'.
*/
pname = brip6_xlate_proto_to_name(info->protocol);
} else {
xt_xlate_add(xl, "meta l4proto ");
if (info->invflags & EBT_IP6_PROTO)
xt_xlate_add(xl, "!= ");
pe = getprotobynumber(info->protocol);
if (pe == NULL)
xt_xlate_add(xl, "%d ", info->protocol);
else
xt_xlate_add(xl, "%s ", pe->p_name);
}
}
brip_xlate_th(xl, info, EBT_IP6_SPORT, pname);
brip_xlate_th(xl, info, EBT_IP6_DPORT, pname);
if (info->bitmask & EBT_IP6_ICMP6) {
xt_xlate_add(xl, "icmpv6 type ");
if (info->invflags & EBT_IP6_ICMP6)
xt_xlate_add(xl, "!= ");
if (info->icmpv6_type[0] == info->icmpv6_type[1])
xt_xlate_add(xl, "%d ", info->icmpv6_type[0]);
else
xt_xlate_add(xl, "%d-%d ", info->icmpv6_type[0],
info->icmpv6_type[1]);
if (info->icmpv6_code[0] == 0 &&
info->icmpv6_code[1] == 0xff)
return 1;
xt_xlate_add(xl, "icmpv6 code ");
if (info->invflags & EBT_IP6_ICMP6)
xt_xlate_add(xl, "!= ");
if (info->icmpv6_code[0] == info->icmpv6_code[1])
xt_xlate_add(xl, "%d ", info->icmpv6_code[0]);
else
xt_xlate_add(xl, "%d-%d ", info->icmpv6_code[0],
info->icmpv6_code[1]);
}
return 1;
}
static struct xtables_match brip6_match = {
.name = "ip6",
.revision = 0,
.version = XTABLES_VERSION,
.family = NFPROTO_BRIDGE,
.size = XT_ALIGN(sizeof(struct ebt_ip6_info)),
.userspacesize = XT_ALIGN(sizeof(struct ebt_ip6_info)),
.init = brip6_init,
.help = brip6_print_help,
.parse = brip6_parse,
.final_check = brip6_final_check,
.print = brip6_print,
.xlate = brip6_xlate,
.extra_opts = brip6_opts,
};
void _init(void)
{
xtables_register_match(&brip6_match);
}
ebtables-translate -A FORWARD -p ip6 --ip6-src ! dead::beef/64 -j ACCEPT
nft add rule bridge filter FORWARD ip6 saddr != dead::/64 counter accept
ebtables-translate -A FORWARD -p ip6 ! --ip6-dst dead:beef::/64 -j ACCEPT
nft add rule bridge filter FORWARD ip6 daddr != dead:beef::/64 counter accept
ebtables-translate -I FORWARD -p ip6 --ip6-dst f00:ba::
nft insert rule bridge filter FORWARD ip6 daddr f00:ba:: counter
ebtables-translate -I OUTPUT -o eth0 -p ip6 --ip6-tclass 0xff
nft insert rule bridge filter OUTPUT oifname "eth0" ip6 dscp 0x3f counter
ebtables-translate -A FORWARD -p ip6 --ip6-proto tcp --ip6-dport 22
nft add rule bridge filter FORWARD ether type ip6 tcp dport 22 counter
ebtables-translate -A FORWARD -p ip6 --ip6-proto udp --ip6-sport 1024:65535
nft add rule bridge filter FORWARD ether type ip6 udp sport 1024-65535 counter
ebtables-translate -A FORWARD -p ip6 --ip6-proto 253
nft add rule bridge filter FORWARD ether type ip6 meta l4proto 253 counter
ebtables-translate -A FORWARD -p ip6 --ip6-protocol icmpv6 --ip6-icmp-type "echo-request"
nft add rule bridge filter FORWARD icmpv6 type 128 counter
ebtables-translate -A FORWARD -p ip6 --ip6-protocol icmpv6 --ip6-icmp-type 1/1
nft add rule bridge filter FORWARD icmpv6 type 1 icmpv6 code 1 counter
ebtables-translate -A FORWARD -p ip6 --ip6-protocol icmpv6 --ip6-icmp-type ! 1:10
nft add rule bridge filter FORWARD icmpv6 type != 1-10 counter
......@@ -133,8 +133,8 @@ 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 }
{ "minute", EBT_LIMIT_SCALE*60 },
{ "second", EBT_LIMIT_SCALE }
};
static void print_rate(uint32_t period)
......@@ -159,6 +159,31 @@ static void brlimit_print(const void *ip, const struct xt_entry_match *match,
printf("--limit-burst %u ", r->burst);
}
static void print_rate_xlate(struct xt_xlate *xl, 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;
xt_xlate_add(xl, "%u/%s ", g_rates[i-1].mult / period, g_rates[i-1].name);
}
static int brlimit_xlate(struct xt_xlate *xl,
const struct xt_xlate_mt_params *params)
{
const struct ebt_limit_info *r = (const void *)params->match->data;
xt_xlate_add(xl, "limit rate ");
print_rate_xlate(xl, r->avg);
if (r->burst != 0)
xt_xlate_add(xl, "burst %u packets ", r->burst);
return 1;
}
static struct xtables_match brlimit_match = {
.name = "limit",
.revision = 0,
......@@ -170,6 +195,7 @@ static struct xtables_match brlimit_match = {
.help = brlimit_print_help,
.parse = brlimit_parse,
.print = brlimit_print,
.xlate = brlimit_xlate,
.extra_opts = brlimit_opts,
};
......
ebtables-translate -A INPUT --limit 3/m --limit-burst 3
nft add rule bridge filter INPUT limit rate 3/minute burst 3 packets counter
ebtables-translate -A INPUT --limit 10/s --limit-burst 5
nft add rule bridge filter INPUT limit rate 10/second burst 5 packets counter
ebtables-translate -A INPUT --limit 10/s --limit-burst 0
nft add rule bridge filter INPUT limit rate 10/second counter
......@@ -176,6 +176,27 @@ static void brlog_print(const void *ip, const struct xt_entry_target *target,
printf(" ");
}
static int brlog_xlate(struct xt_xlate *xl,
const struct xt_xlate_tg_params *params)
{
const struct ebt_log_info *loginfo = (const void *)params->target->data;
xt_xlate_add(xl, "log");
if (loginfo->prefix[0]) {
if (params->escape_quotes)
xt_xlate_add(xl, " prefix \\\"%s\\\"", loginfo->prefix);
else
xt_xlate_add(xl, " prefix \"%s\"", loginfo->prefix);
}
if (loginfo->loglevel != LOG_DEFAULT_LEVEL)
xt_xlate_add(xl, " level %s", eight_priority[loginfo->loglevel].c_name);
xt_xlate_add(xl, " flags ether ");
return 1;
}
static struct xtables_target brlog_target = {
.name = "log",
.revision = 0,
......@@ -188,6 +209,7 @@ static struct xtables_target brlog_target = {
.parse = brlog_parse,
.final_check = brlog_final_check,
.print = brlog_print,
.xlate = brlog_xlate,
.extra_opts = brlog_opts,
};
......
ebtables-translate -A INPUT --log
nft add rule bridge filter INPUT log level notice flags ether counter
ebtables-translate -A INPUT --log-level 1
nft add rule bridge filter INPUT log level alert flags ether counter
ebtables-translate -A INPUT --log-level crit
nft add rule bridge filter INPUT log level crit flags ether counter
ebtables-translate -A INPUT --log-level emerg --log-ip --log-arp --log-ip6
nft add rule bridge filter INPUT log level emerg flags ether counter
ebtables-translate -A INPUT --log-level crit --log-ip --log-arp --log-ip6 --log-prefix foo
nft add rule bridge filter INPUT log prefix "foo" level crit flags ether counter
......@@ -170,6 +170,49 @@ static void brmark_final_check(unsigned int flags)
"You must specify some option");
}
static const char* brmark_verdict(int verdict)
{
switch (verdict) {
case EBT_ACCEPT: return "accept";
case EBT_DROP: return "drop";
case EBT_CONTINUE: return "continue";
case EBT_RETURN: return "return";
}
return "";
}
static int brmark_xlate(struct xt_xlate *xl,
const struct xt_xlate_tg_params *params)
{
const struct ebt_mark_t_info *info = (const void*)params->target->data;
int tmp;
tmp = info->target & ~EBT_VERDICT_BITS;
xt_xlate_add(xl, "meta mark set ");
switch (tmp) {
case MARK_SET_VALUE:
break;
case MARK_OR_VALUE:
xt_xlate_add(xl, "meta mark or ");
break;
case MARK_XOR_VALUE:
xt_xlate_add(xl, "meta mark xor ");
break;
case MARK_AND_VALUE:
xt_xlate_add(xl, "meta mark and ");
break;
default:
return 0;
}
tmp = info->target & EBT_VERDICT_BITS;
xt_xlate_add(xl, "0x%lx %s ", info->mark, brmark_verdict(tmp));
return 1;
}
static struct xtables_target brmark_target = {
.name = "mark",
.revision = 0,
......@@ -182,6 +225,7 @@ static struct xtables_target brmark_target = {
.parse = brmark_parse,
.final_check = brmark_final_check,
.print = brmark_print,
.xlate = brmark_xlate,
.extra_opts = brmark_opts,
};
......
ebtables-translate -A INPUT --mark-set 42
nft add rule bridge filter INPUT mark set 0x2a counter
ebtables-translate -A INPUT --mark-or 42 --mark-target RETURN
nft add rule bridge filter INPUT mark set mark or 0x2a counter return
ebtables-translate -A INPUT --mark-and 42 --mark-target ACCEPT
nft add rule bridge filter INPUT mark set mark and 0x2a counter accept
ebtables-translate -A INPUT --mark-xor 42 --mark-target DROP
nft add rule bridge filter INPUT mark set mark xor 0x2a counter drop
......@@ -97,6 +97,30 @@ static void brmark_m_print(const void *ip, const struct xt_entry_match *match,
printf("0x%lx ", info->mark);
}
static int brmark_m_xlate(struct xt_xlate *xl,
const struct xt_xlate_mt_params *params)
{
const struct ebt_mark_m_info *info = (const void*)params->match->data;
enum xt_op op = XT_OP_EQ;
if (info->invert)
op = XT_OP_NEQ;
xt_xlate_add(xl, "meta mark ");
if (info->bitmask == EBT_MARK_OR) {
xt_xlate_add(xl, "and 0x%x %s0 ", info->mask,
info->invert ? "" : "!= ");
} else if (info->mask != 0xffffffffU) {
xt_xlate_add(xl, "and 0x%x %s0x%x ", info->mask,
op == XT_OP_EQ ? "" : "!= ", info->mark);
} else {
xt_xlate_add(xl, "%s0x%x ",
op == XT_OP_EQ ? "" : "!= ", info->mark);
}
return 1;
}
static struct xtables_match brmark_m_match = {
.name = "mark_m",
.revision = 0,
......@@ -109,6 +133,7 @@ static struct xtables_match brmark_m_match = {
.parse = brmark_m_parse,
.final_check = brmark_m_final_check,
.print = brmark_m_print,
.xlate = brmark_m_xlate,
.extra_opts = brmark_m_opts,
};
......
ebtables-translate -A INPUT --mark 42
nft add rule bridge filter INPUT meta mark 0x2a counter
ebtables-translate -A INPUT ! --mark 42
nft add rule bridge filter INPUT meta mark != 0x2a counter
ebtables-translate -A INPUT --mark ! 42
nft add rule bridge filter INPUT meta mark != 0x2a counter
ebtables-translate -A INPUT --mark ! 0x1/0xff
nft add rule bridge filter INPUT meta mark and 0xff != 0x1 counter
ebtables-translate -A INPUT --mark /0x02
nft add rule bridge filter INPUT meta mark and 0x2 != 0 counter
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment