1 /*
2 * (C) 2005-2011 by Pablo Neira Ayuso <pablo@netfilter.org>
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 */
9
10 #include "internal/internal.h"
11 #include <linux/icmp.h>
12 #include <linux/icmpv6.h>
13
14 static const uint8_t invmap_icmp[] = {
15 [ICMP_ECHO] = ICMP_ECHOREPLY + 1,
16 [ICMP_ECHOREPLY] = ICMP_ECHO + 1,
17 [ICMP_TIMESTAMP] = ICMP_TIMESTAMPREPLY + 1,
18 [ICMP_TIMESTAMPREPLY] = ICMP_TIMESTAMP + 1,
19 [ICMP_INFO_REQUEST] = ICMP_INFO_REPLY + 1,
20 [ICMP_INFO_REPLY] = ICMP_INFO_REQUEST + 1,
21 [ICMP_ADDRESS] = ICMP_ADDRESSREPLY + 1,
22 [ICMP_ADDRESSREPLY] = ICMP_ADDRESS + 1
23 };
24
25 #ifndef ICMPV6_NI_QUERY
26 #define ICMPV6_NI_QUERY 139
27 #endif
28
29 #ifndef ICMPV6_NI_REPLY
30 #define ICMPV6_NI_REPLY 140
31 #endif
32
33 static const uint8_t invmap_icmpv6[] = {
34 [ICMPV6_ECHO_REQUEST - 128] = ICMPV6_ECHO_REPLY + 1,
35 [ICMPV6_ECHO_REPLY - 128] = ICMPV6_ECHO_REQUEST + 1,
36 [ICMPV6_NI_QUERY - 128] = ICMPV6_NI_QUERY + 1,
37 [ICMPV6_NI_REPLY - 128] = ICMPV6_NI_REPLY + 1
38 };
39
set_attr_grp_orig_ipv4(struct nf_conntrack * ct,const void * value)40 static void set_attr_grp_orig_ipv4(struct nf_conntrack *ct, const void *value)
41 {
42 const struct nfct_attr_grp_ipv4 *this = value;
43 ct->head.orig.src.v4 = this->src;
44 ct->head.orig.dst.v4 = this->dst;
45 ct->head.orig.l3protonum = AF_INET;
46 }
47
set_attr_grp_repl_ipv4(struct nf_conntrack * ct,const void * value)48 static void set_attr_grp_repl_ipv4(struct nf_conntrack *ct, const void *value)
49 {
50 const struct nfct_attr_grp_ipv4 *this = value;
51 ct->repl.src.v4 = this->src;
52 ct->repl.dst.v4 = this->dst;
53 ct->repl.l3protonum = AF_INET;
54 }
55
set_attr_grp_orig_ipv6(struct nf_conntrack * ct,const void * value)56 static void set_attr_grp_orig_ipv6(struct nf_conntrack *ct, const void *value)
57 {
58 const struct nfct_attr_grp_ipv6 *this = value;
59 memcpy(&ct->head.orig.src.v6, this->src, sizeof(uint32_t)*4);
60 memcpy(&ct->head.orig.dst.v6, this->dst, sizeof(uint32_t)*4);
61 ct->head.orig.l3protonum = AF_INET6;
62 }
63
set_attr_grp_repl_ipv6(struct nf_conntrack * ct,const void * value)64 static void set_attr_grp_repl_ipv6(struct nf_conntrack *ct, const void *value)
65 {
66 const struct nfct_attr_grp_ipv6 *this = value;
67 memcpy(&ct->repl.src.v6, this->src, sizeof(uint32_t)*4);
68 memcpy(&ct->repl.dst.v6, this->dst, sizeof(uint32_t)*4);
69 ct->repl.l3protonum = AF_INET6;
70 }
71
set_attr_grp_orig_port(struct nf_conntrack * ct,const void * value)72 static void set_attr_grp_orig_port(struct nf_conntrack *ct, const void *value)
73 {
74 const struct nfct_attr_grp_port *this = value;
75 ct->head.orig.l4src.all = this->sport;
76 ct->head.orig.l4dst.all = this->dport;
77 }
78
set_attr_grp_repl_port(struct nf_conntrack * ct,const void * value)79 static void set_attr_grp_repl_port(struct nf_conntrack *ct, const void *value)
80 {
81 const struct nfct_attr_grp_port *this = value;
82 ct->repl.l4src.all = this->sport;
83 ct->repl.l4dst.all = this->dport;
84 }
85
set_attr_grp_icmp(struct nf_conntrack * ct,const void * value)86 static void set_attr_grp_icmp(struct nf_conntrack *ct, const void *value)
87 {
88 uint8_t rtype;
89 const struct nfct_attr_grp_icmp *this = value;
90
91 ct->head.orig.l4dst.icmp.type = this->type;
92
93 switch(ct->head.orig.l3protonum) {
94 case AF_INET:
95 rtype = invmap_icmp[this->type];
96 break;
97
98 case AF_INET6:
99 rtype = invmap_icmpv6[this->type - 128];
100 break;
101
102 default:
103 rtype = 0; /* not found */
104 }
105
106 if (rtype)
107 ct->repl.l4dst.icmp.type = rtype - 1;
108 else
109 ct->repl.l4dst.icmp.type = 255; /* -EINVAL */
110
111 ct->head.orig.l4dst.icmp.code = this->code;
112 ct->repl.l4dst.icmp.code = this->code;
113
114 ct->head.orig.l4src.icmp.id = this->id;
115 ct->repl.l4src.icmp.id = this->id;
116 }
117
set_attr_grp_master_ipv4(struct nf_conntrack * ct,const void * value)118 static void set_attr_grp_master_ipv4(struct nf_conntrack *ct, const void *value)
119 {
120 const struct nfct_attr_grp_ipv4 *this = value;
121 ct->master.src.v4 = this->src;
122 ct->master.dst.v4 = this->dst;
123 ct->master.l3protonum = AF_INET;
124 }
125
set_attr_grp_master_ipv6(struct nf_conntrack * ct,const void * value)126 static void set_attr_grp_master_ipv6(struct nf_conntrack *ct, const void *value)
127 {
128 const struct nfct_attr_grp_ipv6 *this = value;
129 memcpy(&ct->master.src.v6, this->src, sizeof(uint32_t)*4);
130 memcpy(&ct->master.dst.v6, this->dst, sizeof(uint32_t)*4);
131 ct->master.l3protonum = AF_INET6;
132 }
133
set_attr_grp_master_port(struct nf_conntrack * ct,const void * value)134 static void set_attr_grp_master_port(struct nf_conntrack *ct, const void *value)
135 {
136 const struct nfct_attr_grp_port *this = value;
137 ct->master.l4src.all = this->sport;
138 ct->master.l4dst.all = this->dport;
139 }
140
set_attr_grp_do_nothing(struct nf_conntrack * ct,const void * value)141 static void set_attr_grp_do_nothing(struct nf_conntrack *ct, const void *value)
142 {
143 }
144
145 const set_attr_grp set_attr_grp_array[ATTR_GRP_MAX] = {
146 [ATTR_GRP_ORIG_IPV4] = set_attr_grp_orig_ipv4,
147 [ATTR_GRP_REPL_IPV4] = set_attr_grp_repl_ipv4,
148 [ATTR_GRP_ORIG_IPV6] = set_attr_grp_orig_ipv6,
149 [ATTR_GRP_REPL_IPV6] = set_attr_grp_repl_ipv6,
150 [ATTR_GRP_ORIG_PORT] = set_attr_grp_orig_port,
151 [ATTR_GRP_REPL_PORT] = set_attr_grp_repl_port,
152 [ATTR_GRP_ICMP] = set_attr_grp_icmp,
153 [ATTR_GRP_MASTER_IPV4] = set_attr_grp_master_ipv4,
154 [ATTR_GRP_MASTER_IPV6] = set_attr_grp_master_ipv6,
155 [ATTR_GRP_MASTER_PORT] = set_attr_grp_master_port,
156 [ATTR_GRP_ORIG_COUNTERS] = set_attr_grp_do_nothing,
157 [ATTR_GRP_REPL_COUNTERS] = set_attr_grp_do_nothing,
158 [ATTR_GRP_ORIG_ADDR_SRC] = set_attr_grp_do_nothing,
159 [ATTR_GRP_ORIG_ADDR_DST] = set_attr_grp_do_nothing,
160 [ATTR_GRP_REPL_ADDR_SRC] = set_attr_grp_do_nothing,
161 [ATTR_GRP_REPL_ADDR_DST] = set_attr_grp_do_nothing,
162 };
163