10 #include "internal/internal.h"
12 static void __autocomplete(
struct nf_conntrack *ct,
int dir)
14 struct __nfct_tuple *
this = NULL, *other = NULL;
18 this = &ct->head.orig;
23 other = &ct->head.orig;
27 this->l3protonum = other->l3protonum;
28 this->protonum = other->protonum;
30 memcpy(&this->src.v6, &other->dst.v6,
sizeof(
union __nfct_address));
31 memcpy(&this->dst.v6, &other->src.v6,
sizeof(
union __nfct_address));
33 switch(this->protonum) {
40 this->l4src.all = other->l4dst.all;
41 this->l4dst.all = other->l4src.all;
50 ct->head.set[0] |= TS_ORIG | TS_REPL;
53 static void setobjopt_undo_snat(
struct nf_conntrack *ct)
55 switch (ct->head.orig.l3protonum) {
57 ct->snat.min_ip.v4 = ct->repl.dst.v4;
58 ct->snat.max_ip.v4 = ct->snat.min_ip.v4;
59 ct->repl.dst.v4 = ct->head.orig.src.v4;
60 set_bit(ATTR_SNAT_IPV4, ct->head.set);
63 memcpy(&ct->snat.min_ip.v6, &ct->repl.dst.v6,
64 sizeof(
struct in6_addr));
65 memcpy(&ct->snat.max_ip.v6, &ct->snat.min_ip.v6,
66 sizeof(
struct in6_addr));
67 memcpy(&ct->repl.dst.v6, &ct->head.orig.src.v6,
68 sizeof(
struct in6_addr));
69 set_bit(ATTR_SNAT_IPV6, ct->head.set);
76 static void setobjopt_undo_dnat(
struct nf_conntrack *ct)
78 switch (ct->head.orig.l3protonum) {
80 ct->dnat.min_ip.v4 = ct->repl.src.v4;
81 ct->dnat.max_ip.v4 = ct->dnat.min_ip.v4;
82 ct->repl.src.v4 = ct->head.orig.dst.v4;
83 set_bit(ATTR_DNAT_IPV4, ct->head.set);
86 memcpy(&ct->dnat.min_ip.v6, &ct->repl.src.v6,
87 sizeof(
struct in6_addr));
88 memcpy(&ct->dnat.max_ip.v6, &ct->dnat.min_ip.v6,
89 sizeof(
struct in6_addr));
90 memcpy(&ct->repl.src.v6, &ct->head.orig.dst.v6,
91 sizeof(
struct in6_addr));
92 set_bit(ATTR_DNAT_IPV6, ct->head.set);
99 static void setobjopt_undo_spat(
struct nf_conntrack *ct)
101 ct->snat.l4min.all = ct->repl.l4dst.tcp.port;
102 ct->snat.l4max.all = ct->snat.l4min.all;
103 ct->repl.l4dst.tcp.port =
104 ct->head.orig.l4src.tcp.port;
105 set_bit(ATTR_SNAT_PORT, ct->head.set);
108 static void setobjopt_undo_dpat(
struct nf_conntrack *ct)
110 ct->dnat.l4min.all = ct->repl.l4src.tcp.port;
111 ct->dnat.l4max.all = ct->dnat.l4min.all;
112 ct->repl.l4src.tcp.port =
113 ct->head.orig.l4dst.tcp.port;
114 set_bit(ATTR_DNAT_PORT, ct->head.set);
117 static void setobjopt_setup_orig(
struct nf_conntrack *ct)
119 __autocomplete(ct, __DIR_ORIG);
122 static void setobjopt_setup_repl(
struct nf_conntrack *ct)
124 __autocomplete(ct, __DIR_REPL);
127 static const setobjopt setobjopt_array[__NFCT_SOPT_MAX] = {
128 [NFCT_SOPT_UNDO_SNAT] = setobjopt_undo_snat,
129 [NFCT_SOPT_UNDO_DNAT] = setobjopt_undo_dnat,
130 [NFCT_SOPT_UNDO_SPAT] = setobjopt_undo_spat,
131 [NFCT_SOPT_UNDO_DPAT] = setobjopt_undo_dpat,
132 [NFCT_SOPT_SETUP_ORIGINAL] = setobjopt_setup_orig,
133 [NFCT_SOPT_SETUP_REPLY] = setobjopt_setup_repl,
136 int __setobjopt(
struct nf_conntrack *ct,
unsigned int option)
138 if (unlikely(option > NFCT_SOPT_MAX))
141 setobjopt_array[option](ct);
145 static int getobjopt_is_snat(
const struct nf_conntrack *ct)
147 if (test_bit(ATTR_STATUS, ct->head.set) &&
148 !(ct->status & IPS_SRC_NAT_DONE))
151 switch (ct->head.orig.l3protonum) {
153 return ct->repl.dst.v4 != ct->head.orig.src.v4;
155 if (memcmp(&ct->repl.dst.v6, &ct->head.orig.src.v6,
156 sizeof(
struct in6_addr)) != 0)
165 static int getobjopt_is_dnat(
const struct nf_conntrack *ct)
167 if (test_bit(ATTR_STATUS, ct->head.set) &&
168 !(ct->status & IPS_DST_NAT_DONE))
171 switch (ct->head.orig.l3protonum) {
173 return ct->repl.src.v4 != ct->head.orig.dst.v4;
175 if (memcmp(&ct->repl.src.v6, &ct->head.orig.dst.v6,
176 sizeof(
struct in6_addr)) != 0)
185 static int getobjopt_is_spat(
const struct nf_conntrack *ct)
187 return ((test_bit(ATTR_STATUS, ct->head.set) ?
188 ct->status & IPS_SRC_NAT_DONE : 1) &&
189 ct->repl.l4dst.tcp.port !=
190 ct->head.orig.l4src.tcp.port);
193 static int getobjopt_is_dpat(
const struct nf_conntrack *ct)
195 return ((test_bit(ATTR_STATUS, ct->head.set) ?
196 ct->status & IPS_DST_NAT_DONE : 1) &&
197 ct->repl.l4src.tcp.port !=
198 ct->head.orig.l4dst.tcp.port);
201 static const getobjopt getobjopt_array[__NFCT_GOPT_MAX] = {
202 [NFCT_GOPT_IS_SNAT] = getobjopt_is_snat,
203 [NFCT_GOPT_IS_DNAT] = getobjopt_is_dnat,
204 [NFCT_GOPT_IS_SPAT] = getobjopt_is_spat,
205 [NFCT_GOPT_IS_DPAT] = getobjopt_is_dpat,
208 int __getobjopt(
const struct nf_conntrack *ct,
unsigned int option)
210 if (unlikely(option > NFCT_GOPT_MAX))
213 return getobjopt_array[option](ct);