00001
00002
00003
00004
00005
00006
00007
00008 #include "internal/internal.h"
00009
00010 static void __autocomplete(struct nf_conntrack *ct, int dir)
00011 {
00012 int other = (dir == __DIR_ORIG) ? __DIR_REPL : __DIR_ORIG;
00013
00014 ct->tuple[dir].l3protonum = ct->tuple[other].l3protonum;
00015 ct->tuple[dir].protonum = ct->tuple[other].protonum;
00016
00017 memcpy(&ct->tuple[dir].src.v6,
00018 &ct->tuple[other].dst.v6,
00019 sizeof(union __nfct_address));
00020 memcpy(&ct->tuple[dir].dst.v6,
00021 &ct->tuple[other].src.v6,
00022 sizeof(union __nfct_address));
00023
00024 switch(ct->tuple[dir].protonum) {
00025 case IPPROTO_UDP:
00026 case IPPROTO_TCP:
00027 case IPPROTO_SCTP:
00028 case IPPROTO_DCCP:
00029 case IPPROTO_GRE:
00030 case IPPROTO_UDPLITE:
00031 ct->tuple[dir].l4src.all = ct->tuple[other].l4dst.all;
00032 ct->tuple[dir].l4dst.all = ct->tuple[other].l4src.all;
00033 break;
00034 case IPPROTO_ICMP:
00035 case IPPROTO_ICMPV6:
00036
00037 break;
00038 }
00039
00040
00041 ct->set[0] |= TS_ORIG | TS_REPL;
00042 }
00043
00044 static void setobjopt_undo_snat(struct nf_conntrack *ct)
00045 {
00046 ct->snat.min_ip = ct->tuple[__DIR_REPL].dst.v4;
00047 ct->snat.max_ip = ct->snat.min_ip;
00048 ct->tuple[__DIR_REPL].dst.v4 = ct->tuple[__DIR_ORIG].src.v4;
00049 set_bit(ATTR_SNAT_IPV4, ct->set);
00050 }
00051
00052 static void setobjopt_undo_dnat(struct nf_conntrack *ct)
00053 {
00054 ct->dnat.min_ip = ct->tuple[__DIR_REPL].src.v4;
00055 ct->dnat.max_ip = ct->dnat.min_ip;
00056 ct->tuple[__DIR_REPL].src.v4 = ct->tuple[__DIR_ORIG].dst.v4;
00057 set_bit(ATTR_DNAT_IPV4, ct->set);
00058 }
00059
00060 static void setobjopt_undo_spat(struct nf_conntrack *ct)
00061 {
00062 ct->snat.l4min.all = ct->tuple[__DIR_REPL].l4dst.tcp.port;
00063 ct->snat.l4max.all = ct->snat.l4max.all;
00064 ct->tuple[__DIR_REPL].l4dst.tcp.port =
00065 ct->tuple[__DIR_ORIG].l4src.tcp.port;
00066 set_bit(ATTR_SNAT_PORT, ct->set);
00067 }
00068
00069 static void setobjopt_undo_dpat(struct nf_conntrack *ct)
00070 {
00071 ct->dnat.l4min.all = ct->tuple[__DIR_REPL].l4src.tcp.port;
00072 ct->dnat.l4max.all = ct->dnat.l4min.all;
00073 ct->tuple[__DIR_REPL].l4src.tcp.port =
00074 ct->tuple[__DIR_ORIG].l4dst.tcp.port;
00075 set_bit(ATTR_DNAT_PORT, ct->set);
00076 }
00077
00078 static void setobjopt_setup_orig(struct nf_conntrack *ct)
00079 {
00080 __autocomplete(ct, __DIR_ORIG);
00081 }
00082
00083 static void setobjopt_setup_repl(struct nf_conntrack *ct)
00084 {
00085 __autocomplete(ct, __DIR_REPL);
00086 }
00087
00088 static const setobjopt setobjopt_array[__NFCT_SOPT_MAX] = {
00089 [NFCT_SOPT_UNDO_SNAT] = setobjopt_undo_snat,
00090 [NFCT_SOPT_UNDO_DNAT] = setobjopt_undo_dnat,
00091 [NFCT_SOPT_UNDO_SPAT] = setobjopt_undo_spat,
00092 [NFCT_SOPT_UNDO_DPAT] = setobjopt_undo_dpat,
00093 [NFCT_SOPT_SETUP_ORIGINAL] = setobjopt_setup_orig,
00094 [NFCT_SOPT_SETUP_REPLY] = setobjopt_setup_repl,
00095 };
00096
00097 int __setobjopt(struct nf_conntrack *ct, unsigned int option)
00098 {
00099 if (unlikely(option > NFCT_SOPT_MAX))
00100 return -1;
00101
00102 setobjopt_array[option](ct);
00103 return 0;
00104 }
00105
00106 static int getobjopt_is_snat(const struct nf_conntrack *ct)
00107 {
00108 return ((test_bit(ATTR_STATUS, ct->set) ?
00109 ct->status & IPS_SRC_NAT_DONE : 1) &&
00110 ct->tuple[__DIR_REPL].dst.v4 !=
00111 ct->tuple[__DIR_ORIG].src.v4);
00112 }
00113
00114 static int getobjopt_is_dnat(const struct nf_conntrack *ct)
00115 {
00116 return ((test_bit(ATTR_STATUS, ct->set) ?
00117 ct->status & IPS_DST_NAT_DONE : 1) &&
00118 ct->tuple[__DIR_REPL].src.v4 !=
00119 ct->tuple[__DIR_ORIG].dst.v4);
00120 }
00121
00122 static int getobjopt_is_spat(const struct nf_conntrack *ct)
00123 {
00124 return ((test_bit(ATTR_STATUS, ct->set) ?
00125 ct->status & IPS_SRC_NAT_DONE : 1) &&
00126 ct->tuple[__DIR_REPL].l4dst.tcp.port !=
00127 ct->tuple[__DIR_ORIG].l4src.tcp.port);
00128 }
00129
00130 static int getobjopt_is_dpat(const struct nf_conntrack *ct)
00131 {
00132 return ((test_bit(ATTR_STATUS, ct->set) ?
00133 ct->status & IPS_DST_NAT_DONE : 1) &&
00134 ct->tuple[__DIR_REPL].l4src.tcp.port !=
00135 ct->tuple[__DIR_ORIG].l4dst.tcp.port);
00136 }
00137
00138 static const getobjopt getobjopt_array[__NFCT_GOPT_MAX] = {
00139 [NFCT_GOPT_IS_SNAT] = getobjopt_is_snat,
00140 [NFCT_GOPT_IS_DNAT] = getobjopt_is_dnat,
00141 [NFCT_GOPT_IS_SPAT] = getobjopt_is_spat,
00142 [NFCT_GOPT_IS_DPAT] = getobjopt_is_dpat,
00143 };
00144
00145 int __getobjopt(const struct nf_conntrack *ct, unsigned int option)
00146 {
00147 if (unlikely(option > NFCT_GOPT_MAX))
00148 return -1;
00149
00150 return getobjopt_array[option](ct);
00151 }