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);