18a44513648da0c5f5551f96b329cf56b66f5b303pkanwar/*
28a44513648da0c5f5551f96b329cf56b66f5b303pkanwar * (C) 2005-2011 by Pablo Neira Ayuso <pablo@netfilter.org>
38a44513648da0c5f5551f96b329cf56b66f5b303pkanwar *
48a44513648da0c5f5551f96b329cf56b66f5b303pkanwar * This program is free software; you can redistribute it and/or modify it
58a44513648da0c5f5551f96b329cf56b66f5b303pkanwar * under the terms of the GNU General Public License as published by
68a44513648da0c5f5551f96b329cf56b66f5b303pkanwar * the Free Software Foundation; either version 2 of the License, or
78a44513648da0c5f5551f96b329cf56b66f5b303pkanwar * (at your option) any later version.
88a44513648da0c5f5551f96b329cf56b66f5b303pkanwar */
98a44513648da0c5f5551f96b329cf56b66f5b303pkanwar
108a44513648da0c5f5551f96b329cf56b66f5b303pkanwar#include "internal/internal.h"
118a44513648da0c5f5551f96b329cf56b66f5b303pkanwar#include <linux/icmp.h>
128a44513648da0c5f5551f96b329cf56b66f5b303pkanwar#include <linux/icmpv6.h>
138a44513648da0c5f5551f96b329cf56b66f5b303pkanwar
148a44513648da0c5f5551f96b329cf56b66f5b303pkanwarstatic const uint8_t invmap_icmp[] = {
158a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	[ICMP_ECHO]		= ICMP_ECHOREPLY + 1,
168a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	[ICMP_ECHOREPLY]	= ICMP_ECHO + 1,
178a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	[ICMP_TIMESTAMP]	= ICMP_TIMESTAMPREPLY + 1,
188a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	[ICMP_TIMESTAMPREPLY]	= ICMP_TIMESTAMP + 1,
198a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	[ICMP_INFO_REQUEST]	= ICMP_INFO_REPLY + 1,
208a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	[ICMP_INFO_REPLY]	= ICMP_INFO_REQUEST + 1,
218a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	[ICMP_ADDRESS]		= ICMP_ADDRESSREPLY + 1,
228a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	[ICMP_ADDRESSREPLY]	= ICMP_ADDRESS + 1
238a44513648da0c5f5551f96b329cf56b66f5b303pkanwar};
248a44513648da0c5f5551f96b329cf56b66f5b303pkanwar
258a44513648da0c5f5551f96b329cf56b66f5b303pkanwar#ifndef ICMPV6_NI_QUERY
268a44513648da0c5f5551f96b329cf56b66f5b303pkanwar#define ICMPV6_NI_QUERY 139
278a44513648da0c5f5551f96b329cf56b66f5b303pkanwar#endif
288a44513648da0c5f5551f96b329cf56b66f5b303pkanwar
298a44513648da0c5f5551f96b329cf56b66f5b303pkanwar#ifndef ICMPV6_NI_REPLY
308a44513648da0c5f5551f96b329cf56b66f5b303pkanwar#define ICMPV6_NI_REPLY 140
318a44513648da0c5f5551f96b329cf56b66f5b303pkanwar#endif
328a44513648da0c5f5551f96b329cf56b66f5b303pkanwar
338a44513648da0c5f5551f96b329cf56b66f5b303pkanwarstatic const uint8_t invmap_icmpv6[] = {
348a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	[ICMPV6_ECHO_REQUEST - 128]	= ICMPV6_ECHO_REPLY + 1,
358a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	[ICMPV6_ECHO_REPLY - 128]	= ICMPV6_ECHO_REQUEST + 1,
368a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	[ICMPV6_NI_QUERY - 128]		= ICMPV6_NI_QUERY + 1,
378a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	[ICMPV6_NI_REPLY - 128]		= ICMPV6_NI_REPLY + 1
388a44513648da0c5f5551f96b329cf56b66f5b303pkanwar};
398a44513648da0c5f5551f96b329cf56b66f5b303pkanwar
408a44513648da0c5f5551f96b329cf56b66f5b303pkanwarstatic void set_attr_grp_orig_ipv4(struct nf_conntrack *ct, const void *value)
418a44513648da0c5f5551f96b329cf56b66f5b303pkanwar{
428a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	const struct nfct_attr_grp_ipv4 *this = value;
438a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	ct->head.orig.src.v4 = this->src;
448a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	ct->head.orig.dst.v4 = this->dst;
458a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	ct->head.orig.l3protonum = AF_INET;
468a44513648da0c5f5551f96b329cf56b66f5b303pkanwar}
478a44513648da0c5f5551f96b329cf56b66f5b303pkanwar
488a44513648da0c5f5551f96b329cf56b66f5b303pkanwarstatic void set_attr_grp_repl_ipv4(struct nf_conntrack *ct, const void *value)
498a44513648da0c5f5551f96b329cf56b66f5b303pkanwar{
508a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	const struct nfct_attr_grp_ipv4 *this = value;
518a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	ct->repl.src.v4 = this->src;
528a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	ct->repl.dst.v4 = this->dst;
538a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	ct->repl.l3protonum = AF_INET;
548a44513648da0c5f5551f96b329cf56b66f5b303pkanwar}
558a44513648da0c5f5551f96b329cf56b66f5b303pkanwar
568a44513648da0c5f5551f96b329cf56b66f5b303pkanwarstatic void set_attr_grp_orig_ipv6(struct nf_conntrack *ct, const void *value)
578a44513648da0c5f5551f96b329cf56b66f5b303pkanwar{
588a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	const struct nfct_attr_grp_ipv6 *this = value;
598a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	memcpy(&ct->head.orig.src.v6, this->src, sizeof(uint32_t)*4);
608a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	memcpy(&ct->head.orig.dst.v6, this->dst, sizeof(uint32_t)*4);
618a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	ct->head.orig.l3protonum = AF_INET6;
628a44513648da0c5f5551f96b329cf56b66f5b303pkanwar}
638a44513648da0c5f5551f96b329cf56b66f5b303pkanwar
648a44513648da0c5f5551f96b329cf56b66f5b303pkanwarstatic void set_attr_grp_repl_ipv6(struct nf_conntrack *ct, const void *value)
658a44513648da0c5f5551f96b329cf56b66f5b303pkanwar{
668a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	const struct nfct_attr_grp_ipv6 *this = value;
678a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	memcpy(&ct->repl.src.v6, this->src, sizeof(uint32_t)*4);
688a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	memcpy(&ct->repl.dst.v6, this->dst, sizeof(uint32_t)*4);
698a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	ct->repl.l3protonum = AF_INET6;
708a44513648da0c5f5551f96b329cf56b66f5b303pkanwar}
718a44513648da0c5f5551f96b329cf56b66f5b303pkanwar
728a44513648da0c5f5551f96b329cf56b66f5b303pkanwarstatic void set_attr_grp_orig_port(struct nf_conntrack *ct, const void *value)
738a44513648da0c5f5551f96b329cf56b66f5b303pkanwar{
748a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	const struct nfct_attr_grp_port *this = value;
758a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	ct->head.orig.l4src.all = this->sport;
768a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	ct->head.orig.l4dst.all = this->dport;
778a44513648da0c5f5551f96b329cf56b66f5b303pkanwar}
788a44513648da0c5f5551f96b329cf56b66f5b303pkanwar
798a44513648da0c5f5551f96b329cf56b66f5b303pkanwarstatic void set_attr_grp_repl_port(struct nf_conntrack *ct, const void *value)
808a44513648da0c5f5551f96b329cf56b66f5b303pkanwar{
818a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	const struct nfct_attr_grp_port *this = value;
828a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	ct->repl.l4src.all = this->sport;
838a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	ct->repl.l4dst.all = this->dport;
848a44513648da0c5f5551f96b329cf56b66f5b303pkanwar}
858a44513648da0c5f5551f96b329cf56b66f5b303pkanwar
868a44513648da0c5f5551f96b329cf56b66f5b303pkanwarstatic void set_attr_grp_icmp(struct nf_conntrack *ct, const void *value)
878a44513648da0c5f5551f96b329cf56b66f5b303pkanwar{
888a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	uint8_t rtype;
898a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	const struct nfct_attr_grp_icmp *this = value;
908a44513648da0c5f5551f96b329cf56b66f5b303pkanwar
918a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	ct->head.orig.l4dst.icmp.type = this->type;
928a44513648da0c5f5551f96b329cf56b66f5b303pkanwar
938a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	switch(ct->head.orig.l3protonum) {
948a44513648da0c5f5551f96b329cf56b66f5b303pkanwar		case AF_INET:
958a44513648da0c5f5551f96b329cf56b66f5b303pkanwar			rtype = invmap_icmp[this->type];
968a44513648da0c5f5551f96b329cf56b66f5b303pkanwar			break;
978a44513648da0c5f5551f96b329cf56b66f5b303pkanwar
988a44513648da0c5f5551f96b329cf56b66f5b303pkanwar		case AF_INET6:
998a44513648da0c5f5551f96b329cf56b66f5b303pkanwar			rtype = invmap_icmpv6[this->type - 128];
1008a44513648da0c5f5551f96b329cf56b66f5b303pkanwar			break;
1018a44513648da0c5f5551f96b329cf56b66f5b303pkanwar
1028a44513648da0c5f5551f96b329cf56b66f5b303pkanwar		default:
1038a44513648da0c5f5551f96b329cf56b66f5b303pkanwar			rtype = 0;	/* not found */
1048a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	}
1058a44513648da0c5f5551f96b329cf56b66f5b303pkanwar
1068a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	if (rtype)
1078a44513648da0c5f5551f96b329cf56b66f5b303pkanwar		ct->repl.l4dst.icmp.type = rtype - 1;
1088a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	else
1098a44513648da0c5f5551f96b329cf56b66f5b303pkanwar		ct->repl.l4dst.icmp.type = 255;	/* -EINVAL */
1108a44513648da0c5f5551f96b329cf56b66f5b303pkanwar
1118a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	ct->head.orig.l4dst.icmp.code = this->code;
1128a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	ct->repl.l4dst.icmp.code = this->code;
1138a44513648da0c5f5551f96b329cf56b66f5b303pkanwar
1148a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	ct->head.orig.l4src.icmp.id = this->id;
1158a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	ct->repl.l4src.icmp.id = this->id;
1168a44513648da0c5f5551f96b329cf56b66f5b303pkanwar}
1178a44513648da0c5f5551f96b329cf56b66f5b303pkanwar
1188a44513648da0c5f5551f96b329cf56b66f5b303pkanwarstatic void set_attr_grp_master_ipv4(struct nf_conntrack *ct, const void *value)
1198a44513648da0c5f5551f96b329cf56b66f5b303pkanwar{
1208a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	const struct nfct_attr_grp_ipv4 *this = value;
1218a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	ct->master.src.v4 = this->src;
1228a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	ct->master.dst.v4 = this->dst;
1238a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	ct->master.l3protonum = AF_INET;
1248a44513648da0c5f5551f96b329cf56b66f5b303pkanwar}
1258a44513648da0c5f5551f96b329cf56b66f5b303pkanwar
1268a44513648da0c5f5551f96b329cf56b66f5b303pkanwarstatic void set_attr_grp_master_ipv6(struct nf_conntrack *ct, const void *value)
1278a44513648da0c5f5551f96b329cf56b66f5b303pkanwar{
1288a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	const struct nfct_attr_grp_ipv6 *this = value;
1298a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	memcpy(&ct->master.src.v6, this->src, sizeof(uint32_t)*4);
1308a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	memcpy(&ct->master.dst.v6, this->dst, sizeof(uint32_t)*4);
1318a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	ct->master.l3protonum = AF_INET6;
1328a44513648da0c5f5551f96b329cf56b66f5b303pkanwar}
1338a44513648da0c5f5551f96b329cf56b66f5b303pkanwar
1348a44513648da0c5f5551f96b329cf56b66f5b303pkanwarstatic void set_attr_grp_master_port(struct nf_conntrack *ct, const void *value)
1358a44513648da0c5f5551f96b329cf56b66f5b303pkanwar{
1368a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	const struct nfct_attr_grp_port *this = value;
1378a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	ct->master.l4src.all = this->sport;
1388a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	ct->master.l4dst.all = this->dport;
1398a44513648da0c5f5551f96b329cf56b66f5b303pkanwar}
1408a44513648da0c5f5551f96b329cf56b66f5b303pkanwar
1418a44513648da0c5f5551f96b329cf56b66f5b303pkanwarstatic void set_attr_grp_do_nothing(struct nf_conntrack *ct, const void *value)
1428a44513648da0c5f5551f96b329cf56b66f5b303pkanwar{
1438a44513648da0c5f5551f96b329cf56b66f5b303pkanwar}
1448a44513648da0c5f5551f96b329cf56b66f5b303pkanwar
1458a44513648da0c5f5551f96b329cf56b66f5b303pkanwarconst set_attr_grp set_attr_grp_array[ATTR_GRP_MAX] = {
1468a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	[ATTR_GRP_ORIG_IPV4]		= set_attr_grp_orig_ipv4,
1478a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	[ATTR_GRP_REPL_IPV4]		= set_attr_grp_repl_ipv4,
1488a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	[ATTR_GRP_ORIG_IPV6]		= set_attr_grp_orig_ipv6,
1498a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	[ATTR_GRP_REPL_IPV6]		= set_attr_grp_repl_ipv6,
1508a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	[ATTR_GRP_ORIG_PORT]		= set_attr_grp_orig_port,
1518a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	[ATTR_GRP_REPL_PORT]		= set_attr_grp_repl_port,
1528a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	[ATTR_GRP_ICMP]			= set_attr_grp_icmp,
1538a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	[ATTR_GRP_MASTER_IPV4]		= set_attr_grp_master_ipv4,
1548a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	[ATTR_GRP_MASTER_IPV6]		= set_attr_grp_master_ipv6,
1558a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	[ATTR_GRP_MASTER_PORT]		= set_attr_grp_master_port,
1568a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	[ATTR_GRP_ORIG_COUNTERS]	= set_attr_grp_do_nothing,
1578a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	[ATTR_GRP_REPL_COUNTERS]	= set_attr_grp_do_nothing,
1588a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	[ATTR_GRP_ORIG_ADDR_SRC]	= set_attr_grp_do_nothing,
1598a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	[ATTR_GRP_ORIG_ADDR_DST]	= set_attr_grp_do_nothing,
1608a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	[ATTR_GRP_REPL_ADDR_SRC]	= set_attr_grp_do_nothing,
1618a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	[ATTR_GRP_REPL_ADDR_DST]	= set_attr_grp_do_nothing,
1628a44513648da0c5f5551f96b329cf56b66f5b303pkanwar};
163