00001
00002
00003
00004
00005
00006
00007
#include <linux/skbuff.h>
00008
#include <linux/in.h>
00009
#include <linux/ip.h>
00010
#include <linux/icmp.h>
00011
#include <linux/udp.h>
00012
#include <linux/netfilter_ipv4.h>
00013
#include <linux/netdevice.h>
00014
#include <linux/inetdevice.h>
00015
#include <linux/proc_fs.h>
00016
#include <linux/version.h>
00017
#include <linux/module.h>
00018
#include <net/route.h>
00019
00020 #define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_conntrack_lock)
00021 #define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ip_conntrack_lock)
00022
00023
#include <linux/netfilter_ipv4/ip_conntrack.h>
00024
#include <linux/netfilter_ipv4/ip_conntrack_core.h>
00025
#include <linux/netfilter_ipv4/ip_nat.h>
00026
#include <linux/netfilter_ipv4/ip_nat_core.h>
00027
#include <linux/netfilter_ipv4/listhelp.h>
00028
00029
#if 0
00030
#define DEBUGP printk
00031
#else
00032 #define DEBUGP(format, args...)
00033
#endif
00034
00035
unsigned int
00036 do_masquerade(
struct sk_buff **pskb,
const struct net_device *dev)
00037 {
00038
struct iphdr *iph = (*pskb)->nh.iph;
00039
struct ip_nat_info *info;
00040
enum ip_conntrack_info ctinfo;
00041
struct ip_conntrack *ct;
00042
unsigned int ret;
00043
00044
00045
if (iph->protocol !=
IPPROTO_ICMP
00046 && iph->protocol !=
IPPROTO_TCP
00047 && iph->protocol !=
IPPROTO_UDP)
00048
return NF_DROP;
00049
00050
00051
00052 ret =
ip_conntrack_in(
NF_IP_POST_ROUTING, pskb, dev, NULL, NULL);
00053
if (ret !=
NF_ACCEPT) {
00054
DEBUGP(
"ip_conntrack_in returned %u.\n", ret);
00055
return ret;
00056 }
00057
00058 ct =
ip_conntrack_get(*pskb, &ctinfo);
00059
00060
if (!ct) {
00061
DEBUGP(
"ip_conntrack_in set to invalid conntrack.\n");
00062
return NF_DROP;
00063 }
00064
00065 info = &ct->nat.info;
00066
00067 WRITE_LOCK(&ip_nat_lock);
00068
00069
if (!info->initialized) {
00070 u_int32_t newsrc;
00071
struct rtable *rt;
00072
struct ip_nat_multi_range range;
00073
00074
00075
00076
if (
ip_route_output(&rt, iph->daddr, 0, 0, 0) != 0) {
00077
DEBUGP(
"ipnat_rule_masquerade: Can't reroute.\n");
00078
return NF_DROP;
00079 }
00080 newsrc =
inet_select_addr(rt->u.dst.dev, rt->rt_gateway,
00081 RT_SCOPE_UNIVERSE);
00082
ip_rt_put(rt);
00083 range = ((
struct ip_nat_multi_range)
00084 { 1,
00085 {{IP_NAT_RANGE_MAP_IPS|IP_NAT_RANGE_PROTO_SPECIFIED,
00086 newsrc, newsrc,
00087 { htons(61000) }, { htons(65095) } } } });
00088
00089 ret =
ip_nat_setup_info(ct, &range,
NF_IP_POST_ROUTING);
00090
if (ret !=
NF_ACCEPT) {
00091 WRITE_UNLOCK(&ip_nat_lock);
00092
return ret;
00093 }
00094
00095
place_in_hashes(ct, info);
00096 info->initialized = 1;
00097 }
else
00098
DEBUGP(
"Masquerading already done on this conn.\n");
00099 WRITE_UNLOCK(&ip_nat_lock);
00100
00101
return do_bindings(ct, ctinfo, info,
NF_IP_POST_ROUTING, pskb);
00102 }
00103
00104
void
00105 check_for_masq_error(
struct sk_buff *skb)
00106 {
00107
enum ip_conntrack_info ctinfo;
00108
struct ip_conntrack *ct;
00109
00110 ct =
ip_conntrack_get(skb, &ctinfo);
00111
00112
00113
IP_NF_ASSERT(ct);
00114
if (ctinfo == IP_CT_RELATED) {
00115
icmp_reply_translation(skb, ct,
NF_IP_PRE_ROUTING,
00116 CTINFO2DIR(ctinfo));
00117
icmp_reply_translation(skb, ct,
NF_IP_POST_ROUTING,
00118 CTINFO2DIR(ctinfo));
00119 }
00120 }
00121
00122
unsigned int
00123 check_for_demasq(
struct sk_buff **pskb)
00124 {
00125
struct ip_conntrack_tuple tuple;
00126
struct iphdr *iph = (*pskb)->nh.iph;
00127
struct ip_conntrack_protocol *protocol;
00128
struct ip_conntrack_tuple_hash *h;
00129
enum ip_conntrack_info ctinfo;
00130
struct ip_conntrack *ct;
00131
int ret;
00132
00133 protocol =
ip_ct_find_proto(iph->protocol);
00134
00135
00136
00137
00138
switch (iph->protocol) {
00139
case IPPROTO_ICMP:
00140
00141 ct =
icmp_error_track(*pskb, &ctinfo,
NF_IP_PRE_ROUTING);
00142
if (ct) {
00143
00144
00145
00146
00147
if (CTINFO2DIR(ctinfo) == IP_CT_DIR_REPLY) {
00148
icmp_reply_translation(*pskb, ct,
00149
NF_IP_PRE_ROUTING,
00150 CTINFO2DIR(ctinfo));
00151
icmp_reply_translation(*pskb, ct,
00152
NF_IP_POST_ROUTING,
00153 CTINFO2DIR(ctinfo));
00154 }
00155
return NF_ACCEPT;
00156 }
00157
00158
case IPPROTO_TCP:
00159
case IPPROTO_UDP:
00160
IP_NF_ASSERT(((*pskb)->nh.iph->frag_off & htons(
IP_OFFSET)) == 0);
00161
00162
if (!
get_tuple(iph, (*pskb)->len, &tuple, protocol)) {
00163
if (
net_ratelimit())
00164 printk(
"ip_fw_compat_masq: Can't get tuple\n");
00165
return NF_ACCEPT;
00166 }
00167
break;
00168
00169
default:
00170
00171
return NF_ACCEPT;
00172 }
00173 h =
ip_conntrack_find_get(&tuple, NULL);
00174
00175
00176
if (h && DIRECTION(h) == 1) {
00177 ret =
ip_conntrack_in(
NF_IP_PRE_ROUTING, pskb,
00178 NULL, NULL, NULL);
00179
00180
00181 nf_conntrack_put(&h->ctrack->infos[0]);
00182
if (ret ==
NF_ACCEPT) {
00183
struct ip_conntrack *ct;
00184 ct =
ip_conntrack_get(*pskb, &ctinfo);
00185
00186
if (ct) {
00187
struct ip_nat_info *info = &ct->nat.info;
00188
00189
do_bindings(ct, ctinfo, info,
00190
NF_IP_PRE_ROUTING,
00191 pskb);
00192 }
else
00193
if (
net_ratelimit())
00194 printk(
"ip_fw_compat_masq: conntrack"
00195
" didn't like\n");
00196 }
00197 }
else {
00198
if (h)
00199
00200 nf_conntrack_put(&h->ctrack->infos[0]);
00201 ret =
NF_ACCEPT;
00202 }
00203
00204
return ret;
00205 }
00206
00207 int ip_fw_masq_timeouts(
void *user,
int len)
00208 {
00209 printk(
"Sorry: masquerading timeouts set 5DAYS/2MINS/60SECS\n");
00210
return 0;
00211 }
00212
00213 static const char *
masq_proto_name(u_int16_t protonum)
00214 {
00215
switch (protonum) {
00216
case IPPROTO_TCP:
return "TCP";
00217
case IPPROTO_UDP:
return "UDP";
00218
case IPPROTO_ICMP:
return "ICMP";
00219
default:
return "MORE-CAFFIENE-FOR-RUSTY";
00220 }
00221 }
00222
00223
static unsigned int
00224 print_masq(
char *buffer,
const struct ip_conntrack *conntrack)
00225 {
00226
char temp[129];
00227
00228
00229
00230
00231 sprintf(temp,
"%s %08X:%04X %08X:%04X %04X %08X %6d %6d %7lu",
00232
masq_proto_name(conntrack->tuplehash[0].tuple.dst.protonum),
00233 ntohl(conntrack->tuplehash[0].tuple.src.ip),
00234 ntohs(conntrack->tuplehash[0].tuple.src.u.all),
00235 ntohl(conntrack->tuplehash[0].tuple.dst.ip),
00236 ntohs(conntrack->tuplehash[0].tuple.dst.u.all),
00237 ntohs(conntrack->tuplehash[1].tuple.dst.u.all),
00238
00239 0, 0, 0,
00240 conntrack->timeout.expires - jiffies);
00241
00242
return sprintf(buffer,
"%-127s\n", temp);
00243 }
00244
00245
00246
static int
00247 masq_iterate(
const struct ip_conntrack_tuple_hash *hash,
00248
char *buffer, off_t offset, off_t *upto,
00249
unsigned int *len,
unsigned int maxlen)
00250 {
00251
unsigned int newlen;
00252
00253
IP_NF_ASSERT(hash->ctrack);
00254
00255
00256
if (DIRECTION(hash))
00257
return 0;
00258
00259
if ((*upto)++ < offset)
00260
return 0;
00261
00262 newlen =
print_masq(buffer + *len, hash->ctrack);
00263
if (*len + newlen > maxlen)
00264
return 1;
00265
else *len += newlen;
00266
00267
return 0;
00268 }
00269
00270
00271
static int
00272 masq_procinfo(
char *buffer,
char **start, off_t offset,
int length)
00273 {
00274
unsigned int i;
00275
int len = 0;
00276 off_t upto = 1;
00277
00278
00279
if (offset == 0) {
00280
char temp[128];
00281
00282 sprintf(temp,
00283
"Prc FromIP FPrt ToIP TPrt Masq Init-seq Delta PDelta Expires (free=0,0,0)");
00284 len = sprintf(buffer,
"%-127s\n", temp);
00285 offset = 1;
00286 }
00287
00288 READ_LOCK(&ip_conntrack_lock);
00289
00290
for (i = 0; i <
ip_conntrack_htable_size; i++) {
00291
if (LIST_FIND(&
ip_conntrack_hash[i],
masq_iterate,
00292
struct ip_conntrack_tuple_hash *,
00293 buffer, offset, &upto, &len, length))
00294
break;
00295 }
00296 READ_UNLOCK(&ip_conntrack_lock);
00297
00298
00299 *start = (
char *)((
unsigned int)upto - offset);
00300
return len;
00301 }
00302
00303 int __init
masq_init(
void)
00304 {
00305
int ret;
00306
struct proc_dir_entry *proc;
00307
00308 ret =
ip_conntrack_init();
00309
if (ret == 0) {
00310 ret =
ip_nat_init();
00311
if (ret == 0) {
00312 proc = proc_net_create(
"ip_masquerade",
00313 0,
masq_procinfo);
00314
if (proc)
00315 proc->owner = THIS_MODULE;
00316
else {
00317
ip_nat_cleanup();
00318
ip_conntrack_cleanup();
00319 ret = -ENOMEM;
00320 }
00321 }
else
00322
ip_conntrack_cleanup();
00323 }
00324
00325
return ret;
00326 }
00327
00328 void masq_cleanup(
void)
00329 {
00330
ip_nat_cleanup();
00331
ip_conntrack_cleanup();
00332 proc_net_remove(
"ip_masquerade");
00333 }