/*
|
* (C) 2005-2011 by Pablo Neira Ayuso <pablo@netfilter.org>
|
*
|
* This program is free software; you can redistribute it and/or modify it
|
* under the terms of the GNU General Public License as published by
|
* the Free Software Foundation; either version 2 of the License, or
|
* (at your option) any later version.
|
*/
|
|
#include "internal/internal.h"
|
#include <linux/icmp.h>
|
#include <linux/icmpv6.h>
|
|
static const uint8_t invmap_icmp[] = {
|
[ICMP_ECHO] = ICMP_ECHOREPLY + 1,
|
[ICMP_ECHOREPLY] = ICMP_ECHO + 1,
|
[ICMP_TIMESTAMP] = ICMP_TIMESTAMPREPLY + 1,
|
[ICMP_TIMESTAMPREPLY] = ICMP_TIMESTAMP + 1,
|
[ICMP_INFO_REQUEST] = ICMP_INFO_REPLY + 1,
|
[ICMP_INFO_REPLY] = ICMP_INFO_REQUEST + 1,
|
[ICMP_ADDRESS] = ICMP_ADDRESSREPLY + 1,
|
[ICMP_ADDRESSREPLY] = ICMP_ADDRESS + 1
|
};
|
|
#ifndef ICMPV6_NI_QUERY
|
#define ICMPV6_NI_QUERY 139
|
#endif
|
|
#ifndef ICMPV6_NI_REPLY
|
#define ICMPV6_NI_REPLY 140
|
#endif
|
|
static const uint8_t invmap_icmpv6[] = {
|
[ICMPV6_ECHO_REQUEST - 128] = ICMPV6_ECHO_REPLY + 1,
|
[ICMPV6_ECHO_REPLY - 128] = ICMPV6_ECHO_REQUEST + 1,
|
[ICMPV6_NI_QUERY - 128] = ICMPV6_NI_QUERY + 1,
|
[ICMPV6_NI_REPLY - 128] = ICMPV6_NI_REPLY + 1
|
};
|
|
static void set_attr_grp_orig_ipv4(struct nf_conntrack *ct, const void *value)
|
{
|
const struct nfct_attr_grp_ipv4 *this = value;
|
ct->head.orig.src.v4 = this->src;
|
ct->head.orig.dst.v4 = this->dst;
|
ct->head.orig.l3protonum = AF_INET;
|
}
|
|
static void set_attr_grp_repl_ipv4(struct nf_conntrack *ct, const void *value)
|
{
|
const struct nfct_attr_grp_ipv4 *this = value;
|
ct->repl.src.v4 = this->src;
|
ct->repl.dst.v4 = this->dst;
|
ct->repl.l3protonum = AF_INET;
|
}
|
|
static void set_attr_grp_orig_ipv6(struct nf_conntrack *ct, const void *value)
|
{
|
const struct nfct_attr_grp_ipv6 *this = value;
|
memcpy(&ct->head.orig.src.v6, this->src, sizeof(uint32_t)*4);
|
memcpy(&ct->head.orig.dst.v6, this->dst, sizeof(uint32_t)*4);
|
ct->head.orig.l3protonum = AF_INET6;
|
}
|
|
static void set_attr_grp_repl_ipv6(struct nf_conntrack *ct, const void *value)
|
{
|
const struct nfct_attr_grp_ipv6 *this = value;
|
memcpy(&ct->repl.src.v6, this->src, sizeof(uint32_t)*4);
|
memcpy(&ct->repl.dst.v6, this->dst, sizeof(uint32_t)*4);
|
ct->repl.l3protonum = AF_INET6;
|
}
|
|
static void set_attr_grp_orig_port(struct nf_conntrack *ct, const void *value)
|
{
|
const struct nfct_attr_grp_port *this = value;
|
ct->head.orig.l4src.all = this->sport;
|
ct->head.orig.l4dst.all = this->dport;
|
}
|
|
static void set_attr_grp_repl_port(struct nf_conntrack *ct, const void *value)
|
{
|
const struct nfct_attr_grp_port *this = value;
|
ct->repl.l4src.all = this->sport;
|
ct->repl.l4dst.all = this->dport;
|
}
|
|
static void set_attr_grp_icmp(struct nf_conntrack *ct, const void *value)
|
{
|
uint8_t rtype;
|
const struct nfct_attr_grp_icmp *this = value;
|
|
ct->head.orig.l4dst.icmp.type = this->type;
|
|
switch(ct->head.orig.l3protonum) {
|
case AF_INET:
|
rtype = invmap_icmp[this->type];
|
break;
|
|
case AF_INET6:
|
rtype = invmap_icmpv6[this->type - 128];
|
break;
|
|
default:
|
rtype = 0; /* not found */
|
}
|
|
if (rtype)
|
ct->repl.l4dst.icmp.type = rtype - 1;
|
else
|
ct->repl.l4dst.icmp.type = 255; /* -EINVAL */
|
|
ct->head.orig.l4dst.icmp.code = this->code;
|
ct->repl.l4dst.icmp.code = this->code;
|
|
ct->head.orig.l4src.icmp.id = this->id;
|
ct->repl.l4src.icmp.id = this->id;
|
}
|
|
static void set_attr_grp_master_ipv4(struct nf_conntrack *ct, const void *value)
|
{
|
const struct nfct_attr_grp_ipv4 *this = value;
|
ct->master.src.v4 = this->src;
|
ct->master.dst.v4 = this->dst;
|
ct->master.l3protonum = AF_INET;
|
}
|
|
static void set_attr_grp_master_ipv6(struct nf_conntrack *ct, const void *value)
|
{
|
const struct nfct_attr_grp_ipv6 *this = value;
|
memcpy(&ct->master.src.v6, this->src, sizeof(uint32_t)*4);
|
memcpy(&ct->master.dst.v6, this->dst, sizeof(uint32_t)*4);
|
ct->master.l3protonum = AF_INET6;
|
}
|
|
static void set_attr_grp_master_port(struct nf_conntrack *ct, const void *value)
|
{
|
const struct nfct_attr_grp_port *this = value;
|
ct->master.l4src.all = this->sport;
|
ct->master.l4dst.all = this->dport;
|
}
|
|
static void set_attr_grp_do_nothing(struct nf_conntrack *ct, const void *value)
|
{
|
}
|
|
const set_attr_grp set_attr_grp_array[ATTR_GRP_MAX] = {
|
[ATTR_GRP_ORIG_IPV4] = set_attr_grp_orig_ipv4,
|
[ATTR_GRP_REPL_IPV4] = set_attr_grp_repl_ipv4,
|
[ATTR_GRP_ORIG_IPV6] = set_attr_grp_orig_ipv6,
|
[ATTR_GRP_REPL_IPV6] = set_attr_grp_repl_ipv6,
|
[ATTR_GRP_ORIG_PORT] = set_attr_grp_orig_port,
|
[ATTR_GRP_REPL_PORT] = set_attr_grp_repl_port,
|
[ATTR_GRP_ICMP] = set_attr_grp_icmp,
|
[ATTR_GRP_MASTER_IPV4] = set_attr_grp_master_ipv4,
|
[ATTR_GRP_MASTER_IPV6] = set_attr_grp_master_ipv6,
|
[ATTR_GRP_MASTER_PORT] = set_attr_grp_master_port,
|
[ATTR_GRP_ORIG_COUNTERS] = set_attr_grp_do_nothing,
|
[ATTR_GRP_REPL_COUNTERS] = set_attr_grp_do_nothing,
|
[ATTR_GRP_ORIG_ADDR_SRC] = set_attr_grp_do_nothing,
|
[ATTR_GRP_ORIG_ADDR_DST] = set_attr_grp_do_nothing,
|
[ATTR_GRP_REPL_ADDR_SRC] = set_attr_grp_do_nothing,
|
[ATTR_GRP_REPL_ADDR_DST] = set_attr_grp_do_nothing,
|
};
|