Commit 615f9fca authored by Arturo Borrero Gonzalez's avatar Arturo Borrero Gonzalez
Browse files

Imported Upstream version 1.6.0

parent 7e95a8db
/* ebt_ip
*
* Authors:
* Bart De Schuymer <bdschuym@pandora.be>
*
* Changes:
* added ip-sport and ip-dport; parsing of port arguments is
* based on code from iptables-1.2.7a
* Innominate Security Technologies AG <mhopf@innominate.com>
* September, 2002
*
* Adapted by Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>
* to use libxtables for ebtables-compat in 2015.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <netdb.h>
#include <xtables.h>
#include <linux/netfilter_bridge/ebt_ip.h>
#define IP_SOURCE '1'
#define IP_DEST '2'
#define IP_EBT_TOS '3' /* include/bits/in.h seems to already define IP_TOS */
#define IP_PROTO '4'
#define IP_SPORT '5'
#define IP_DPORT '6'
static const struct option brip_opts[] = {
{ .name = "ip-source", .has_arg = true, .val = IP_SOURCE },
{ .name = "ip-src", .has_arg = true, .val = IP_SOURCE },
{ .name = "ip-destination", .has_arg = true, .val = IP_DEST },
{ .name = "ip-dst", .has_arg = true, .val = IP_DEST },
{ .name = "ip-tos", .has_arg = true, .val = IP_EBT_TOS },
{ .name = "ip-protocol", .has_arg = true, .val = IP_PROTO },
{ .name = "ip-proto", .has_arg = true, .val = IP_PROTO },
{ .name = "ip-source-port", .has_arg = true, .val = IP_SPORT },
{ .name = "ip-sport", .has_arg = true, .val = IP_SPORT },
{ .name = "ip-destination-port",.has_arg = true, .val = IP_DPORT },
{ .name = "ip-dport", .has_arg = true, .val = IP_DPORT },
XT_GETOPT_TABLEEND,
};
static void brip_print_help(void)
{
printf(
"ip options:\n"
"--ip-src [!] address[/mask]: ip source specification\n"
"--ip-dst [!] address[/mask]: ip destination specification\n"
"--ip-tos [!] tos : ip tos specification\n"
"--ip-proto [!] protocol : ip protocol specification\n"
"--ip-sport [!] port[:port] : tcp/udp source port or port range\n"
"--ip-dport [!] port[:port] : tcp/udp destination port or port range\n");
}
static void brip_init(struct xt_entry_match *match)
{
struct ebt_ip_info *info = (struct ebt_ip_info *)match->data;
info->invflags = 0;
info->bitmask = 0;
}
static void
parse_port_range(const char *protocol, const char *portstring, uint16_t *ports)
{
char *buffer;
char *cp;
buffer = strdup(portstring);
if ((cp = strchr(buffer, ':')) == NULL)
ports[0] = ports[1] = xtables_parse_port(buffer, NULL);
else {
*cp = '\0';
cp++;
ports[0] = buffer[0] ? xtables_parse_port(buffer, NULL) : 0;
ports[1] = cp[0] ? xtables_parse_port(cp, NULL) : 0xFFFF;
if (ports[0] > ports[1])
xtables_error(PARAMETER_PROBLEM,
"invalid portrange (min > max)");
}
free(buffer);
}
/* original code from ebtables: useful_functions.c */
static int undot_ip(char *ip, unsigned char *ip2)
{
char *p, *q, *end;
long int onebyte;
int i;
char buf[20];
strncpy(buf, ip, sizeof(buf) - 1);
p = buf;
for (i = 0; i < 3; i++) {
if ((q = strchr(p, '.')) == NULL)
return -1;
*q = '\0';
onebyte = strtol(p, &end, 10);
if (*end != '\0' || onebyte > 255 || onebyte < 0)
return -1;
ip2[i] = (unsigned char)onebyte;
p = q + 1;
}
onebyte = strtol(p, &end, 10);
if (*end != '\0' || onebyte > 255 || onebyte < 0)
return -1;
ip2[3] = (unsigned char)onebyte;
return 0;
}
static int ip_mask(char *mask, unsigned char *mask2)
{
char *end;
long int bits;
uint32_t mask22;
if (undot_ip(mask, mask2)) {
/* not the /a.b.c.e format, maybe the /x format */
bits = strtol(mask, &end, 10);
if (*end != '\0' || bits > 32 || bits < 0)
return -1;
if (bits != 0) {
mask22 = htonl(0xFFFFFFFF << (32 - bits));
memcpy(mask2, &mask22, 4);
} else {
mask22 = 0xFFFFFFFF;
memcpy(mask2, &mask22, 4);
}
}
return 0;
}
static void ebt_parse_ip_address(char *address, uint32_t *addr, uint32_t *msk)
{
char *p;
/* first the mask */
if ((p = strrchr(address, '/')) != NULL) {
*p = '\0';
if (ip_mask(p + 1, (unsigned char *)msk)) {
xtables_error(PARAMETER_PROBLEM,
"Problem with the IP mask '%s'", p + 1);
return;
}
} else
*msk = 0xFFFFFFFF;
if (undot_ip(address, (unsigned char *)addr)) {
xtables_error(PARAMETER_PROBLEM,
"Problem with the IP address '%s'", address);
return;
}
*addr = *addr & *msk;
}
static int
brip_parse(int c, char **argv, int invert, unsigned int *flags,
const void *entry, struct xt_entry_match **match)
{
struct ebt_ip_info *info = (struct ebt_ip_info *)(*match)->data;
switch (c) {
case IP_SOURCE:
if (invert)
info->invflags |= EBT_IP_SOURCE;
ebt_parse_ip_address(optarg, &info->saddr, &info->smsk);
info->bitmask |= EBT_IP_SOURCE;
break;
case IP_DEST:
if (invert)
info->invflags |= EBT_IP_DEST;
ebt_parse_ip_address(optarg, &info->daddr, &info->dmsk);
info->bitmask |= EBT_IP_DEST;
break;
case IP_SPORT:
if (invert)
info->invflags |= EBT_IP_SPORT;
parse_port_range(NULL, optarg, info->sport);
info->bitmask |= EBT_IP_SPORT;
break;
case IP_DPORT:
if (invert)
info->invflags |= EBT_IP_DPORT;
parse_port_range(NULL, optarg, info->dport);
info->bitmask |= EBT_IP_DPORT;
break;
case IP_EBT_TOS:
if (invert)
info->invflags |= EBT_IP_TOS;
if (!xtables_strtoul(optarg, NULL, (uintmax_t *)&info->tos,
0, 255))
xtables_error(PARAMETER_PROBLEM,
"Problem with specified IP tos");
info->bitmask |= EBT_IP_TOS;
break;
case IP_PROTO:
if (invert)
info->invflags |= EBT_IP_PROTO;
info->protocol = xtables_parse_protocol(optarg);
if (info->protocol == -1)
xtables_error(PARAMETER_PROBLEM,
"Unknown specified IP protocol - %s",
optarg);
info->bitmask |= EBT_IP_PROTO;
break;
default:
return 0;
}
*flags |= info->bitmask;
return 1;
}
static void brip_final_check(unsigned int flags)
{
if (!flags)
xtables_error(PARAMETER_PROBLEM,
"You must specify proper arguments");
}
static void print_port_range(uint16_t *ports)
{
if (ports[0] == ports[1])
printf("%d ", ports[0]);
else
printf("%d:%d ", ports[0], ports[1]);
}
static void brip_print(const void *ip, const struct xt_entry_match *match,
int numeric)
{
struct ebt_ip_info *info = (struct ebt_ip_info *)match->data;
struct in_addr *addrp, *maskp;
if (info->bitmask & EBT_IP_SOURCE) {
printf("--ip-src ");
if (info->invflags & EBT_IP_SOURCE)
printf("! ");
addrp = (struct in_addr *)&info->saddr;
maskp = (struct in_addr *)&info->smsk;
printf("%s%s ", xtables_ipaddr_to_numeric(addrp),
xtables_ipmask_to_numeric(maskp));
}
if (info->bitmask & EBT_IP_DEST) {
printf("--ip-dst ");
if (info->invflags & EBT_IP_DEST)
printf("! ");
addrp = (struct in_addr *)&info->daddr;
maskp = (struct in_addr *)&info->dmsk;
printf("%s%s ", xtables_ipaddr_to_numeric(addrp),
xtables_ipmask_to_numeric(maskp));
}
if (info->bitmask & EBT_IP_TOS) {
printf("--ip-tos ");
if (info->invflags & EBT_IP_TOS)
printf("! ");
printf("0x%02X ", info->tos);
}
if (info->bitmask & EBT_IP_PROTO) {
struct protoent *pe;
printf("--ip-proto ");
if (info->invflags & EBT_IP_PROTO)
printf("! ");
pe = getprotobynumber(info->protocol);
if (pe == NULL) {
printf("%d ", info->protocol);
} else {
printf("%s ", pe->p_name);
}
}
if (info->bitmask & EBT_IP_SPORT) {
printf("--ip-sport ");
if (info->invflags & EBT_IP_SPORT)
printf("! ");
print_port_range(info->sport);
}
if (info->bitmask & EBT_IP_DPORT) {
printf("--ip-dport ");
if (info->invflags & EBT_IP_DPORT)
printf("! ");
print_port_range(info->dport);
}
}
static struct xtables_match brip_match = {
.name = "ip",
.revision = 0,
.version = XTABLES_VERSION,
.family = NFPROTO_BRIDGE,
.size = XT_ALIGN(sizeof(struct ebt_ip_info)),
.userspacesize = XT_ALIGN(sizeof(struct ebt_ip_info)),
.init = brip_init,
.help = brip_print_help,
.parse = brip_parse,
.final_check = brip_final_check,
.print = brip_print,
.extra_opts = brip_opts,
};
void _init(void)
{
xtables_register_match(&brip_match);
}
/* ebt_limit
*
* Authors:
* Tom Marshall <tommy@home.tig-grr.com>
*
* Mostly copied from iptables' limit match.
*
* September, 2003
*
* Translated to use libxtables for ebtables-compat in 2015 by
* Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <errno.h>
#include <xtables.h>
#include <linux/netfilter_bridge/ebt_limit.h>
#include "iptables/nft.h"
#include "iptables/nft-bridge.h"
#define EBT_LIMIT_AVG "3/hour"
#define EBT_LIMIT_BURST 5
#define FLAG_LIMIT 0x01
#define FLAG_LIMIT_BURST 0x02
#define ARG_LIMIT '1'
#define ARG_LIMIT_BURST '2'
static struct option brlimit_opts[] =
{
{ .name = "limit", .has_arg = true, .val = ARG_LIMIT },
{ .name = "limit-burst",.has_arg = true, .val = ARG_LIMIT_BURST },
XT_GETOPT_TABLEEND,
};
static void brlimit_print_help(void)
{
printf(
"limit options:\n"
"--limit avg : max average match rate: default "EBT_LIMIT_AVG"\n"
" [Packets per second unless followed by \n"
" /sec /minute /hour /day postfixes]\n"
"--limit-burst number : number to match in a burst, -1 < number < 10001,\n"
" default %u\n", EBT_LIMIT_BURST);
}
static int parse_rate(const char *rate, uint32_t *val)
{
const char *delim;
uint32_t r;
uint32_t mult = 1; /* Seconds by default. */
delim = strchr(rate, '/');
if (delim) {
if (strlen(delim+1) == 0)
return 0;
if (strncasecmp(delim+1, "second", strlen(delim+1)) == 0)
mult = 1;
else if (strncasecmp(delim+1, "minute", strlen(delim+1)) == 0)
mult = 60;
else if (strncasecmp(delim+1, "hour", strlen(delim+1)) == 0)
mult = 60*60;
else if (strncasecmp(delim+1, "day", strlen(delim+1)) == 0)
mult = 24*60*60;
else
return 0;
}
r = atoi(rate);
if (!r)
return 0;
/* This would get mapped to infinite (1/day is minimum they
can specify, so we're ok at that end). */
if (r / mult > EBT_LIMIT_SCALE)
return 0;
*val = EBT_LIMIT_SCALE * mult / r;
return 1;
}
static void brlimit_init(struct xt_entry_match *match)
{
struct ebt_limit_info *r = (struct ebt_limit_info *)match->data;
parse_rate(EBT_LIMIT_AVG, &r->avg);
r->burst = EBT_LIMIT_BURST;
}
static int brlimit_parse(int c, char **argv, int invert, unsigned int *flags,
const void *entry, struct xt_entry_match **match)
{
struct ebt_limit_info *r = (struct ebt_limit_info *)(*match)->data;
uintmax_t num;
switch (c) {
case ARG_LIMIT:
EBT_CHECK_OPTION(flags, FLAG_LIMIT);
if (invert)
xtables_error(PARAMETER_PROBLEM,
"Unexpected `!' after --limit");
if (!parse_rate(optarg, &r->avg))
xtables_error(PARAMETER_PROBLEM,
"bad rate `%s'", optarg);
break;
case ARG_LIMIT_BURST:
EBT_CHECK_OPTION(flags, FLAG_LIMIT_BURST);
if (invert)
xtables_error(PARAMETER_PROBLEM,
"Unexpected `!' after --limit-burst");
if (!xtables_strtoul(optarg, NULL, &num, 0, 10000))
xtables_error(PARAMETER_PROBLEM,
"bad --limit-burst `%s'", optarg);
r->burst = num;
break;
default:
return 0;
}
return 1;
}
struct rates
{
const char *name;
uint32_t mult;
};
static struct rates g_rates[] =
{
{ "day", EBT_LIMIT_SCALE*24*60*60 },
{ "hour", EBT_LIMIT_SCALE*60*60 },
{ "min", EBT_LIMIT_SCALE*60 },
{ "sec", EBT_LIMIT_SCALE }
};
static void print_rate(uint32_t period)
{
unsigned int i;
for (i = 1; i < sizeof(g_rates)/sizeof(struct rates); i++)
if (period > g_rates[i].mult ||
g_rates[i].mult/period < g_rates[i].mult%period)
break;
printf("%u/%s ", g_rates[i-1].mult / period, g_rates[i-1].name);
}
static void brlimit_print(const void *ip, const struct xt_entry_match *match,
int numeric)
{
struct ebt_limit_info *r = (struct ebt_limit_info *)match->data;
printf("--limit ");
print_rate(r->avg);
printf("--limit-burst %u ", r->burst);
}
static struct xtables_match brlimit_match = {
.name = "limit",
.revision = 0,
.version = XTABLES_VERSION,
.family = NFPROTO_BRIDGE,
.size = XT_ALIGN(sizeof(struct ebt_limit_info)),
.userspacesize = offsetof(struct ebt_limit_info, prev),
.init = brlimit_init,
.help = brlimit_print_help,
.parse = brlimit_parse,
.print = brlimit_print,
.extra_opts = brlimit_opts,
};
void _init(void)
{
xtables_register_match(&brlimit_match);
}
/*
* Bart De Schuymer <bdschuym@pandora.be>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Giuseppe Longo <giuseppelng@gmail.com> adapted the original code to the
* xtables-compat environment in 2015.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <syslog.h>
#include <string.h>
#include <getopt.h>
#include <xtables.h>
#include <linux/netfilter_bridge/ebt_log.h>
#define LOG_DEFAULT_LEVEL LOG_INFO
#define LOG_PREFIX '1'
#define LOG_LEVEL '2'
#define LOG_ARP '3'
#define LOG_IP '4'
#define LOG_LOG '5'
#define LOG_IP6 '6'
typedef struct _code {
char *c_name;
int c_val;
} CODE;
static CODE eight_priority[] = {
{ "emerg", LOG_EMERG },
{ "alert", LOG_ALERT },
{ "crit", LOG_CRIT },
{ "error", LOG_ERR },
{ "warning", LOG_WARNING },
{ "notice", LOG_NOTICE },
{ "info", LOG_INFO },
{ "debug", LOG_DEBUG }
};
static int name_to_loglevel(const char *arg)
{
int i;
for (i = 0; i < 8; i++)
if (!strcmp(arg, eight_priority[i].c_name))
return eight_priority[i].c_val;
/* return bad loglevel */
return 9;
}
static const struct option brlog_opts[] = {
{ .name = "log-prefix", .has_arg = true, .val = LOG_PREFIX },
{ .name = "log-level", .has_arg = true, .val = LOG_LEVEL },
{ .name = "log-arp", .has_arg = false, .val = LOG_ARP },
{ .name = "log-ip", .has_arg = false, .val = LOG_IP },
{ .name = "log", .has_arg = false, .val = LOG_LOG },
{ .name = "log-ip6", .has_arg = false, .val = LOG_IP6 },
XT_GETOPT_TABLEEND,
};
static void brlog_help(void)
{
int i;
printf(
"log options:\n"
"--log : use this if you're not specifying anything\n"
"--log-level level : level = [1-8] or a string\n"
"--log-prefix prefix : max. %d chars.\n"
"--log-ip : put ip info. in the log for ip packets\n"
"--log-arp : put (r)arp info. in the log for (r)arp packets\n"
"--log-ip6 : put ip6 info. in the log for ip6 packets\n"
, EBT_LOG_PREFIX_SIZE - 1);
for (i = 0; i < 8; i++)
printf("%d = %s\n", eight_priority[i].c_val,
eight_priority[i].c_name);
}
static void brlog_init(struct xt_entry_target *t)
{
struct ebt_log_info *loginfo = (struct ebt_log_info *)t->data;
loginfo->bitmask = 0;
loginfo->prefix[0] = '\0';
loginfo->loglevel = LOG_NOTICE;
}
static int brlog_parse(int c, char **argv, int invert, unsigned int *flags,
const void *entry, struct xt_entry_target **target)
{
struct ebt_log_info *loginfo = (struct ebt_log_info *)(*target)->data;
long int i;
char *end;
switch (c) {
case LOG_PREFIX:
if (invert)
xtables_error(PARAMETER_PROBLEM,
"Unexpected `!` after --log-prefix");
if (strlen(optarg) > sizeof(loginfo->prefix) - 1)
xtables_error(PARAMETER_PROBLEM,
"Prefix too long");
if (strchr(optarg, '\"'))
xtables_error(PARAMETER_PROBLEM,
"Use of \\\" is not allowed"
" in the prefix");
strcpy((char *)loginfo->prefix, (char *)optarg);
break;
case LOG_LEVEL:
i = strtol(optarg, &end, 16);
if (*end != '\0' || i < 0 || i > 7)
loginfo->loglevel = name_to_loglevel(optarg);
else
loginfo->loglevel = i;
if (loginfo->loglevel == 9)
xtables_error(PARAMETER_PROBLEM,
"Problem with the log-level");
break;
case LOG_IP:
if (invert)
xtables_error(PARAMETER_PROBLEM,
"Unexpected `!' after --log-ip");
loginfo->bitmask |= EBT_LOG_IP;
break;
case LOG_ARP:
if (invert)
xtables_error(PARAMETER_PROBLEM,
"Unexpected `!' after --log-arp");
loginfo->bitmask |= EBT_LOG_ARP;
case LOG_LOG:
if (invert)
xtables_error(PARAMETER_PROBLEM,
"Unexpected `!' after --log");
break;
case LOG_IP6:
if (invert)
xtables_error(PARAMETER_PROBLEM,
"Unexpected `!' after --log-ip6");
loginfo->bitmask |= EBT_LOG_IP6;
break;
default:
return 0;
}
*flags |= loginfo->bitmask;
return 1;
}
static void brlog_final_check(unsigned int flags)
{
}
static void brlog_print(const void *ip, const struct xt_entry_target *target,
int numeric)
{
struct ebt_log_info *loginfo = (struct ebt_log_info *)target->data;
printf("--log-level %s --log-prefix \"%s\"",
eight_priority[loginfo->loglevel].c_name,
loginfo->prefix);
if (loginfo->bitmask & EBT_LOG_IP)
printf(" --log-ip");
if (loginfo->bitmask & EBT_LOG_ARP)
printf(" --log-arp");
if (loginfo->bitmask & EBT_LOG_IP6)
printf(" --log-ip6");
printf(" ");
}
static struct xtables_target brlog_target = {
.name = "log",
.revision = 0,
.version = XTABLES_VERSION,
.family = NFPROTO_BRIDGE,
.size = XT_ALIGN(sizeof(struct ebt_log_info)),
.userspacesize = XT_ALIGN(sizeof(struct ebt_log_info)),
.init = brlog_init,
.help = brlog_help,
.parse = brlog_parse,
.final_check = brlog_final_check,
.print = brlog_print,
.extra_opts = brlog_opts,
};
void _init(void)
{
xtables_register_target(&brlog_target);
}
/* ebt_mark
*
* Authors:
* Bart De Schuymer <bdschuym@pandora.be>
*
* July, 2002, September 2006
*
* Adapted by Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>
* to use libxtables for ebtables-compat in 2015.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <xtables.h>
#include <linux/netfilter_bridge/ebt_mark_t.h>
#include "iptables/nft.h"
#include "iptables/nft-bridge.h"
static int mark_supplied;
#define MARK_TARGET '1'
#define MARK_SETMARK '2'
#define MARK_ORMARK '3'
#define MARK_ANDMARK '4'
#define MARK_XORMARK '5'
static struct option brmark_opts[] = {
{ .name = "mark-target",.has_arg = true, .val = MARK_TARGET },
/* an oldtime messup, we should have always used the scheme
* <extension-name>-<option> */
{ .name = "set-mark", .has_arg = true, .val = MARK_SETMARK },
{ .name = "mark-set", .has_arg = true, .val = MARK_SETMARK },
{ .name = "mark-or", .has_arg = true, .val = MARK_ORMARK },
{ .name = "mark-and", .has_arg = true, .val = MARK_ANDMARK },
{ .name = "mark-xor", .has_arg = true, .val = MARK_XORMARK },
XT_GETOPT_TABLEEND,
};
static void brmark_print_help(void)
{
printf(
"mark target options:\n"
" --mark-set value : Set nfmark value\n"
" --mark-or value : Or nfmark with value (nfmark |= value)\n"
" --mark-and value : And nfmark with value (nfmark &= value)\n"
" --mark-xor value : Xor nfmark with value (nfmark ^= value)\n"
" --mark-target target : ACCEPT, DROP, RETURN or CONTINUE\n");
}
static void brmark_init(struct xt_entry_target *target)
{
struct ebt_mark_t_info *info = (struct ebt_mark_t_info *)target->data;
info->target = EBT_ACCEPT;
info->mark = 0;
mark_supplied = 0;
}
#define OPT_MARK_TARGET 0x01
#define OPT_MARK_SETMARK 0x02
#define OPT_MARK_ORMARK 0x04
#define OPT_MARK_ANDMARK 0x08
#define OPT_MARK_XORMARK 0x10
static int
brmark_parse(int c, char **argv, int invert, unsigned int *flags,
const void *entry, struct xt_entry_target **target)
{
struct ebt_mark_t_info *info = (struct ebt_mark_t_info *)
(*target)->data;
char *end;
uint32_t mask;
switch (c) {
case MARK_TARGET:
{ unsigned int tmp;
EBT_CHECK_OPTION(flags, OPT_MARK_TARGET);
if (ebt_fill_target(optarg, &tmp))
xtables_error(PARAMETER_PROBLEM,
"Illegal --mark-target target");
/* the 4 lsb are left to designate the target */
info->target = (info->target & ~EBT_VERDICT_BITS) |
(tmp & EBT_VERDICT_BITS);
}
return 1;
case MARK_SETMARK:
EBT_CHECK_OPTION(flags, OPT_MARK_SETMARK);
mask = (OPT_MARK_ORMARK|OPT_MARK_ANDMARK|OPT_MARK_XORMARK);
if (*flags & mask)
xtables_error(PARAMETER_PROBLEM,
"--mark-set cannot be used together with"
" specific --mark option");
info->target = (info->target & EBT_VERDICT_BITS) |
MARK_SET_VALUE;
break;
case MARK_ORMARK:
EBT_CHECK_OPTION(flags, OPT_MARK_ORMARK);
mask = (OPT_MARK_SETMARK|OPT_MARK_ANDMARK|OPT_MARK_XORMARK);
if (*flags & mask)
xtables_error(PARAMETER_PROBLEM,
"--mark-or cannot be used together with"
" specific --mark option");
info->target = (info->target & EBT_VERDICT_BITS) |
MARK_OR_VALUE;
break;
case MARK_ANDMARK:
EBT_CHECK_OPTION(flags, OPT_MARK_ANDMARK);
mask = (OPT_MARK_SETMARK|OPT_MARK_ORMARK|OPT_MARK_XORMARK);
if (*flags & mask)
xtables_error(PARAMETER_PROBLEM,
"--mark-and cannot be used together with"
" specific --mark option");
info->target = (info->target & EBT_VERDICT_BITS) |
MARK_AND_VALUE;
break;
case MARK_XORMARK:
EBT_CHECK_OPTION(flags, OPT_MARK_XORMARK);
mask = (OPT_MARK_SETMARK|OPT_MARK_ANDMARK|OPT_MARK_ORMARK);
if (*flags & mask)
xtables_error(PARAMETER_PROBLEM,
"--mark-xor cannot be used together with"
" specific --mark option");
info->target = (info->target & EBT_VERDICT_BITS) |
MARK_XOR_VALUE;
break;
default:
return 0;
}
/* mutual code */
info->mark = strtoul(optarg, &end, 0);
if (*end != '\0' || end == optarg)
xtables_error(PARAMETER_PROBLEM, "Bad MARK value '%s'",
optarg);
mark_supplied = 1;
return 1;
}
static void brmark_print(const void *ip, const struct xt_entry_target *target,
int numeric)
{
struct ebt_mark_t_info *info = (struct ebt_mark_t_info *)target->data;
int tmp;
tmp = info->target & ~EBT_VERDICT_BITS;
if (tmp == MARK_SET_VALUE)
printf("--mark-set");
else if (tmp == MARK_OR_VALUE)
printf("--mark-or");
else if (tmp == MARK_XOR_VALUE)
printf("--mark-xor");
else if (tmp == MARK_AND_VALUE)
printf("--mark-and");
else
xtables_error(PARAMETER_PROBLEM, "Unknown mark action");
printf(" 0x%lx", info->mark);
tmp = info->target | ~EBT_VERDICT_BITS;
printf(" --mark-target %s", ebt_target_name(tmp));
}
static void brmark_final_check(unsigned int flags)
{
if (mark_supplied == 0)
xtables_error(PARAMETER_PROBLEM, "No mark value supplied");
if (!flags)
xtables_error(PARAMETER_PROBLEM,
"You must specify some option");
}
static struct xtables_target brmark_target = {
.name = "mark",
.revision = 0,
.version = XTABLES_VERSION,
.family = NFPROTO_BRIDGE,
.size = XT_ALIGN(sizeof(struct ebt_mark_t_info)),
.userspacesize = XT_ALIGN(sizeof(struct ebt_mark_t_info)),
.help = brmark_print_help,
.init = brmark_init,
.parse = brmark_parse,
.final_check = brmark_final_check,
.print = brmark_print,
.extra_opts = brmark_opts,
};
void _init(void)
{
xtables_register_target(&brmark_target);
}
/* ebt_mark_m
*
* Authors:
* Bart De Schuymer <bdschuym@pandora.be>
*
* July, 2002
*
* Adapted by Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>
* to use libxtables for ebtables-compat in 2015.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <xtables.h>
#include <linux/netfilter_bridge/ebt_mark_m.h>
#define MARK '1'
static struct option brmark_m_opts[] = {
{ .name = "mark", .has_arg = true, .val = MARK },
XT_GETOPT_TABLEEND,
};
static void brmark_m_print_help(void)
{
printf(
"mark option:\n"
"--mark [!] [value][/mask]: Match nfmask value (see man page)\n");
}
static void brmark_m_init(struct xt_entry_match *match)
{
struct ebt_mark_m_info *info = (struct ebt_mark_m_info *)match->data;
info->mark = 0;
info->mask = 0;
info->invert = 0;
info->bitmask = 0;
}
#define OPT_MARK 0x01
static int
brmark_m_parse(int c, char **argv, int invert, unsigned int *flags,
const void *entry, struct xt_entry_match **match)
{
struct ebt_mark_m_info *info = (struct ebt_mark_m_info *)
(*match)->data;
char *end;
switch (c) {
case MARK:
if (invert)
info->invert = 1;
info->mark = strtoul(optarg, &end, 0);
info->bitmask = EBT_MARK_AND;
if (*end == '/') {
if (end == optarg)
info->bitmask = EBT_MARK_OR;
info->mask = strtoul(end+1, &end, 0);
} else {
info->mask = 0xffffffff;
}
if (*end != '\0' || end == optarg)
xtables_error(PARAMETER_PROBLEM, "Bad mark value '%s'",
optarg);
break;
default:
return 0;
}
*flags |= info->bitmask;
return 1;
}
static void brmark_m_final_check(unsigned int flags)
{
if (!flags)
xtables_error(PARAMETER_PROBLEM,
"You must specify proper arguments");
}
static void brmark_m_print(const void *ip, const struct xt_entry_match *match,
int numeric)
{
struct ebt_mark_m_info *info = (struct ebt_mark_m_info *)match->data;
printf("--mark ");
if (info->invert)
printf("! ");
if (info->bitmask == EBT_MARK_OR)
printf("/0x%lx ", info->mask);
else if (info->mask != 0xffffffff)
printf("0x%lx/0x%lx ", info->mark, info->mask);
else
printf("0x%lx ", info->mark);
}
static struct xtables_match brmark_m_match = {
.name = "mark_m",
.revision = 0,
.version = XTABLES_VERSION,
.family = NFPROTO_BRIDGE,
.size = XT_ALIGN(sizeof(struct ebt_mark_m_info)),
.userspacesize = XT_ALIGN(sizeof(struct ebt_mark_m_info)),
.init = brmark_m_init,
.help = brmark_m_print_help,
.parse = brmark_m_parse,
.final_check = brmark_m_final_check,
.print = brmark_m_print,
.extra_opts = brmark_m_opts,
};
void _init(void)
{
xtables_register_match(&brmark_m_match);
}
/* ebt_nflog
*
* Authors:
* Peter Warasin <peter@endian.com>
*
* February, 2008
*
* Based on:
* ebt_ulog.c, (C) 2004, Bart De Schuymer <bdschuym@pandora.be>
* libxt_NFLOG.c
*
* Adapted to libxtables for ebtables-compat in 2015 by
* Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <xtables.h>
#include "iptables/nft.h"
#include "iptables/nft-bridge.h"
#include <linux/netfilter_bridge/ebt_nflog.h>
enum {
NFLOG_GROUP = 0x1,
NFLOG_PREFIX = 0x2,
NFLOG_RANGE = 0x4,
NFLOG_THRESHOLD = 0x8,
NFLOG_NFLOG = 0x16,
};
static struct option brnflog_opts[] = {
{ .name = "nflog-group", .has_arg = true, .val = NFLOG_GROUP},
{ .name = "nflog-prefix", .has_arg = true, .val = NFLOG_PREFIX},
{ .name = "nflog-range", .has_arg = true, .val = NFLOG_RANGE},
{ .name = "nflog-threshold", .has_arg = true, .val = NFLOG_THRESHOLD},
{ .name = "nflog", .has_arg = false, .val = NFLOG_NFLOG},
XT_GETOPT_TABLEEND,
};
static void brnflog_help(void)
{
printf("nflog options:\n"
"--nflog : use the default nflog parameters\n"
"--nflog-prefix prefix : Prefix string for log message\n"
"--nflog-group group : NETLINK group used for logging\n"
"--nflog-range range : Number of byte to copy\n"
"--nflog-threshold : Message threshold of"
"in-kernel queue\n");
}
static void brnflog_init(struct xt_entry_target *t)
{
struct ebt_nflog_info *info = (struct ebt_nflog_info *)t->data;
info->prefix[0] = '\0';
info->group = EBT_NFLOG_DEFAULT_GROUP;
info->threshold = EBT_NFLOG_DEFAULT_THRESHOLD;
}
static int brnflog_parse(int c, char **argv, int invert, unsigned int *flags,
const void *entry, struct xt_entry_target **target)
{
struct ebt_nflog_info *info = (struct ebt_nflog_info *)(*target)->data;
unsigned int i;
if (invert)
xtables_error(PARAMETER_PROBLEM,
"The use of '!' makes no sense for the"
" nflog watcher");
switch (c) {
case NFLOG_PREFIX:
EBT_CHECK_OPTION(flags, NFLOG_PREFIX);
if (strlen(optarg) > EBT_NFLOG_PREFIX_SIZE - 1)
xtables_error(PARAMETER_PROBLEM,
"Prefix too long for nflog-prefix");
strncpy(info->prefix, optarg, EBT_NFLOG_PREFIX_SIZE);
break;
case NFLOG_GROUP:
EBT_CHECK_OPTION(flags, NFLOG_GROUP);
if (!xtables_strtoui(optarg, NULL, &i, 1, UINT32_MAX))
xtables_error(PARAMETER_PROBLEM,
"--nflog-group must be a number!");
info->group = i;
break;
case NFLOG_RANGE:
EBT_CHECK_OPTION(flags, NFLOG_RANGE);
if (!xtables_strtoui(optarg, NULL, &i, 1, UINT32_MAX))
xtables_error(PARAMETER_PROBLEM,
"--nflog-range must be a number!");
info->len = i;
break;
case NFLOG_THRESHOLD:
EBT_CHECK_OPTION(flags, NFLOG_THRESHOLD);
if (!xtables_strtoui(optarg, NULL, &i, 1, UINT32_MAX))
xtables_error(PARAMETER_PROBLEM,
"--nflog-threshold must be a number!");
info->threshold = i;
break;
case NFLOG_NFLOG:
EBT_CHECK_OPTION(flags, NFLOG_NFLOG);
break;
default:
return 0;
}
return 1;
}
static void
brnflog_print(const void *ip, const struct xt_entry_target *target,
int numeric)
{
struct ebt_nflog_info *info = (struct ebt_nflog_info *)target->data;
if (info->prefix[0] != '\0')
printf("--nflog-prefix \"%s\" ", info->prefix);
if (info->group)
printf("--nflog-group %d ", info->group);
if (info->len)
printf("--nflog-range %d ", info->len);
if (info->threshold != EBT_NFLOG_DEFAULT_THRESHOLD)
printf("--nflog-threshold %d ", info->threshold);
}
static struct xtables_target brnflog_watcher = {
.name = "nflog",
.revision = 0,
.version = XTABLES_VERSION,
.family = NFPROTO_BRIDGE,
.size = XT_ALIGN(sizeof(struct ebt_nflog_info)),
.userspacesize = XT_ALIGN(sizeof(struct ebt_nflog_info)),
.init = brnflog_init,
.help = brnflog_help,
.parse = brnflog_parse,
.print = brnflog_print,
.extra_opts = brnflog_opts,
};
void _init(void)
{
xtables_register_target(&brnflog_watcher);
}
...@@ -52,9 +52,9 @@ static void DNPT_print(const void *ip, const struct xt_entry_target *target, ...@@ -52,9 +52,9 @@ static void DNPT_print(const void *ip, const struct xt_entry_target *target,
{ {
const struct ip6t_npt_tginfo *npt = (const void *)target->data; const struct ip6t_npt_tginfo *npt = (const void *)target->data;
printf("src-pfx %s/%u ", xtables_ip6addr_to_numeric(&npt->src_pfx.in6), printf(" DNPT src-pfx %s/%u", xtables_ip6addr_to_numeric(&npt->src_pfx.in6),
npt->src_pfx_len); npt->src_pfx_len);
printf("dst-pfx %s/%u ", xtables_ip6addr_to_numeric(&npt->dst_pfx.in6), printf(" dst-pfx %s/%u", xtables_ip6addr_to_numeric(&npt->dst_pfx.in6),
npt->dst_pfx_len); npt->dst_pfx_len);
} }
...@@ -65,12 +65,12 @@ static void DNPT_save(const void *ip, const struct xt_entry_target *target) ...@@ -65,12 +65,12 @@ static void DNPT_save(const void *ip, const struct xt_entry_target *target)
if (memcmp(&info->src_pfx.in6, &zero_addr, sizeof(zero_addr)) != 0 || if (memcmp(&info->src_pfx.in6, &zero_addr, sizeof(zero_addr)) != 0 ||
info->src_pfx_len != 0) info->src_pfx_len != 0)
printf("--src-pfx %s/%u ", printf(" --src-pfx %s/%u",
xtables_ip6addr_to_numeric(&info->src_pfx.in6), xtables_ip6addr_to_numeric(&info->src_pfx.in6),
info->src_pfx_len); info->src_pfx_len);
if (memcmp(&info->dst_pfx.in6, &zero_addr, sizeof(zero_addr)) != 0 || if (memcmp(&info->dst_pfx.in6, &zero_addr, sizeof(zero_addr)) != 0 ||
info->dst_pfx_len != 0) info->dst_pfx_len != 0)
printf("--dst-pfx %s/%u ", printf(" --dst-pfx %s/%u",
xtables_ip6addr_to_numeric(&info->dst_pfx.in6), xtables_ip6addr_to_numeric(&info->dst_pfx.in6),
info->dst_pfx_len); info->dst_pfx_len);
} }
......
...@@ -35,7 +35,11 @@ static const struct reject_names reject_table[] = { ...@@ -35,7 +35,11 @@ static const struct reject_names reject_table[] = {
{"icmp6-port-unreachable", "port-unreach", {"icmp6-port-unreachable", "port-unreach",
IP6T_ICMP6_PORT_UNREACH, "ICMPv6 port unreachable"}, IP6T_ICMP6_PORT_UNREACH, "ICMPv6 port unreachable"},
{"tcp-reset", "tcp-reset", {"tcp-reset", "tcp-reset",
IP6T_TCP_RESET, "TCP RST packet"} 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"}
}; };
static void static void
......
...@@ -18,11 +18,13 @@ ...@@ -18,11 +18,13 @@
enum { enum {
O_TO_SRC = 0, O_TO_SRC = 0,
O_RANDOM, O_RANDOM,
O_RANDOM_FULLY,
O_PERSISTENT, O_PERSISTENT,
O_X_TO_SRC, O_X_TO_SRC,
F_TO_SRC = 1 << O_TO_SRC, F_TO_SRC = 1 << O_TO_SRC,
F_RANDOM = 1 << O_RANDOM, F_RANDOM = 1 << O_RANDOM,
F_X_TO_SRC = 1 << O_X_TO_SRC, F_RANDOM_FULLY = 1 << O_RANDOM_FULLY,
F_X_TO_SRC = 1 << O_X_TO_SRC,
}; };
static void SNAT_help(void) static void SNAT_help(void)
...@@ -31,13 +33,14 @@ static void SNAT_help(void) ...@@ -31,13 +33,14 @@ static void SNAT_help(void)
"SNAT target options:\n" "SNAT target options:\n"
" --to-source [<ipaddr>[-<ipaddr>]][:port[-port]]\n" " --to-source [<ipaddr>[-<ipaddr>]][:port[-port]]\n"
" Address to map source to.\n" " Address to map source to.\n"
"[--random] [--persistent]\n"); "[--random] [--random-fully] [--persistent]\n");
} }
static const struct xt_option_entry SNAT_opts[] = { static const struct xt_option_entry SNAT_opts[] = {
{.name = "to-source", .id = O_TO_SRC, .type = XTTYPE_STRING, {.name = "to-source", .id = O_TO_SRC, .type = XTTYPE_STRING,
.flags = XTOPT_MAND | XTOPT_MULTI}, .flags = XTOPT_MAND | XTOPT_MULTI},
{.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE}, {.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE},
{.name = "random-fully", .id = O_RANDOM_FULLY, .type = XTTYPE_NONE},
{.name = "persistent", .id = O_PERSISTENT, .type = XTTYPE_NONE}, {.name = "persistent", .id = O_PERSISTENT, .type = XTTYPE_NONE},
XTOPT_TABLEEND, XTOPT_TABLEEND,
}; };
...@@ -180,10 +183,13 @@ static void SNAT_parse(struct xt_option_call *cb) ...@@ -180,10 +183,13 @@ static void SNAT_parse(struct xt_option_call *cb)
static void SNAT_fcheck(struct xt_fcheck_call *cb) static void SNAT_fcheck(struct xt_fcheck_call *cb)
{ {
static const unsigned int f = F_TO_SRC | F_RANDOM; static const unsigned int f = F_TO_SRC | F_RANDOM;
static const unsigned int r = F_TO_SRC | F_RANDOM_FULLY;
struct nf_nat_range *range = cb->data; struct nf_nat_range *range = cb->data;
if ((cb->xflags & f) == f) if ((cb->xflags & f) == f)
range->flags |= NF_NAT_RANGE_PROTO_RANDOM; range->flags |= NF_NAT_RANGE_PROTO_RANDOM;
if ((cb->xflags & r) == r)
range->flags |= NF_NAT_RANGE_PROTO_RANDOM_FULLY;
} }
static void print_range(const struct nf_nat_range *range) static void print_range(const struct nf_nat_range *range)
...@@ -215,6 +221,8 @@ static void SNAT_print(const void *ip, const struct xt_entry_target *target, ...@@ -215,6 +221,8 @@ static void SNAT_print(const void *ip, const struct xt_entry_target *target,
print_range(range); print_range(range);
if (range->flags & NF_NAT_RANGE_PROTO_RANDOM) if (range->flags & NF_NAT_RANGE_PROTO_RANDOM)
printf(" random"); printf(" random");
if (range->flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY)
printf(" random-fully");
if (range->flags & NF_NAT_RANGE_PERSISTENT) if (range->flags & NF_NAT_RANGE_PERSISTENT)
printf(" persistent"); printf(" persistent");
} }
...@@ -227,6 +235,8 @@ static void SNAT_save(const void *ip, const struct xt_entry_target *target) ...@@ -227,6 +235,8 @@ static void SNAT_save(const void *ip, const struct xt_entry_target *target)
print_range(range); print_range(range);
if (range->flags & NF_NAT_RANGE_PROTO_RANDOM) if (range->flags & NF_NAT_RANGE_PROTO_RANDOM)
printf(" --random"); printf(" --random");
if (range->flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY)
printf(" --random-fully");
if (range->flags & NF_NAT_RANGE_PERSISTENT) if (range->flags & NF_NAT_RANGE_PERSISTENT)
printf(" --persistent"); printf(" --persistent");
} }
......
...@@ -52,9 +52,9 @@ static void SNPT_print(const void *ip, const struct xt_entry_target *target, ...@@ -52,9 +52,9 @@ static void SNPT_print(const void *ip, const struct xt_entry_target *target,
{ {
const struct ip6t_npt_tginfo *npt = (const void *)target->data; const struct ip6t_npt_tginfo *npt = (const void *)target->data;
printf("src-pfx %s/%u ", xtables_ip6addr_to_numeric(&npt->src_pfx.in6), printf(" SNPT src-pfx %s/%u", xtables_ip6addr_to_numeric(&npt->src_pfx.in6),
npt->src_pfx_len); npt->src_pfx_len);
printf("dst-pfx %s/%u ", xtables_ip6addr_to_numeric(&npt->dst_pfx.in6), printf(" dst-pfx %s/%u", xtables_ip6addr_to_numeric(&npt->dst_pfx.in6),
npt->dst_pfx_len); npt->dst_pfx_len);
} }
...@@ -65,12 +65,12 @@ static void SNPT_save(const void *ip, const struct xt_entry_target *target) ...@@ -65,12 +65,12 @@ static void SNPT_save(const void *ip, const struct xt_entry_target *target)
if (memcmp(&info->src_pfx.in6, &zero_addr, sizeof(zero_addr)) != 0 || if (memcmp(&info->src_pfx.in6, &zero_addr, sizeof(zero_addr)) != 0 ||
info->src_pfx_len != 0) info->src_pfx_len != 0)
printf("--src-pfx %s/%u ", printf(" --src-pfx %s/%u",
xtables_ip6addr_to_numeric(&info->src_pfx.in6), xtables_ip6addr_to_numeric(&info->src_pfx.in6),
info->src_pfx_len); info->src_pfx_len);
if (memcmp(&info->dst_pfx.in6, &zero_addr, sizeof(zero_addr)) != 0 || if (memcmp(&info->dst_pfx.in6, &zero_addr, sizeof(zero_addr)) != 0 ||
info->dst_pfx_len != 0) info->dst_pfx_len != 0)
printf("--dst-pfx %s/%u ", printf(" --dst-pfx %s/%u",
xtables_ip6addr_to_numeric(&info->dst_pfx.in6), xtables_ip6addr_to_numeric(&info->dst_pfx.in6),
info->dst_pfx_len); info->dst_pfx_len);
} }
......
...@@ -28,6 +28,14 @@ static const struct xt_option_entry ah_opts[] = { ...@@ -28,6 +28,14 @@ static const struct xt_option_entry ah_opts[] = {
}; };
#undef s #undef s
static void ah_init(struct xt_entry_match *m)
{
struct ip6t_ah *ahinfo = (void *)m->data;
/* Defaults for when no --ahspi is used at all */
ahinfo->spis[1] = ~0U;
}
static void ah_parse(struct xt_option_call *cb) static void ah_parse(struct xt_option_call *cb)
{ {
struct ip6t_ah *ahinfo = cb->data; struct ip6t_ah *ahinfo = cb->data;
...@@ -127,6 +135,7 @@ static struct xtables_match ah_mt6_reg = { ...@@ -127,6 +135,7 @@ static struct xtables_match ah_mt6_reg = {
.size = XT_ALIGN(sizeof(struct ip6t_ah)), .size = XT_ALIGN(sizeof(struct ip6t_ah)),
.userspacesize = XT_ALIGN(sizeof(struct ip6t_ah)), .userspacesize = XT_ALIGN(sizeof(struct ip6t_ah)),
.help = ah_help, .help = ah_help,
.init = ah_init,
.print = ah_print, .print = ah_print,
.save = ah_save, .save = ah_save,
.x6_parse = ah_parse, .x6_parse = ah_parse,
......
...@@ -112,6 +112,8 @@ static void dst_parse(struct xt_option_call *cb) ...@@ -112,6 +112,8 @@ static void dst_parse(struct xt_option_call *cb)
xtables_option_parse(cb); xtables_option_parse(cb);
switch (cb->entry->id) { switch (cb->entry->id) {
case O_DSTLEN: case O_DSTLEN:
if (cb->invert)
optinfo->invflags |= IP6T_OPTS_INV_LEN;
optinfo->flags |= IP6T_OPTS_LEN; optinfo->flags |= IP6T_OPTS_LEN;
break; break;
case O_DSTOPTS: case O_DSTOPTS:
......
...@@ -19,8 +19,11 @@ static const struct icmpv6_names icmpv6_codes[] = { ...@@ -19,8 +19,11 @@ static const struct icmpv6_names icmpv6_codes[] = {
{ "destination-unreachable", 1, 0, 0xFF }, { "destination-unreachable", 1, 0, 0xFF },
{ "no-route", 1, 0, 0 }, { "no-route", 1, 0, 0 },
{ "communication-prohibited", 1, 1, 1 }, { "communication-prohibited", 1, 1, 1 },
{ "beyond-scope", 1, 2, 2 },
{ "address-unreachable", 1, 3, 3 }, { "address-unreachable", 1, 3, 3 },
{ "port-unreachable", 1, 4, 4 }, { "port-unreachable", 1, 4, 4 },
{ "failed-policy", 1, 5, 5 },
{ "reject-route", 1, 6, 6 },
{ "packet-too-big", 2, 0, 0xFF }, { "packet-too-big", 2, 0, 0xFF },
......
...@@ -127,7 +127,7 @@ static void ipv6header_help(void) ...@@ -127,7 +127,7 @@ static void ipv6header_help(void)
printf( printf(
"ipv6header match options:\n" "ipv6header match options:\n"
"[!] --header headers Type of header to match, by name\n" "[!] --header headers Type of header to match, by name\n"
" names: hop,dst,route,frag,auth,esp,none,proto\n" " names: hop,dst,route,frag,auth,esp,none,prot\n"
" long names: hop-by-hop,ipv6-opts,ipv6-route,\n" " long names: hop-by-hop,ipv6-opts,ipv6-route,\n"
" ipv6-frag,ah,esp,ipv6-nonxt,protocol\n" " ipv6-frag,ah,esp,ipv6-nonxt,protocol\n"
" numbers: 0,60,43,44,51,50,59\n" " numbers: 0,60,43,44,51,50,59\n"
......
...@@ -31,7 +31,7 @@ Encapsulating Security Payload header ...@@ -31,7 +31,7 @@ Encapsulating Security Payload header
No Next header which matches 59 in the 'Next Header field' of IPv6 header or No Next header which matches 59 in the 'Next Header field' of IPv6 header or
any IPv6 extension headers any IPv6 extension headers
.TP .TP
\fBproto\fP \fBprot\fP
which matches any upper layer protocol header. A protocol name from which matches any upper layer protocol header. A protocol name from
/etc/protocols and numeric value also allowed. The number 255 is equivalent to /etc/protocols and numeric value also allowed. The number 255 is equivalent to
\fBproto\fP. \fBprot\fP.
...@@ -99,6 +99,13 @@ parse_addresses(const char *addrstr, struct in6_addr *addrp) ...@@ -99,6 +99,13 @@ parse_addresses(const char *addrstr, struct in6_addr *addrp)
return i; return i;
} }
static void rt_init(struct xt_entry_match *m)
{
struct ip6t_rt *rtinfo = (void *)m->data;
rtinfo->segsleft[1] = ~0U;
}
static void rt_parse(struct xt_option_call *cb) static void rt_parse(struct xt_option_call *cb)
{ {
struct ip6t_rt *rtinfo = cb->data; struct ip6t_rt *rtinfo = cb->data;
...@@ -245,6 +252,7 @@ static struct xtables_match rt_mt6_reg = { ...@@ -245,6 +252,7 @@ static struct xtables_match rt_mt6_reg = {
.size = XT_ALIGN(sizeof(struct ip6t_rt)), .size = XT_ALIGN(sizeof(struct ip6t_rt)),
.userspacesize = XT_ALIGN(sizeof(struct ip6t_rt)), .userspacesize = XT_ALIGN(sizeof(struct ip6t_rt)),
.help = rt_help, .help = rt_help,
.init = rt_init,
.x6_parse = rt_parse, .x6_parse = rt_parse,
.print = rt_print, .print = rt_print,
.save = rt_save, .save = rt_save,
......
/* Shared library add-on to iptables to add MIRROR target support. */
#include <xtables.h>
static struct xtables_target mirror_tg_reg = {
.name = "MIRROR",
.version = XTABLES_VERSION,
.family = NFPROTO_IPV4,
.size = XT_ALIGN(0),
.userspacesize = XT_ALIGN(0),
};
void _init(void)
{
xtables_register_target(&mirror_tg_reg);
}
This is an experimental demonstration target which inverts the source
and destination fields in the IP header and retransmits the packet.
It is only valid in the
.BR INPUT ,
.B FORWARD
and
.B PREROUTING
chains, and user-defined chains which are only called from those
chains. Note that the outgoing packets are
.B NOT
seen by any packet filtering chains, connection tracking or NAT, to
avoid loops and other problems.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <xtables.h>
#include <linux/netfilter/nf_nat.h>
#include <linux/netfilter_ipv4/ipt_SAME.h>
enum {
O_TO_ADDR = 0,
O_NODST,
O_RANDOM,
F_TO_ADDR = 1 << O_TO_ADDR,
F_RANDOM = 1 << O_RANDOM,
};
static void SAME_help(void)
{
printf(
"SAME target options:\n"
" --to <ipaddr>-<ipaddr>\n"
" Addresses to map source to.\n"
" May be specified more than\n"
" once for multiple ranges.\n"
" --nodst\n"
" Don't use destination-ip in\n"
" source selection\n"
" --random\n"
" Randomize source port\n");
}
static const struct xt_option_entry SAME_opts[] = {
{.name = "to", .id = O_TO_ADDR, .type = XTTYPE_STRING,
.flags = XTOPT_MAND},
{.name = "nodst", .id = O_NODST, .type = XTTYPE_NONE},
{.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE},
XTOPT_TABLEEND,
};
/* Parses range of IPs */
static void parse_to(const char *orig_arg, struct nf_nat_ipv4_range *range)
{
char *dash, *arg;
const struct in_addr *ip;
arg = strdup(orig_arg);
if (arg == NULL)
xtables_error(RESOURCE_PROBLEM, "strdup");
range->flags |= NF_NAT_RANGE_MAP_IPS;
dash = strchr(arg, '-');
if (dash)
*dash = '\0';
ip = xtables_numeric_to_ipaddr(arg);
if (!ip)
xtables_error(PARAMETER_PROBLEM, "Bad IP address \"%s\"\n",
arg);
range->min_ip = ip->s_addr;
if (dash) {
ip = xtables_numeric_to_ipaddr(dash+1);
if (!ip)
xtables_error(PARAMETER_PROBLEM, "Bad IP address \"%s\"\n",
dash+1);
}
range->max_ip = ip->s_addr;
if (dash)
if (range->min_ip > range->max_ip)
xtables_error(PARAMETER_PROBLEM, "Bad IP range \"%s-%s\"\n",
arg, dash+1);
free(arg);
}
static void SAME_parse(struct xt_option_call *cb)
{
struct ipt_same_info *mr = cb->data;
unsigned int count;
xtables_option_parse(cb);
switch (cb->entry->id) {
case O_TO_ADDR:
if (mr->rangesize == IPT_SAME_MAX_RANGE)
xtables_error(PARAMETER_PROBLEM,
"Too many ranges specified, maximum "
"is %i ranges.\n",
IPT_SAME_MAX_RANGE);
parse_to(cb->arg, &mr->range[mr->rangesize]);
mr->rangesize++;
break;
case O_NODST:
mr->info |= IPT_SAME_NODST;
break;
case O_RANDOM:
for (count=0; count < mr->rangesize; count++)
mr->range[count].flags |= NF_NAT_RANGE_PROTO_RANDOM;
break;
}
}
static void SAME_fcheck(struct xt_fcheck_call *cb)
{
static const unsigned int f = F_TO_ADDR | F_RANDOM;
struct ipt_same_info *mr = cb->data;
unsigned int count;
if ((cb->xflags & f) == f)
for (count = 0; count < mr->rangesize; ++count)
mr->range[count].flags |= NF_NAT_RANGE_PROTO_RANDOM;
}
static void SAME_print(const void *ip, const struct xt_entry_target *target,
int numeric)
{
unsigned int count;
const struct ipt_same_info *mr = (const void *)target->data;
int random_selection = 0;
printf(" same:");
for (count = 0; count < mr->rangesize; count++) {
const struct nf_nat_ipv4_range *r = &mr->range[count];
struct in_addr a;
a.s_addr = r->min_ip;
printf("%s", xtables_ipaddr_to_numeric(&a));
a.s_addr = r->max_ip;
if (r->min_ip != r->max_ip)
printf("-%s", xtables_ipaddr_to_numeric(&a));
if (r->flags & NF_NAT_RANGE_PROTO_RANDOM)
random_selection = 1;
}
if (mr->info & IPT_SAME_NODST)
printf(" nodst");
if (random_selection)
printf(" random");
}
static void SAME_save(const void *ip, const struct xt_entry_target *target)
{
unsigned int count;
const struct ipt_same_info *mr = (const void *)target->data;
int random_selection = 0;
for (count = 0; count < mr->rangesize; count++) {
const struct nf_nat_ipv4_range *r = &mr->range[count];
struct in_addr a;
a.s_addr = r->min_ip;
printf(" --to %s", xtables_ipaddr_to_numeric(&a));
a.s_addr = r->max_ip;
if (r->min_ip != r->max_ip)
printf("-%s", xtables_ipaddr_to_numeric(&a));
if (r->flags & NF_NAT_RANGE_PROTO_RANDOM)
random_selection = 1;
}
if (mr->info & IPT_SAME_NODST)
printf(" --nodst");
if (random_selection)
printf(" --random");
}
static struct xtables_target same_tg_reg = {
.name = "SAME",
.version = XTABLES_VERSION,
.family = NFPROTO_IPV4,
.size = XT_ALIGN(sizeof(struct ipt_same_info)),
.userspacesize = XT_ALIGN(sizeof(struct ipt_same_info)),
.help = SAME_help,
.x6_parse = SAME_parse,
.x6_fcheck = SAME_fcheck,
.print = SAME_print,
.save = SAME_save,
.x6_options = SAME_opts,
};
void _init(void)
{
xtables_register_target(&same_tg_reg);
}
Similar to SNAT/DNAT depending on chain: it takes a range of addresses
(`\-\-to 1.2.3.4\-1.2.3.7') and gives a client the same
source-/destination-address for each connection.
.PP
N.B.: The DNAT target's \fB\-\-persistent\fP option replaced the SAME target.
.TP
\fB\-\-to\fP \fIipaddr\fP[\fB\-\fP\fIipaddr\fP]
Addresses to map source to. May be specified more than once for
multiple ranges.
.TP
\fB\-\-nodst\fP
Don't use the destination-ip in the calculations when selecting the
new source-ip
.TP
\fB\-\-random\fP
Port mapping will be forcibly randomized to avoid attacks based on
port prediction (kernel >= 2.6.21).
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