Commit 278668fa authored by Arturo Borrero Gonzalez's avatar Arturo Borrero Gonzalez
Browse files

New upstream version 1.8.0

parent 5beab31f
#! /bin/sh #! /bin/sh
# Guess values for system-dependent variables and create Makefiles. # 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. # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
...@@ -587,8 +587,8 @@ MAKEFLAGS= ...@@ -587,8 +587,8 @@ MAKEFLAGS=
# Identity of this package. # Identity of this package.
PACKAGE_NAME='iptables' PACKAGE_NAME='iptables'
PACKAGE_TARNAME='iptables' PACKAGE_TARNAME='iptables'
PACKAGE_VERSION='1.6.2' PACKAGE_VERSION='1.8.0'
PACKAGE_STRING='iptables 1.6.2' PACKAGE_STRING='iptables 1.8.0'
PACKAGE_BUGREPORT='' PACKAGE_BUGREPORT=''
PACKAGE_URL='' PACKAGE_URL=''
...@@ -1413,7 +1413,7 @@ if test "$ac_init_help" = "long"; then ...@@ -1413,7 +1413,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing. # 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. # This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF 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]... Usage: $0 [OPTION]... [VAR=VALUE]...
...@@ -1484,7 +1484,7 @@ fi ...@@ -1484,7 +1484,7 @@ fi
if test -n "$ac_init_help"; then if test -n "$ac_init_help"; then
case $ac_init_help in case $ac_init_help in
short | recursive ) echo "Configuration of iptables 1.6.2:";; short | recursive ) echo "Configuration of iptables 1.8.0:";;
esac esac
cat <<\_ACEOF cat <<\_ACEOF
...@@ -1641,7 +1641,7 @@ fi ...@@ -1641,7 +1641,7 @@ fi
test -n "$ac_init_help" && exit $ac_status test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then if $ac_init_version; then
cat <<\_ACEOF cat <<\_ACEOF
iptables configure 1.6.2 iptables configure 1.8.0
generated by GNU Autoconf 2.69 generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc. Copyright (C) 2012 Free Software Foundation, Inc.
...@@ -2189,7 +2189,7 @@ cat >config.log <<_ACEOF ...@@ -2189,7 +2189,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake. 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 generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@ $ $0 $@
...@@ -3060,7 +3060,7 @@ fi ...@@ -3060,7 +3060,7 @@ fi
# Define the identity of the package. # Define the identity of the package.
PACKAGE='iptables' PACKAGE='iptables'
VERSION='1.6.2' VERSION='1.8.0'
cat >>confdefs.h <<_ACEOF cat >>confdefs.h <<_ACEOF
...@@ -13114,12 +13114,12 @@ if test -n "$libnftnl_CFLAGS"; then ...@@ -13114,12 +13114,12 @@ if test -n "$libnftnl_CFLAGS"; then
pkg_cv_libnftnl_CFLAGS="$libnftnl_CFLAGS" pkg_cv_libnftnl_CFLAGS="$libnftnl_CFLAGS"
elif test -n "$PKG_CONFIG"; then elif test -n "$PKG_CONFIG"; then
if test -n "$PKG_CONFIG" && \ if test -n "$PKG_CONFIG" && \
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libnftnl >= 1.0.5\""; } >&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.0.5") 2>&5 ($PKG_CONFIG --exists --print-errors "libnftnl >= 1.1.1") 2>&5
ac_status=$? ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then 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 test "x$?" != "x0" && pkg_failed=yes
else else
pkg_failed=yes pkg_failed=yes
...@@ -13131,12 +13131,12 @@ if test -n "$libnftnl_LIBS"; then ...@@ -13131,12 +13131,12 @@ if test -n "$libnftnl_LIBS"; then
pkg_cv_libnftnl_LIBS="$libnftnl_LIBS" pkg_cv_libnftnl_LIBS="$libnftnl_LIBS"
elif test -n "$PKG_CONFIG"; then elif test -n "$PKG_CONFIG"; then
if test -n "$PKG_CONFIG" && \ if test -n "$PKG_CONFIG" && \
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libnftnl >= 1.0.5\""; } >&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.0.5") 2>&5 ($PKG_CONFIG --exists --print-errors "libnftnl >= 1.1.1") 2>&5
ac_status=$? ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then 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 test "x$?" != "x0" && pkg_failed=yes
else else
pkg_failed=yes pkg_failed=yes
...@@ -13157,9 +13157,9 @@ else ...@@ -13157,9 +13157,9 @@ else
_pkg_short_errors_supported=no _pkg_short_errors_supported=no
fi fi
if test $_pkg_short_errors_supported = yes; then 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 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 fi
# Put the nasty error message in config.log where it belongs # Put the nasty error message in config.log where it belongs
echo "$libnftnl_PKG_ERRORS" >&5 echo "$libnftnl_PKG_ERRORS" >&5
...@@ -13528,6 +13528,7 @@ fi ...@@ -13528,6 +13528,7 @@ fi
regular_CFLAGS="-Wall -Waggregate-return -Wmissing-declarations \ regular_CFLAGS="-Wall -Waggregate-return -Wmissing-declarations \
-Wmissing-prototypes -Wredundant-decls -Wshadow -Wstrict-prototypes \ -Wmissing-prototypes -Wredundant-decls -Wshadow -Wstrict-prototypes \
-Wlogical-op \
-Winline -pipe"; -Winline -pipe";
regular_CPPFLAGS="${largefile_cppflags} -D_REENTRANT \ regular_CPPFLAGS="${largefile_cppflags} -D_REENTRANT \
-DXTABLES_LIBDIR=\\\"\${xtlibdir}\\\" -DXTABLES_INTERNAL"; -DXTABLES_LIBDIR=\\\"\${xtlibdir}\\\" -DXTABLES_INTERNAL";
...@@ -13561,7 +13562,7 @@ cat >>confdefs.h <<_ACEOF ...@@ -13561,7 +13562,7 @@ cat >>confdefs.h <<_ACEOF
_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 cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure # This file is a shell script that caches the results of configure
...@@ -14153,7 +14154,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ...@@ -14153,7 +14154,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their # report actual input values of CONFIG_FILES etc. instead of their
# values after options handling. # values after options handling.
ac_log=" 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 generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES CONFIG_FILES = $CONFIG_FILES
...@@ -14219,7 +14220,7 @@ _ACEOF ...@@ -14219,7 +14220,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\ ac_cs_version="\\
iptables config.status 1.6.2 iptables config.status 1.8.0
configured by $0, generated by GNU Autoconf 2.69, configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\" with options \\"\$ac_cs_config\\"
...@@ -14655,6 +14656,7 @@ do ...@@ -14655,6 +14656,7 @@ do
"utils/Makefile") CONFIG_FILES="$CONFIG_FILES utils/Makefile" ;; "utils/Makefile") CONFIG_FILES="$CONFIG_FILES utils/Makefile" ;;
"include/xtables-version.h") CONFIG_FILES="$CONFIG_FILES include/xtables-version.h" ;; "include/xtables-version.h") CONFIG_FILES="$CONFIG_FILES include/xtables-version.h" ;;
"include/iptables/internal.h") CONFIG_FILES="$CONFIG_FILES include/iptables/internal.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" ;; "utils/nfnl_osf.8") CONFIG_FILES="$CONFIG_FILES utils/nfnl_osf.8" ;;
*) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; *) 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" # See libtool.info "Libtool's versioning system"
libxtables_vcurrent=12 libxtables_vcurrent=12
...@@ -136,7 +136,7 @@ if test "x$enable_nftables" = "xyes"; then ...@@ -136,7 +136,7 @@ if test "x$enable_nftables" = "xyes"; then
exit 1 exit 1
fi 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; if test "$nftables" = 0;
then then
...@@ -197,6 +197,7 @@ AC_SUBST([blacklist_6_modules]) ...@@ -197,6 +197,7 @@ AC_SUBST([blacklist_6_modules])
regular_CFLAGS="-Wall -Waggregate-return -Wmissing-declarations \ regular_CFLAGS="-Wall -Waggregate-return -Wmissing-declarations \
-Wmissing-prototypes -Wredundant-decls -Wshadow -Wstrict-prototypes \ -Wmissing-prototypes -Wredundant-decls -Wshadow -Wstrict-prototypes \
-Wlogical-op \
-Winline -pipe"; -Winline -pipe";
regular_CPPFLAGS="${largefile_cppflags} -D_REENTRANT \ regular_CPPFLAGS="${largefile_cppflags} -D_REENTRANT \
-DXTABLES_LIBDIR=\\\"\${xtlibdir}\\\" -DXTABLES_INTERNAL"; -DXTABLES_LIBDIR=\\\"\${xtlibdir}\\\" -DXTABLES_INTERNAL";
...@@ -250,6 +251,7 @@ AC_CONFIG_FILES([Makefile extensions/GNUmakefile include/Makefile ...@@ -250,6 +251,7 @@ AC_CONFIG_FILES([Makefile extensions/GNUmakefile include/Makefile
libiptc/libip4tc.pc libiptc/libip6tc.pc libiptc/libip4tc.pc libiptc/libip6tc.pc
libxtables/Makefile utils/Makefile libxtables/Makefile utils/Makefile
include/xtables-version.h include/iptables/internal.h include/xtables-version.h include/iptables/internal.h
iptables/xtables-monitor.8
utils/nfnl_osf.8]) utils/nfnl_osf.8])
AC_OUTPUT AC_OUTPUT
......
...@@ -20,8 +20,8 @@ family ipv4 { ...@@ -20,8 +20,8 @@ family ipv4 {
table nat { table nat {
chain PREROUTING hook NF_INET_PRE_ROUTING prio -100 chain PREROUTING hook NF_INET_PRE_ROUTING prio -100
chain INPUT hook NF_INET_LOCAL_IN prio -100 chain INPUT hook NF_INET_LOCAL_IN prio 100
chain OUTPUT hook NF_INET_LOCAL_OUT prio 100 chain OUTPUT hook NF_INET_LOCAL_OUT prio -100
chain POSTROUTING hook NF_INET_POST_ROUTING prio 100 chain POSTROUTING hook NF_INET_POST_ROUTING prio 100
} }
...@@ -54,8 +54,8 @@ family ipv6 { ...@@ -54,8 +54,8 @@ family ipv6 {
table nat { table nat {
chain PREROUTING hook NF_INET_PRE_ROUTING prio -100 chain PREROUTING hook NF_INET_PRE_ROUTING prio -100
chain INPUT hook NF_INET_LOCAL_IN prio -100 chain INPUT hook NF_INET_LOCAL_IN prio 100
chain OUTPUT hook NF_INET_LOCAL_OUT prio 100 chain OUTPUT hook NF_INET_LOCAL_OUT prio -100
chain POSTROUTING hook NF_INET_POST_ROUTING prio 100 chain POSTROUTING hook NF_INET_POST_ROUTING prio 100
} }
...@@ -69,7 +69,6 @@ family ipv6 { ...@@ -69,7 +69,6 @@ family ipv6 {
family arp { family arp {
table filter { table filter {
chain INPUT hook NF_ARP_IN prio 0 chain INPUT hook NF_ARP_IN prio 0
chain FORWARD hook NF_ARP_FORWARD prio 0
chain OUTPUT hook NF_ARP_OUT 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 ...@@ -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 iptables-translate -F -t nat
nft flush table ip 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) ...@@ -32,7 +32,7 @@ static void arpmangle_print_help(void)
#define MANGLE_DEVT '4' #define MANGLE_DEVT '4'
#define MANGLE_TARGET '5' #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-s", .has_arg = true, .val = MANGLE_IPS },
{ .name = "mangle-ip-d", .has_arg = true, .val = MANGLE_IPT }, { .name = "mangle-ip-d", .has_arg = true, .val = MANGLE_IPT },
{ .name = "mangle-mac-s", .has_arg = true, .val = MANGLE_DEVS }, { .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 @@ ...@@ -18,8 +18,41 @@
#include <string.h> #include <string.h>
#include <getopt.h> #include <getopt.h>
#include <netdb.h> #include <netdb.h>
#include <inttypes.h>
#include <xtables.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_SOURCE '1'
#define IP_DEST '2' #define IP_DEST '2'
...@@ -27,6 +60,8 @@ ...@@ -27,6 +60,8 @@
#define IP_PROTO '4' #define IP_PROTO '4'
#define IP_SPORT '5' #define IP_SPORT '5'
#define IP_DPORT '6' #define IP_DPORT '6'
#define IP_EBT_ICMP '7'
#define IP_EBT_IGMP '8'
static const struct option brip_opts[] = { static const struct option brip_opts[] = {
{ .name = "ip-source", .has_arg = true, .val = IP_SOURCE }, { .name = "ip-source", .has_arg = true, .val = IP_SOURCE },
...@@ -40,9 +75,73 @@ static const struct option brip_opts[] = { ...@@ -40,9 +75,73 @@ static const struct option brip_opts[] = {
{ .name = "ip-sport", .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-destination-port",.has_arg = true, .val = IP_DPORT },
{ .name = "ip-dport", .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, 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) static void brip_print_help(void)
{ {
printf( printf(
...@@ -52,7 +151,14 @@ static void brip_print_help(void) ...@@ -52,7 +151,14 @@ static void brip_print_help(void)
"--ip-tos [!] tos : ip tos specification\n" "--ip-tos [!] tos : ip tos specification\n"
"--ip-proto [!] protocol : ip protocol specification\n" "--ip-proto [!] protocol : ip protocol specification\n"
"--ip-sport [!] port[:port] : tcp/udp source port or port range\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) 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) ...@@ -161,6 +267,118 @@ static void ebt_parse_ip_address(char *address, uint32_t *addr, uint32_t *msk)
*addr = *addr & *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 static int
brip_parse(int c, char **argv, int invert, unsigned int *flags, brip_parse(int c, char **argv, int invert, unsigned int *flags,
const void *entry, struct xt_entry_match **match) const void *entry, struct xt_entry_match **match)
...@@ -192,6 +410,20 @@ brip_parse(int c, char **argv, int invert, unsigned int *flags, ...@@ -192,6 +410,20 @@ brip_parse(int c, char **argv, int invert, unsigned int *flags,
parse_port_range(NULL, optarg, info->dport); parse_port_range(NULL, optarg, info->dport);
info->bitmask |= EBT_IP_DPORT; info->bitmask |= EBT_IP_DPORT;
break; 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: case IP_EBT_TOS:
if (invert) if (invert)
info->invflags |= EBT_IP_TOS; info->invflags |= EBT_IP_TOS;
...@@ -289,6 +521,194 @@ static void brip_print(const void *ip, const struct xt_entry_match *match, ...@@ -289,6 +521,194 @@ static void brip_print(const void *ip, const struct xt_entry_match *match,
printf("! "); printf("! ");
print_port_range(info->dport); 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 = { static struct xtables_match brip_match = {
...@@ -303,6 +723,7 @@ static struct xtables_match brip_match = { ...@@ -303,6 +723,7 @@ static struct xtables_match brip_match = {
.parse = brip_parse, .parse = brip_parse,
.final_check = brip_final_check, .final_check = brip_final_check,
.print = brip_print, .print = brip_print,
.xlate = brip_xlate,
.extra_opts = brip_opts, .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[] = ...@@ -133,8 +133,8 @@ static struct rates g_rates[] =
{ {
{ "day", EBT_LIMIT_SCALE*24*60*60 }, { "day", EBT_LIMIT_SCALE*24*60*60 },
{ "hour", EBT_LIMIT_SCALE*60*60 }, { "hour", EBT_LIMIT_SCALE*60*60 },
{ "min", EBT_LIMIT_SCALE*60 }, { "minute", EBT_LIMIT_SCALE*60 },
{ "sec", EBT_LIMIT_SCALE } { "second", EBT_LIMIT_SCALE }
}; };
static void print_rate(uint32_t period) static void print_rate(uint32_t period)
...@@ -159,6 +159,31 @@ static void brlimit_print(const void *ip, const struct xt_entry_match *match, ...@@ -159,6 +159,31 @@ static void brlimit_print(const void *ip, const struct xt_entry_match *match,
printf("--limit-burst %u ", r->burst); 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 = { static struct xtables_match brlimit_match = {
.name = "limit", .name = "limit",
.revision = 0, .revision = 0,
...@@ -170,6 +195,7 @@ static struct xtables_match brlimit_match = { ...@@ -170,6 +195,7 @@ static struct xtables_match brlimit_match = {
.help = brlimit_print_help, .help = brlimit_print_help,
.parse = brlimit_parse, .parse = brlimit_parse,
.print = brlimit_print, .print = brlimit_print,
.xlate = brlimit_xlate,
.extra_opts = brlimit_opts, .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, ...@@ -176,6 +176,27 @@ static void brlog_print(const void *ip, const struct xt_entry_target *target,
printf(" "); 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 = { static struct xtables_target brlog_target = {
.name = "log", .name = "log",
.revision = 0, .revision = 0,
...@@ -188,6 +209,7 @@ static struct xtables_target brlog_target = { ...@@ -188,6 +209,7 @@ static struct xtables_target brlog_target = {
.parse = brlog_parse, .parse = brlog_parse,
.final_check = brlog_final_check, .final_check = brlog_final_check,
.print = brlog_print, .print = brlog_print,
.xlate = brlog_xlate,
.extra_opts = brlog_opts, .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) ...@@ -170,6 +170,49 @@ static void brmark_final_check(unsigned int flags)
"You must specify some option"); "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 = { static struct xtables_target brmark_target = {
.name = "mark", .name = "mark",
.revision = 0, .revision = 0,
...@@ -182,6 +225,7 @@ static struct xtables_target brmark_target = { ...@@ -182,6 +225,7 @@ static struct xtables_target brmark_target = {
.parse = brmark_parse, .parse = brmark_parse,
.final_check = brmark_final_check, .final_check = brmark_final_check,
.print = brmark_print, .print = brmark_print,
.xlate = brmark_xlate,
.extra_opts = brmark_opts, .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, ...@@ -97,6 +97,30 @@ static void brmark_m_print(const void *ip, const struct xt_entry_match *match,
printf("0x%lx ", info->mark); 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 = { static struct xtables_match brmark_m_match = {
.name = "mark_m", .name = "mark_m",
.revision = 0, .revision = 0,
...@@ -109,6 +133,7 @@ static struct xtables_match brmark_m_match = { ...@@ -109,6 +133,7 @@ static struct xtables_match brmark_m_match = {
.parse = brmark_m_parse, .parse = brmark_m_parse,
.final_check = brmark_m_final_check, .final_check = brmark_m_final_check,
.print = brmark_m_print, .print = brmark_m_print,
.xlate = brmark_m_xlate,
.extra_opts = brmark_m_opts, .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