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

New upstream version 1.8.1

parent f1f129da
ebtables-translate -t nat -A POSTROUTING -s 0:0:0:0:0:0 -o someport+ --to-source de:ad:00:be:ee:ff
nft add rule bridge nat POSTROUTING oifname "someport*" ether saddr 00:00:00:00:00:00 ether saddr set de:ad:0:be:ee:ff accept counter
ebtables-translate -t nat -A POSTROUTING -o someport --to-src de:ad:00:be:ee:ff --snat-target CONTINUE
nft add rule bridge nat POSTROUTING oifname "someport" ether saddr set de:ad:0:be:ee:ff continue counter
/* ebt_stp
*
* Authors:
* Bart De Schuymer <bdschuym@pandora.be>
*
* July, 2003
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <getopt.h>
#include <netinet/ether.h>
#include <linux/netfilter_bridge/ebt_stp.h>
#include <xtables.h>
#include "iptables/nft.h"
#include "iptables/nft-bridge.h"
#define STP_TYPE 'a'
#define STP_FLAGS 'b'
#define STP_ROOTPRIO 'c'
#define STP_ROOTADDR 'd'
#define STP_ROOTCOST 'e'
#define STP_SENDERPRIO 'f'
#define STP_SENDERADDR 'g'
#define STP_PORT 'h'
#define STP_MSGAGE 'i'
#define STP_MAXAGE 'j'
#define STP_HELLOTIME 'k'
#define STP_FWDD 'l'
#define STP_NUMOPS 12
static const struct option brstp_opts[] =
{
{ "stp-type" , required_argument, 0, STP_TYPE},
{ "stp-flags" , required_argument, 0, STP_FLAGS},
{ "stp-root-prio" , required_argument, 0, STP_ROOTPRIO},
{ "stp-root-addr" , required_argument, 0, STP_ROOTADDR},
{ "stp-root-cost" , required_argument, 0, STP_ROOTCOST},
{ "stp-sender-prio" , required_argument, 0, STP_SENDERPRIO},
{ "stp-sender-addr" , required_argument, 0, STP_SENDERADDR},
{ "stp-port" , required_argument, 0, STP_PORT},
{ "stp-msg-age" , required_argument, 0, STP_MSGAGE},
{ "stp-max-age" , required_argument, 0, STP_MAXAGE},
{ "stp-hello-time" , required_argument, 0, STP_HELLOTIME},
{ "stp-forward-delay", required_argument, 0, STP_FWDD},
{ 0 }
};
#define BPDU_TYPE_CONFIG 0
#define BPDU_TYPE_TCN 0x80
#define BPDU_TYPE_CONFIG_STRING "config"
#define BPDU_TYPE_TCN_STRING "tcn"
#define FLAG_TC 0x01
#define FLAG_TC_ACK 0x80
#define FLAG_TC_STRING "topology-change"
#define FLAG_TC_ACK_STRING "topology-change-ack"
static void brstp_print_help(void)
{
printf(
"stp options:\n"
"--stp-type type : BPDU type\n"
"--stp-flags flag : control flag\n"
"--stp-root-prio prio[:prio] : root priority (16-bit) range\n"
"--stp-root-addr address[/mask] : MAC address of root\n"
"--stp-root-cost cost[:cost] : root cost (32-bit) range\n"
"--stp-sender-prio prio[:prio] : sender priority (16-bit) range\n"
"--stp-sender-addr address[/mask] : MAC address of sender\n"
"--stp-port port[:port] : port id (16-bit) range\n"
"--stp-msg-age age[:age] : message age timer (16-bit) range\n"
"--stp-max-age age[:age] : maximum age timer (16-bit) range\n"
"--stp-hello-time time[:time] : hello time timer (16-bit) range\n"
"--stp-forward-delay delay[:delay]: forward delay timer (16-bit) range\n"
" Recognized BPDU type strings:\n"
" \"config\": configuration BPDU (=0)\n"
" \"tcn\" : topology change notification BPDU (=0x80)\n"
" Recognized control flag strings:\n"
" \"topology-change\" : topology change flag (0x01)\n"
" \"topology-change-ack\": topology change acknowledgement flag (0x80)");
}
static int parse_range(const char *portstring, void *lower, void *upper,
int bits, uint32_t min, uint32_t max)
{
char *buffer;
char *cp, *end;
uint32_t low_nr, upp_nr;
int ret = 0;
buffer = strdup(portstring);
if ((cp = strchr(buffer, ':')) == NULL) {
low_nr = strtoul(buffer, &end, 10);
if (*end || low_nr < min || low_nr > max) {
ret = -1;
goto out;
}
if (bits == 2) {
*(uint16_t *)lower = low_nr;
*(uint16_t *)upper = low_nr;
} else {
*(uint32_t *)lower = low_nr;
*(uint32_t *)upper = low_nr;
}
} else {
*cp = '\0';
cp++;
if (!*buffer)
low_nr = min;
else {
low_nr = strtoul(buffer, &end, 10);
if (*end || low_nr < min) {
ret = -1;
goto out;
}
}
if (!*cp)
upp_nr = max;
else {
upp_nr = strtoul(cp, &end, 10);
if (*end || upp_nr > max) {
ret = -1;
goto out;
}
}
if (upp_nr < low_nr) {
ret = -1;
goto out;
}
if (bits == 2) {
*(uint16_t *)lower = low_nr;
*(uint16_t *)upper = upp_nr;
} else {
*(uint32_t *)lower = low_nr;
*(uint32_t *)upper = upp_nr;
}
}
out:
free(buffer);
return ret;
}
static void print_range(unsigned int l, unsigned int u)
{
if (l == u)
printf("%u ", l);
else
printf("%u:%u ", l, u);
}
static int brstp_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 int
brstp_parse(int c, char **argv, int invert, unsigned int *flags,
const void *entry, struct xt_entry_match **match)
{
struct ebt_stp_info *stpinfo = (struct ebt_stp_info *)(*match)->data;
unsigned int flag;
long int i;
char *end = NULL;
if (c < 'a' || c > ('a' + STP_NUMOPS - 1))
return 0;
flag = 1 << (c - 'a');
EBT_CHECK_OPTION(flags, flag);
if (invert)
stpinfo->invflags |= flag;
stpinfo->bitmask |= flag;
switch (flag) {
case EBT_STP_TYPE:
i = strtol(optarg, &end, 0);
if (i < 0 || i > 255 || *end != '\0') {
if (!strcasecmp(optarg, BPDU_TYPE_CONFIG_STRING))
stpinfo->type = BPDU_TYPE_CONFIG;
else if (!strcasecmp(optarg, BPDU_TYPE_TCN_STRING))
stpinfo->type = BPDU_TYPE_TCN;
else
xtables_error(PARAMETER_PROBLEM, "Bad --stp-type argument");
} else
stpinfo->type = i;
break;
case EBT_STP_FLAGS:
i = strtol(optarg, &end, 0);
if (i < 0 || i > 255 || *end != '\0') {
if (!strcasecmp(optarg, FLAG_TC_STRING))
stpinfo->config.flags = FLAG_TC;
else if (!strcasecmp(optarg, FLAG_TC_ACK_STRING))
stpinfo->config.flags = FLAG_TC_ACK;
else
xtables_error(PARAMETER_PROBLEM, "Bad --stp-flags argument");
} else
stpinfo->config.flags = i;
break;
case EBT_STP_ROOTPRIO:
if (parse_range(argv[optind-1], &(stpinfo->config.root_priol),
&(stpinfo->config.root_priou), 2, 0, 0xffff))
xtables_error(PARAMETER_PROBLEM, "Bad --stp-root-prio range");
break;
case EBT_STP_ROOTCOST:
if (parse_range(argv[optind-1], &(stpinfo->config.root_costl),
&(stpinfo->config.root_costu), 4, 0, 0xffffffff))
xtables_error(PARAMETER_PROBLEM, "Bad --stp-root-cost range");
break;
case EBT_STP_SENDERPRIO:
if (parse_range(argv[optind-1], &(stpinfo->config.sender_priol),
&(stpinfo->config.sender_priou), 2, 0, 0xffff))
xtables_error(PARAMETER_PROBLEM, "Bad --stp-sender-prio range");
break;
case EBT_STP_PORT:
if (parse_range(argv[optind-1], &(stpinfo->config.portl),
&(stpinfo->config.portu), 2, 0, 0xffff))
xtables_error(PARAMETER_PROBLEM, "Bad --stp-port-range");
break;
case EBT_STP_MSGAGE:
if (parse_range(argv[optind-1], &(stpinfo->config.msg_agel),
&(stpinfo->config.msg_ageu), 2, 0, 0xffff))
xtables_error(PARAMETER_PROBLEM, "Bad --stp-msg-age range");
break;
case EBT_STP_MAXAGE:
if (parse_range(argv[optind-1], &(stpinfo->config.max_agel),
&(stpinfo->config.max_ageu), 2, 0, 0xffff))
xtables_error(PARAMETER_PROBLEM, "Bad --stp-max-age range");
break;
case EBT_STP_HELLOTIME:
if (parse_range(argv[optind-1], &(stpinfo->config.hello_timel),
&(stpinfo->config.hello_timeu), 2, 0, 0xffff))
xtables_error(PARAMETER_PROBLEM, "Bad --stp-hello-time range");
break;
case EBT_STP_FWDD:
if (parse_range(argv[optind-1], &(stpinfo->config.forward_delayl),
&(stpinfo->config.forward_delayu), 2, 0, 0xffff))
xtables_error(PARAMETER_PROBLEM, "Bad --stp-forward-delay range");
break;
case EBT_STP_ROOTADDR:
if (brstp_get_mac_and_mask(argv[optind-1],
(unsigned char *)stpinfo->config.root_addr,
(unsigned char *)stpinfo->config.root_addrmsk))
xtables_error(PARAMETER_PROBLEM, "Bad --stp-root-addr address");
break;
case EBT_STP_SENDERADDR:
if (brstp_get_mac_and_mask(argv[optind-1],
(unsigned char *)stpinfo->config.sender_addr,
(unsigned char *)stpinfo->config.sender_addrmsk))
xtables_error(PARAMETER_PROBLEM, "Bad --stp-sender-addr address");
break;
default:
xtables_error(PARAMETER_PROBLEM, "Unknown stp option");
}
return 1;
}
static void ebt_print_mac(const unsigned char *mac)
{
int j;
for (j = 0; j < ETH_ALEN; j++)
printf("%02x%s", mac[j],
(j==ETH_ALEN-1) ? "" : ":");
}
static bool mac_all_ones(const unsigned char *mac)
{
static const char hlpmsk[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
return memcmp(mac, hlpmsk, sizeof(hlpmsk)) == 0;
}
static void ebt_print_mac_and_mask(const unsigned char *mac, const unsigned char *mask)
{
ebt_print_mac(mac);
if (!mac_all_ones(mask)) {
printf("/");
ebt_print_mac(mask);
}
}
static void brstp_print(const void *ip, const struct xt_entry_match *match,
int numeric)
{
const struct ebt_stp_info *stpinfo = (struct ebt_stp_info *)match->data;
const struct ebt_stp_config_info *c = &(stpinfo->config);
int i;
for (i = 0; i < STP_NUMOPS; i++) {
if (!(stpinfo->bitmask & (1 << i)))
continue;
printf("--%s %s", brstp_opts[i].name,
(stpinfo->invflags & (1 << i)) ? "! " : "");
if (EBT_STP_TYPE == (1 << i)) {
if (stpinfo->type == BPDU_TYPE_CONFIG)
printf("%s", BPDU_TYPE_CONFIG_STRING);
else if (stpinfo->type == BPDU_TYPE_TCN)
printf("%s", BPDU_TYPE_TCN_STRING);
else
printf("%d", stpinfo->type);
} else if (EBT_STP_FLAGS == (1 << i)) {
if (c->flags == FLAG_TC)
printf("%s", FLAG_TC_STRING);
else if (c->flags == FLAG_TC_ACK)
printf("%s", FLAG_TC_ACK_STRING);
else
printf("%d", c->flags);
} else if (EBT_STP_ROOTPRIO == (1 << i))
print_range(c->root_priol, c->root_priou);
else if (EBT_STP_ROOTADDR == (1 << i))
ebt_print_mac_and_mask((unsigned char *)c->root_addr,
(unsigned char*)c->root_addrmsk);
else if (EBT_STP_ROOTCOST == (1 << i))
print_range(c->root_costl, c->root_costu);
else if (EBT_STP_SENDERPRIO == (1 << i))
print_range(c->sender_priol, c->sender_priou);
else if (EBT_STP_SENDERADDR == (1 << i))
ebt_print_mac_and_mask((unsigned char *)c->sender_addr,
(unsigned char *)c->sender_addrmsk);
else if (EBT_STP_PORT == (1 << i))
print_range(c->portl, c->portu);
else if (EBT_STP_MSGAGE == (1 << i))
print_range(c->msg_agel, c->msg_ageu);
else if (EBT_STP_MAXAGE == (1 << i))
print_range(c->max_agel, c->max_ageu);
else if (EBT_STP_HELLOTIME == (1 << i))
print_range(c->hello_timel, c->hello_timeu);
else if (EBT_STP_FWDD == (1 << i))
print_range(c->forward_delayl, c->forward_delayu);
printf(" ");
}
}
static struct xtables_match brstp_match = {
.name = "stp",
.version = XTABLES_VERSION,
.family = NFPROTO_BRIDGE,
.size = sizeof(struct ebt_stp_info),
.help = brstp_print_help,
.parse = brstp_parse,
.print = brstp_print,
.extra_opts = brstp_opts,
};
void _init(void)
{
xtables_register_match(&brstp_match);
}
/* ebt_vlan
*
* Authors:
* Bart De Schuymer <bdschuym@pandora.be>
* Nick Fedchik <nick@fedchik.org.ua>
* June, 2002
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <ctype.h>
#include <xtables.h>
#include <linux/netfilter_bridge/ebt_vlan.h>
#include <linux/if_ether.h>
#include "iptables/nft.h"
#include "iptables/nft-bridge.h"
#define NAME_VLAN_ID "id"
#define NAME_VLAN_PRIO "prio"
#define NAME_VLAN_ENCAP "encap"
#define VLAN_ID '1'
#define VLAN_PRIO '2'
#define VLAN_ENCAP '3'
static const struct option brvlan_opts[] = {
{"vlan-id" , required_argument, NULL, VLAN_ID},
{"vlan-prio" , required_argument, NULL, VLAN_PRIO},
{"vlan-encap", required_argument, NULL, VLAN_ENCAP},
XT_GETOPT_TABLEEND,
};
/*
* option inverse flags definition
*/
#define OPT_VLAN_ID 0x01
#define OPT_VLAN_PRIO 0x02
#define OPT_VLAN_ENCAP 0x04
#define OPT_VLAN_FLAGS (OPT_VLAN_ID | OPT_VLAN_PRIO | OPT_VLAN_ENCAP)
static void brvlan_print_help(void)
{
printf(
"vlan options:\n"
"--vlan-id [!] id : vlan-tagged frame identifier, 0,1-4096 (integer)\n"
"--vlan-prio [!] prio : Priority-tagged frame's user priority, 0-7 (integer)\n"
"--vlan-encap [!] encap : Encapsulated frame protocol (hexadecimal or name)\n");
}
static int
brvlan_parse(int c, char **argv, int invert, unsigned int *flags,
const void *entry, struct xt_entry_match **match)
{
struct ebt_vlan_info *vlaninfo = (struct ebt_vlan_info *) (*match)->data;
struct xt_ethertypeent *ethent;
char *end;
struct ebt_vlan_info local;
switch (c) {
case VLAN_ID:
EBT_CHECK_OPTION(flags, OPT_VLAN_ID);
if (invert)
vlaninfo->invflags |= EBT_VLAN_ID;
local.id = strtoul(optarg, &end, 10);
if (local.id > 4094 || *end != '\0')
xtables_error(PARAMETER_PROBLEM, "Invalid --vlan-id range ('%s')", optarg);
vlaninfo->id = local.id;
vlaninfo->bitmask |= EBT_VLAN_ID;
break;
case VLAN_PRIO:
EBT_CHECK_OPTION(flags, OPT_VLAN_PRIO);
if (invert)
vlaninfo->invflags |= EBT_VLAN_PRIO;
local.prio = strtoul(optarg, &end, 10);
if (local.prio >= 8 || *end != '\0')
xtables_error(PARAMETER_PROBLEM, "Invalid --vlan-prio range ('%s')", optarg);
vlaninfo->prio = local.prio;
vlaninfo->bitmask |= EBT_VLAN_PRIO;
break;
case VLAN_ENCAP:
EBT_CHECK_OPTION(flags, OPT_VLAN_ENCAP);
if (invert)
vlaninfo->invflags |= EBT_VLAN_ENCAP;
local.encap = strtoul(optarg, &end, 16);
if (*end != '\0') {
ethent = xtables_getethertypebyname(optarg);
if (ethent == NULL)
xtables_error(PARAMETER_PROBLEM, "Unknown --vlan-encap value ('%s')", optarg);
local.encap = ethent->e_ethertype;
}
if (local.encap < ETH_ZLEN)
xtables_error(PARAMETER_PROBLEM, "Invalid --vlan-encap range ('%s')", optarg);
vlaninfo->encap = htons(local.encap);
vlaninfo->bitmask |= EBT_VLAN_ENCAP;
break;
default:
return 0;
}
return 1;
}
static void brvlan_print(const void *ip, const struct xt_entry_match *match,
int numeric)
{
struct ebt_vlan_info *vlaninfo = (struct ebt_vlan_info *) match->data;
if (vlaninfo->bitmask & EBT_VLAN_ID) {
printf("--vlan-id %s%d ", (vlaninfo->invflags & EBT_VLAN_ID) ? "! " : "", vlaninfo->id);
}
if (vlaninfo->bitmask & EBT_VLAN_PRIO) {
printf("--vlan-prio %s%d ", (vlaninfo->invflags & EBT_VLAN_PRIO) ? "! " : "", vlaninfo->prio);
}
if (vlaninfo->bitmask & EBT_VLAN_ENCAP) {
printf("--vlan-encap %s", (vlaninfo->invflags & EBT_VLAN_ENCAP) ? "! " : "");
printf("%4.4X ", ntohs(vlaninfo->encap));
}
}
static int brvlan_xlate(struct xt_xlate *xl,
const struct xt_xlate_mt_params *params)
{
const struct ebt_vlan_info *vlaninfo = (const void*)params->match->data;
if (vlaninfo->bitmask & EBT_VLAN_ID)
xt_xlate_add(xl, "vlan id %s%d ", (vlaninfo->invflags & EBT_VLAN_ID) ? "!= " : "", vlaninfo->id);
if (vlaninfo->bitmask & EBT_VLAN_PRIO)
xt_xlate_add(xl, "vlan pcp %s%d ", (vlaninfo->invflags & EBT_VLAN_PRIO) ? "!= " : "", vlaninfo->prio);
if (vlaninfo->bitmask & EBT_VLAN_ENCAP)
xt_xlate_add(xl, "vlan type %s0x%4.4x ", (vlaninfo->invflags & EBT_VLAN_ENCAP) ? "!= " : "", ntohs(vlaninfo->encap));
return 1;
}
static struct xtables_match brvlan_match = {
.name = "vlan",
.version = XTABLES_VERSION,
.family = NFPROTO_BRIDGE,
.size = XT_ALIGN(sizeof(struct ebt_vlan_info)),
.userspacesize = XT_ALIGN(sizeof(struct ebt_vlan_info)),
.help = brvlan_print_help,
.parse = brvlan_parse,
.print = brvlan_print,
.xlate = brvlan_xlate,
.extra_opts = brvlan_opts,
};
void _init(void)
{
xtables_register_match(&brvlan_match);
}
ebtables-translate -A INPUT -p 802_1Q --vlan-id 42
nft add rule bridge filter INPUT vlan id 42 counter
ebtables-translate -A INPUT -p 802_1Q --vlan-prio ! 1
nft add rule bridge filter INPUT vlan pcp != 1 counter
ebtables-translate -A INPUT -p 802_1Q --vlan-encap ip
nft add rule bridge filter INPUT vlan type 0x0800 counter
ebtables-translate -A INPUT -p 802_1Q --vlan-encap ipv6 ! --vlan-id 1
nft add rule bridge filter INPUT vlan id != 1 vlan type 0x86dd counter
......@@ -34,6 +34,15 @@ static void DNAT_help(void)
"[--random] [--persistent]\n");
}
static void DNAT_help_v2(void)
{
printf(
"DNAT target options:\n"
" --to-destination [<ipaddr>[-<ipaddr>]][:port[-port[/port]]]\n"
" Address to map destination to.\n"
"[--random] [--persistent]\n");
}
static const struct xt_option_entry DNAT_opts[] = {
{.name = "to-destination", .id = O_TO_DEST, .type = XTTYPE_STRING,
.flags = XTOPT_MAND | XTOPT_MULTI},
......@@ -44,7 +53,7 @@ static const struct xt_option_entry DNAT_opts[] = {
/* Ranges expected in network order. */
static void
parse_to(const char *orig_arg, int portok, struct nf_nat_range *range)
parse_to(const char *orig_arg, int portok, struct nf_nat_range2 *range, int rev)
{
char *arg, *start, *end = NULL, *colon = NULL, *dash, *error;
const struct in6_addr *ip;
......@@ -109,6 +118,20 @@ parse_to(const char *orig_arg, int portok, struct nf_nat_range *range)
"Port range `%s' funky\n", colon+1);
range->min_proto.tcp.port = htons(port);
range->max_proto.tcp.port = htons(maxport);
if (rev >= 2) {
char *slash = strchr(dash, '/');
if (slash) {
int baseport;
baseport = atoi(slash + 1);
if (baseport <= 0 || baseport > 65535)
xtables_error(PARAMETER_PROBLEM,
"Port `%s' not valid\n", slash+1);
range->flags |= NF_NAT_RANGE_PROTO_OFFSET;
range->base_proto.tcp.port = htons(baseport);
}
}
}
/* Starts with colon or [] colon? No IP info...*/
if (colon == arg || colon == arg+2) {
......@@ -144,10 +167,10 @@ parse_to(const char *orig_arg, int portok, struct nf_nat_range *range)
return;
}
static void DNAT_parse(struct xt_option_call *cb)
static void _DNAT_parse(struct xt_option_call *cb,
struct nf_nat_range2 *range, int rev)
{
const struct ip6t_entry *entry = cb->xt_entry;
struct nf_nat_range *range = cb->data;
int portok;
if (entry->ipv6.proto == IPPROTO_TCP ||
......@@ -163,13 +186,11 @@ static void DNAT_parse(struct xt_option_call *cb)
switch (cb->entry->id) {
case O_TO_DEST:
if (cb->xflags & F_X_TO_DEST) {
if (!kernel_version)
get_kernel_version();
if (kernel_version > LINUX_VERSION(2, 6, 10))
xtables_error(PARAMETER_PROBLEM,
"DNAT: Multiple --to-destination not supported");
}
parse_to(cb->arg, portok, range);
parse_to(cb->arg, portok, range, rev);
cb->xflags |= F_X_TO_DEST;
break;
case O_PERSISTENT:
range->flags |= NF_NAT_RANGE_PERSISTENT;
......@@ -177,16 +198,40 @@ static void DNAT_parse(struct xt_option_call *cb)
}
}
static void DNAT_fcheck(struct xt_fcheck_call *cb)
static void DNAT_parse(struct xt_option_call *cb)
{
struct nf_nat_range *range_v1 = (void *)cb->data;
struct nf_nat_range2 range = {};
memcpy(&range, range_v1, sizeof(*range_v1));
_DNAT_parse(cb, &range, 1);
memcpy(range_v1, &range, sizeof(*range_v1));
}
static void DNAT_parse_v2(struct xt_option_call *cb)
{
_DNAT_parse(cb, (struct nf_nat_range2 *)cb->data, 2);
}
static void _DNAT_fcheck(struct xt_fcheck_call *cb, unsigned int *flags)
{
static const unsigned int f = F_TO_DEST | F_RANDOM;
struct nf_nat_range *mr = cb->data;
if ((cb->xflags & f) == f)
mr->flags |= NF_NAT_RANGE_PROTO_RANDOM;
*flags |= NF_NAT_RANGE_PROTO_RANDOM;
}
static void DNAT_fcheck(struct xt_fcheck_call *cb)
{
_DNAT_fcheck(cb, &((struct nf_nat_range *)cb->data)->flags);
}
static void DNAT_fcheck_v2(struct xt_fcheck_call *cb)
{
_DNAT_fcheck(cb, &((struct nf_nat_range2 *)cb->data)->flags);
}
static void print_range(const struct nf_nat_range *range)
static void print_range(const struct nf_nat_range2 *range, int rev)
{
if (range->flags & NF_NAT_RANGE_MAP_IPS) {
if (range->flags & NF_NAT_RANGE_PROTO_SPECIFIED)
......@@ -203,36 +248,63 @@ static void print_range(const struct nf_nat_range *range)
printf("%hu", ntohs(range->min_proto.tcp.port));
if (range->max_proto.tcp.port != range->min_proto.tcp.port)
printf("-%hu", ntohs(range->max_proto.tcp.port));
if (rev >= 2 && (range->flags & NF_NAT_RANGE_PROTO_OFFSET))
printf("/%hu", ntohs(range->base_proto.tcp.port));
}
}
static void DNAT_print(const void *ip, const struct xt_entry_target *target,
int numeric)
static void _DNAT_print(const struct nf_nat_range2 *range, int rev)
{
const struct nf_nat_range *range = (const void *)target->data;
printf(" to:");
print_range(range);
print_range(range, rev);
if (range->flags & NF_NAT_RANGE_PROTO_RANDOM)
printf(" random");
if (range->flags & NF_NAT_RANGE_PERSISTENT)
printf(" persistent");
}
static void DNAT_save(const void *ip, const struct xt_entry_target *target)
static void DNAT_print(const void *ip, const struct xt_entry_target *target,
int numeric)
{
const struct nf_nat_range *range_v1 = (const void *)target->data;
struct nf_nat_range2 range = {};
memcpy(&range, range_v1, sizeof(*range_v1));
_DNAT_print(&range, 1);
}
static void DNAT_print_v2(const void *ip, const struct xt_entry_target *target,
int numeric)
{
const struct nf_nat_range *range = (const void *)target->data;
_DNAT_print((const struct nf_nat_range2 *)target->data, 2);
}
static void _DNAT_save(const struct nf_nat_range2 *range, int rev)
{
printf(" --to-destination ");
print_range(range);
print_range(range, rev);
if (range->flags & NF_NAT_RANGE_PROTO_RANDOM)
printf(" --random");
if (range->flags & NF_NAT_RANGE_PERSISTENT)
printf(" --persistent");
}
static void print_range_xlate(const struct nf_nat_range *range,
struct xt_xlate *xl)
static void DNAT_save(const void *ip, const struct xt_entry_target *target)
{
const struct nf_nat_range *range_v1 = (const void *)target->data;
struct nf_nat_range2 range = {};
memcpy(&range, range_v1, sizeof(*range_v1));
_DNAT_save(&range, 1);
}
static void DNAT_save_v2(const void *ip, const struct xt_entry_target *target)
{
_DNAT_save((const struct nf_nat_range2 *)target->data, 2);
}
static void print_range_xlate(const struct nf_nat_range2 *range,
struct xt_xlate *xl, int rev)
{
bool proto_specified = range->flags & NF_NAT_RANGE_PROTO_SPECIFIED;
......@@ -259,15 +331,14 @@ static void print_range_xlate(const struct nf_nat_range *range,
}
}
static int DNAT_xlate(struct xt_xlate *xl,
const struct xt_xlate_tg_params *params)
static int _DNAT_xlate(struct xt_xlate *xl,
const struct nf_nat_range2 *range, int rev)
{
const struct nf_nat_range *range = (const void *)params->target->data;
bool sep_need = false;
const char *sep = " ";
xt_xlate_add(xl, "dnat to ");
print_range_xlate(range, xl);
print_range_xlate(range, xl, rev);
if (range->flags & NF_NAT_RANGE_PROTO_RANDOM) {
xt_xlate_add(xl, " random");
sep_need = true;
......@@ -281,7 +352,28 @@ static int DNAT_xlate(struct xt_xlate *xl,
return 1;
}
static struct xtables_target snat_tg_reg = {
static int DNAT_xlate(struct xt_xlate *xl,
const struct xt_xlate_tg_params *params)
{
const struct nf_nat_range *range_v1 = (const void *)params->target->data;
struct nf_nat_range2 range = {};
memcpy(&range, range_v1, sizeof(*range_v1));
_DNAT_xlate(xl, &range, 1);
return 1;
}
static int DNAT_xlate_v2(struct xt_xlate *xl,
const struct xt_xlate_tg_params *params)
{
_DNAT_xlate(xl, (const struct nf_nat_range2 *)params->target->data, 2);
return 1;
}
static struct xtables_target dnat_tg_reg[] = {
{
.name = "DNAT",
.version = XTABLES_VERSION,
.family = NFPROTO_IPV6,
......@@ -289,15 +381,31 @@ static struct xtables_target snat_tg_reg = {
.size = XT_ALIGN(sizeof(struct nf_nat_range)),
.userspacesize = XT_ALIGN(sizeof(struct nf_nat_range)),
.help = DNAT_help,
.x6_parse = DNAT_parse,
.x6_fcheck = DNAT_fcheck,
.print = DNAT_print,
.save = DNAT_save,
.x6_parse = DNAT_parse,
.x6_fcheck = DNAT_fcheck,
.x6_options = DNAT_opts,
.xlate = DNAT_xlate,
},
{
.name = "DNAT",
.version = XTABLES_VERSION,
.family = NFPROTO_IPV6,
.revision = 2,
.size = XT_ALIGN(sizeof(struct nf_nat_range2)),
.userspacesize = XT_ALIGN(sizeof(struct nf_nat_range2)),
.help = DNAT_help_v2,
.print = DNAT_print_v2,
.save = DNAT_save_v2,
.x6_parse = DNAT_parse_v2,
.x6_fcheck = DNAT_fcheck_v2,
.x6_options = DNAT_opts,
.xlate = DNAT_xlate_v2,
},
};
void _init(void)
{
xtables_register_target(&snat_tg_reg);
xtables_register_targets(dnat_tg_reg, ARRAY_SIZE(dnat_tg_reg));
}
ip6tables-translate -t nat -A prerouting -i eth1 -p tcp --dport 8080 -j DNAT --to-destination [fec0::1234]:80
nft add rule ip6 nat prerouting iifname "eth1" tcp dport 8080 counter dnat to [fec0::1234]:80
ip6tables-translate -t nat -A prerouting -p tcp -j DNAT --to-destination [fec0::1234]:1-20
nft add rule ip6 nat prerouting meta l4proto tcp counter dnat to [fec0::1234]:1-20
ip6tables-translate -t nat -A prerouting -p tcp -j DNAT --to-destination [fec0::1234]:80 --persistent
nft add rule ip6 nat prerouting meta l4proto tcp counter dnat to [fec0::1234]:80 persistent
ip6tables-translate -t nat -A prerouting -p tcp -j DNAT --to-destination [fec0::1234]:80 --random --persistent
nft add rule ip6 nat prerouting meta l4proto tcp counter dnat to [fec0::1234]:80 random,persistent
iptables-translate -I INPUT -j LOG
nft insert rule ip filter INPUT counter log
ip6tables-translate -A FORWARD -p tcp -j LOG --log-level debug
nft add rule ip6 filter FORWARD meta l4proto tcp counter log level debug
ip6tables-translate -A FORWARD -p tcp -j LOG --log-prefix "Checking log"
nft add rule ip6 filter FORWARD meta l4proto tcp counter log prefix \"Checking log\"
......@@ -18,6 +18,7 @@
enum {
O_TO_PORTS = 0,
O_RANDOM,
O_RANDOM_FULLY,
};
static void MASQUERADE_help(void)
......@@ -27,12 +28,15 @@ static void MASQUERADE_help(void)
" --to-ports <port>[-<port>]\n"
" Port (range) to map to.\n"
" --random\n"
" Randomize source port.\n");
" Randomize source port.\n"
" --random-fully\n"
" Fully randomize source port.\n");
}
static const struct xt_option_entry MASQUERADE_opts[] = {
{.name = "to-ports", .id = O_TO_PORTS, .type = XTTYPE_STRING},
{.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE},
{.name = "random-fully", .id = O_RANDOM_FULLY, .type = XTTYPE_NONE},
XTOPT_TABLEEND,
};
......@@ -96,6 +100,9 @@ static void MASQUERADE_parse(struct xt_option_call *cb)
case O_RANDOM:
r->flags |= NF_NAT_RANGE_PROTO_RANDOM;
break;
case O_RANDOM_FULLY:
r->flags |= NF_NAT_RANGE_PROTO_RANDOM_FULLY;
break;
}
}
......@@ -114,6 +121,9 @@ MASQUERADE_print(const void *ip, const struct xt_entry_target *target,
if (r->flags & NF_NAT_RANGE_PROTO_RANDOM)
printf(" random");
if (r->flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY)
printf(" random-fully");
}
static void
......@@ -129,6 +139,9 @@ MASQUERADE_save(const void *ip, const struct xt_entry_target *target)
if (r->flags & NF_NAT_RANGE_PROTO_RANDOM)
printf(" --random");
if (r->flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY)
printf(" --random-fully");
}
static int MASQUERADE_xlate(struct xt_xlate *xl,
......@@ -148,6 +161,10 @@ static int MASQUERADE_xlate(struct xt_xlate *xl,
if (r->flags & NF_NAT_RANGE_PROTO_RANDOM)
xt_xlate_add(xl, "random ");
xt_xlate_add(xl, " ");
if (r->flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY)
xt_xlate_add(xl, "random-fully ");
return 1;
}
......
ip6tables-translate -t nat -A POSTROUTING -j MASQUERADE
nft add rule ip6 nat POSTROUTING counter masquerade
ip6tables-translate -t nat -A POSTROUTING -p tcp -j MASQUERADE --to-ports 10
nft add rule ip6 nat POSTROUTING meta l4proto tcp counter masquerade to :10
ip6tables-translate -t nat -A POSTROUTING -p tcp -j MASQUERADE --to-ports 10-20 --random
nft add rule ip6 nat POSTROUTING meta l4proto tcp counter masquerade to :10-20 random
ip6tables-translate -t nat -A prerouting -p tcp --dport 80 -j REDIRECT --to-ports 8080
nft add rule ip6 nat prerouting tcp dport 80 counter redirect to :8080
ip6tables-translate -t nat -A prerouting -p tcp --dport 80 -j REDIRECT --to-ports 8080 --random
nft add rule ip6 nat prerouting tcp dport 80 counter redirect to :8080 random
......@@ -13,13 +13,8 @@
struct reject_names {
const char *name;
const char *alias;
enum ip6t_reject_with with;
const char *desc;
};
struct reject_names_xlate {
const char *name;
enum ip6t_reject_with with;
const char *xlate;
};
enum {
......@@ -27,24 +22,50 @@ enum {
};
static const struct reject_names reject_table[] = {
{"icmp6-no-route", "no-route",
IP6T_ICMP6_NO_ROUTE, "ICMPv6 no route"},
{"icmp6-adm-prohibited", "adm-prohibited",
IP6T_ICMP6_ADM_PROHIBITED, "ICMPv6 administratively prohibited"},
[IP6T_ICMP6_NO_ROUTE] = {
"icmp6-no-route", "no-route",
"ICMPv6 no route",
"no-route",
},
[IP6T_ICMP6_ADM_PROHIBITED] = {
"icmp6-adm-prohibited", "adm-prohibited",
"ICMPv6 administratively prohibited",
"admin-prohibited",
},
#if 0
{"icmp6-not-neighbor", "not-neighbor"},
IP6T_ICMP6_NOT_NEIGHBOR, "ICMPv6 not a neighbor"},
[IP6T_ICMP6_NOT_NEIGHBOR] = {
"icmp6-not-neighbor", "not-neighbor",
"ICMPv6 not a neighbor",
},
#endif
{"icmp6-addr-unreachable", "addr-unreach",
IP6T_ICMP6_ADDR_UNREACH, "ICMPv6 address unreachable"},
{"icmp6-port-unreachable", "port-unreach",
IP6T_ICMP6_PORT_UNREACH, "ICMPv6 port unreachable"},
{"tcp-reset", "tcp-reset",
IP6T_TCP_RESET, "TCP RST packet"},
{"icmp6-policy-fail", "policy-fail",
IP6T_ICMP6_POLICY_FAIL, "ICMPv6 policy fail"},
{"icmp6-reject-route", "reject-route",
IP6T_ICMP6_REJECT_ROUTE, "ICMPv6 reject route"}
[IP6T_ICMP6_ADDR_UNREACH] = {
"icmp6-addr-unreachable", "addr-unreach",
"ICMPv6 address unreachable",
"addr-unreachable",
},
[IP6T_ICMP6_PORT_UNREACH] = {
"icmp6-port-unreachable", "port-unreach",
"ICMPv6 port unreachable",
"port-unreachable",
},
#if 0
[IP6T_ICMP6_ECHOREPLY] = {},
#endif
[IP6T_TCP_RESET] = {
"tcp-reset", "tcp-reset",
"TCP RST packet",
"tcp reset",
},
[IP6T_ICMP6_POLICY_FAIL] = {
"icmp6-policy-fail", "policy-fail",
"ICMPv6 policy fail",
"policy-fail",
},
[IP6T_ICMP6_REJECT_ROUTE] = {
"icmp6-reject-route", "reject-route",
"ICMPv6 reject route",
"reject-route",
},
};
static void
......@@ -55,6 +76,8 @@ print_reject_types(void)
printf("Valid reject types:\n");
for (i = 0; i < ARRAY_SIZE(reject_table); ++i) {
if (!reject_table[i].name)
continue;
printf(" %-25s\t%s\n", reject_table[i].name, reject_table[i].desc);
printf(" %-25s\talias\n", reject_table[i].alias);
}
......@@ -91,14 +114,17 @@ static void REJECT_parse(struct xt_option_call *cb)
unsigned int i;
xtables_option_parse(cb);
for (i = 0; i < ARRAY_SIZE(reject_table); ++i)
for (i = 0; i < ARRAY_SIZE(reject_table); ++i) {
if (!reject_table[i].name)
continue;
if (strncasecmp(reject_table[i].name,
cb->arg, strlen(cb->arg)) == 0 ||
strncasecmp(reject_table[i].alias,
cb->arg, strlen(cb->arg)) == 0) {
reject->with = reject_table[i].with;
reject->with = i;
return;
}
}
xtables_error(PARAMETER_PROBLEM,
"unknown reject type \"%s\"", cb->arg);
}
......@@ -108,55 +134,32 @@ static void REJECT_print(const void *ip, const struct xt_entry_target *target,
{
const struct ip6t_reject_info *reject
= (const struct ip6t_reject_info *)target->data;
unsigned int i;
for (i = 0; i < ARRAY_SIZE(reject_table); ++i)
if (reject_table[i].with == reject->with)
break;
printf(" reject-with %s", reject_table[i].name);
printf(" reject-with %s", reject_table[reject->with].name);
}
static void REJECT_save(const void *ip, const struct xt_entry_target *target)
{
const struct ip6t_reject_info *reject
= (const struct ip6t_reject_info *)target->data;
unsigned int i;
for (i = 0; i < ARRAY_SIZE(reject_table); ++i)
if (reject_table[i].with == reject->with)
break;
printf(" --reject-with %s", reject_table[i].name);
printf(" --reject-with %s", reject_table[reject->with].name);
}
static const struct reject_names_xlate reject_table_xlate[] = {
{"no-route", IP6T_ICMP6_NO_ROUTE},
{"admin-prohibited", IP6T_ICMP6_ADM_PROHIBITED},
{"addr-unreachable", IP6T_ICMP6_ADDR_UNREACH},
{"port-unreachable", IP6T_ICMP6_PORT_UNREACH},
{"tcp reset", IP6T_TCP_RESET},
{"policy-fail", IP6T_ICMP6_POLICY_FAIL},
{"reject-route", IP6T_ICMP6_REJECT_ROUTE}
};
static int REJECT_xlate(struct xt_xlate *xl,
const struct xt_xlate_tg_params *params)
{
const struct ip6t_reject_info *reject =
(const struct ip6t_reject_info *)params->target->data;
unsigned int i;
for (i = 0; i < ARRAY_SIZE(reject_table_xlate); ++i)
if (reject_table_xlate[i].with == reject->with)
break;
if (reject->with == IP6T_ICMP6_PORT_UNREACH)
xt_xlate_add(xl, "reject");
else if (reject->with == IP6T_TCP_RESET)
xt_xlate_add(xl, "reject with %s", reject_table_xlate[i].name);
xt_xlate_add(xl, "reject with %s",
reject_table[reject->with].xlate);
else
xt_xlate_add(xl, "reject with icmpv6 type %s",
reject_table_xlate[i].name);
reject_table[reject->with].xlate);
return 1;
}
......
ip6tables-translate -A FORWARD -p TCP --dport 22 -j REJECT
nft add rule ip6 filter FORWARD tcp dport 22 counter reject
ip6tables-translate -A FORWARD -p TCP --dport 22 -j REJECT --reject-with icmp6-reject-route
nft add rule ip6 filter FORWARD tcp dport 22 counter reject with icmpv6 type reject-route
ip6tables-translate -A FORWARD -p TCP --dport 22 -j REJECT --reject-with tcp-reset
nft add rule ip6 filter FORWARD tcp dport 22 counter reject with tcp reset
......@@ -166,13 +166,11 @@ static void SNAT_parse(struct xt_option_call *cb)
switch (cb->entry->id) {
case O_TO_SRC:
if (cb->xflags & F_X_TO_SRC) {
if (!kernel_version)
get_kernel_version();
if (kernel_version > LINUX_VERSION(2, 6, 10))
xtables_error(PARAMETER_PROBLEM,
"SNAT: Multiple --to-source not supported");
}
parse_to(cb->arg, portok, range);
cb->xflags |= F_X_TO_SRC;
break;
case O_PERSISTENT:
range->flags |= NF_NAT_RANGE_PERSISTENT;
......
ip6tables-translate -t nat -A postrouting -o eth0 -p tcp -j SNAT --to [fec0::1234]:80
nft add rule ip6 nat postrouting oifname "eth0" meta l4proto tcp counter snat to [fec0::1234]:80
ip6tables-translate -t nat -A postrouting -o eth0 -p tcp -j SNAT --to [fec0::1234]:1-20
nft add rule ip6 nat postrouting oifname "eth0" meta l4proto tcp counter snat to [fec0::1234]:1-20
ip6tables-translate -t nat -A postrouting -o eth0 -p tcp -j SNAT --to [fec0::1234]:123 --random
nft add rule ip6 nat postrouting oifname "eth0" meta l4proto tcp counter snat to [fec0::1234]:123 random
ip6tables-translate -t nat -A postrouting -o eth0 -p tcp -j SNAT --to [fec0::1234]:123 --random-fully --persistent
nft add rule ip6 nat postrouting oifname "eth0" meta l4proto tcp counter snat to [fec0::1234]:123 fully-random,persistent
ip6tables-translate -A INPUT -m ah --ahspi 500 -j DROP
nft add rule ip6 filter INPUT ah spi 500 counter drop
ip6tables-translate -A INPUT -m ah --ahspi 500:550 -j DROP
nft add rule ip6 filter INPUT ah spi 500-550 counter drop
ip6tables-translate -A INPUT -m ah ! --ahlen 120
nft add rule ip6 filter INPUT ah hdrlength != 120 counter
ip6tables-translate -A INPUT -m ah --ahres
nft add rule ip6 filter INPUT ah reserved 1 counter
ip6tables-translate -A INPUT -m ah --ahspi 500 ! --ahlen 120 -j DROP
nft add rule ip6 filter INPUT ah spi 500 ah hdrlength != 120 counter drop
ip6tables-translate -A INPUT -m ah --ahspi 500 --ahlen 120 --ahres -j ACCEPT
nft add rule ip6 filter INPUT ah spi 500 ah hdrlength 120 ah reserved 1 counter accept
ip6tables-translate -t filter -A INPUT -m frag --fragid 100:200 -j ACCEPT
nft add rule ip6 filter INPUT frag id 100-200 counter accept
ip6tables-translate -t filter -A INPUT -m frag --fragid 100 --fragres --fragmore -j ACCEPT
nft add rule ip6 filter INPUT frag id 100 frag reserved 1 frag more-fragments 1 counter accept
ip6tables-translate -t filter -A INPUT -m frag ! --fragid 100:200 -j ACCEPT
nft add rule ip6 filter INPUT frag id != 100-200 counter accept
ip6tables-translate -t filter -A INPUT -m frag --fragid 100:200 --fraglast -j ACCEPT
nft add rule ip6 filter INPUT frag id 100-200 frag more-fragments 0 counter accept
ip6tables-translate -t filter -A INPUT -m frag --fragid 100:200 --fragfirst -j ACCEPT
nft add rule ip6 filter INPUT frag id 100-200 frag frag-off 0 counter accept
ip6tables-translate -t filter -A INPUT -m frag --fraglast -j ACCEPT
nft add rule ip6 filter INPUT frag more-fragments 0 counter accept
......@@ -5,8 +5,6 @@
#include <xtables.h>
#include <linux/netfilter_ipv6/ip6t_opts.h>
#define DEBUG 0
enum {
O_HBH_LEN = 0,
O_HBH_OPTS,
......@@ -83,7 +81,7 @@ parse_options(const char *optsstr, uint16_t *opts)
opts[i] |= (0x00FF);
}
#if DEBUG
#ifdef DEBUG
printf("opts str: %s %s\n", cp, range);
printf("opts opt: %04X\n", opts[i]);
#endif
......@@ -92,7 +90,7 @@ parse_options(const char *optsstr, uint16_t *opts)
free(buffer);
#if DEBUG
#ifdef DEBUG
printf("addr nr: %d\n", i);
#endif
......
ip6tables-translate -t filter -A INPUT -m hbh --hbh-len 22
nft add rule ip6 filter INPUT hbh hdrlength 22 counter
ip6tables-translate -t filter -A INPUT -m hbh ! --hbh-len 22
nft add rule ip6 filter INPUT hbh hdrlength != 22 counter
ip6tables-translate -t nat -A postrouting -m hl --hl-gt 3
nft add rule ip6 nat postrouting ip6 hoplimit gt 3 counter
ip6tables-translate -t nat -A postrouting -m hl ! --hl-eq 3
nft add rule ip6 nat postrouting ip6 hoplimit != 3 counter
......@@ -6,17 +6,13 @@
#include <linux/netfilter_ipv6/ip6_tables.h>
#include <netinet/icmp6.h>
#include "libxt_icmp.h"
enum {
O_ICMPV6_TYPE = 0,
};
struct icmpv6_names {
const char *name;
uint8_t type;
uint8_t code_min, code_max;
};
static const struct icmpv6_names icmpv6_codes[] = {
static const struct xt_icmp_names icmpv6_codes[] = {
{ "destination-unreachable", 1, 0, 0xFF },
{ "no-route", 1, 0, 0 },
{ "communication-prohibited", 1, 1, 1 },
......@@ -58,34 +54,14 @@ static const struct icmpv6_names icmpv6_codes[] = {
};
static void
print_icmpv6types(void)
{
unsigned int i;
printf("Valid ICMPv6 Types:");
for (i = 0; i < ARRAY_SIZE(icmpv6_codes); ++i) {
if (i && icmpv6_codes[i].type == icmpv6_codes[i-1].type) {
if (icmpv6_codes[i].code_min == icmpv6_codes[i-1].code_min
&& (icmpv6_codes[i].code_max
== icmpv6_codes[i-1].code_max))
printf(" (%s)", icmpv6_codes[i].name);
else
printf("\n %s", icmpv6_codes[i].name);
}
else
printf("\n%s", icmpv6_codes[i].name);
}
printf("\n");
}
static void icmp6_help(void)
{
printf(
"icmpv6 match options:\n"
"[!] --icmpv6-type typename match icmpv6 type\n"
" (or numeric type or type/code)\n");
print_icmpv6types();
printf("Valid ICMPv6 Types:");
xt_print_icmp_types(icmpv6_codes, ARRAY_SIZE(icmpv6_codes));
}
static const struct xt_option_entry icmp6_opts[] = {
......@@ -282,8 +258,6 @@ static int icmp6_xlate(struct xt_xlate *xl,
if (!type_xlate_print(xl, info->type, info->code[0], info->code[1]))
return 0;
xt_xlate_add(xl, " ");
return 1;
}
......
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