2 * Licensed under GNU GPL version 2 Copyright Magnus Boden <mb@ozaba.mine.nu>
5 * Thu 21 Mar 2002 Harald Welte <laforge@gnumonks.org>
8 * This module currently supports DNAT:
9 * iptables -t nat -A PREROUTING -d x.x.x.x -j DNAT --to-dest x.x.x.y
12 * iptables -t nat -A POSTROUTING { -j MASQUERADE , -j SNAT --to-source x.x.x.x }
14 * It has not been tested with
15 * -j SNAT --to-source x.x.x.x-x.x.x.y since I only have one external ip
16 * If you do test this please let me know if it works or not.
20 #include <linux/module.h>
21 #include <linux/netfilter_ipv4.h>
23 #include <linux/udp.h>
25 #include <linux/netfilter.h>
26 #include <linux/netfilter_ipv4/ip_tables.h>
27 #include <linux/netfilter_ipv4/ip_conntrack_helper.h>
28 #include <linux/netfilter_ipv4/ip_conntrack_tftp.h>
29 #include <linux/netfilter_ipv4/ip_nat_helper.h>
30 #include <linux/netfilter_ipv4/ip_nat_rule.h>
32 MODULE_AUTHOR("Magnus Boden <mb@ozaba.mine.nu>");
33 MODULE_DESCRIPTION("Netfilter NAT helper for tftp");
34 MODULE_LICENSE("GPL");
38 static int ports
[MAX_PORTS
];
39 static int ports_c
= 0;
41 MODULE_PARM(ports
,"1-" __MODULE_STRING(MAX_PORTS
) "i");
42 MODULE_PARM_DESC(ports
, "port numbers of tftp servers");
45 #define DEBUGP(format, args...)
47 tftp_nat_help(struct ip_conntrack
*ct
,
48 struct ip_conntrack_expect
*exp
,
49 struct ip_nat_info
*info
,
50 enum ip_conntrack_info ctinfo
,
52 struct sk_buff
**pskb
)
54 int dir
= CTINFO2DIR(ctinfo
);
55 struct iphdr
*iph
= (*pskb
)->nh
.iph
;
56 struct udphdr
*udph
= (void *)iph
+ iph
->ihl
* 4;
57 struct tftphdr
*tftph
= (void *)udph
+ 8;
58 struct ip_conntrack_tuple repl
;
60 if (!((hooknum
== NF_IP_POST_ROUTING
&& dir
== IP_CT_DIR_ORIGINAL
)
61 || (hooknum
== NF_IP_PRE_ROUTING
&& dir
== IP_CT_DIR_REPLY
)))
65 DEBUGP("no conntrack expectation to modify\n");
69 switch (ntohs(tftph
->opcode
)) {
70 /* RRQ and WRQ works the same way */
71 case TFTP_OPCODE_READ
:
72 case TFTP_OPCODE_WRITE
:
73 repl
= ct
->tuplehash
[IP_CT_DIR_REPLY
].tuple
;
75 DUMP_TUPLE(&ct
->tuplehash
[IP_CT_DIR_ORIGINAL
].tuple
);
76 DUMP_TUPLE(&ct
->tuplehash
[IP_CT_DIR_REPLY
].tuple
);
77 DEBUGP("expecting: ");
78 DUMP_TUPLE_RAW(&repl
);
79 DUMP_TUPLE_RAW(&exp
->mask
);
80 ip_conntrack_change_expect(exp
, &repl
);
83 DEBUGP("Unknown opcode\n");
90 tftp_nat_expected(struct sk_buff
**pskb
,
92 struct ip_conntrack
*ct
,
93 struct ip_nat_info
*info
)
95 const struct ip_conntrack
*master
= ct
->master
->expectant
;
96 const struct ip_conntrack_tuple
*orig
=
97 &master
->tuplehash
[IP_CT_DIR_ORIGINAL
].tuple
;
98 struct ip_nat_multi_range mr
;
101 IP_NF_ASSERT(master
);
102 IP_NF_ASSERT(!(info
->initialized
& (1 << HOOK2MANIP(hooknum
))));
105 mr
.range
[0].flags
= IP_NAT_RANGE_MAP_IPS
;
107 if (HOOK2MANIP(hooknum
) == IP_NAT_MANIP_SRC
) {
108 mr
.range
[0].min_ip
= mr
.range
[0].max_ip
= orig
->dst
.ip
;
109 DEBUGP("orig: %u.%u.%u.%u:%u <-> %u.%u.%u.%u:%u "
110 "newsrc: %u.%u.%u.%u\n",
111 NIPQUAD((*pskb
)->nh
.iph
->saddr
), ntohs(udph
->source
),
112 NIPQUAD((*pskb
)->nh
.iph
->daddr
), ntohs(udph
->dest
),
113 NIPQUAD(orig
->dst
.ip
));
115 mr
.range
[0].min_ip
= mr
.range
[0].max_ip
= orig
->src
.ip
;
116 mr
.range
[0].min
.udp
.port
= mr
.range
[0].max
.udp
.port
=
117 orig
->src
.u
.udp
.port
;
118 mr
.range
[0].flags
|= IP_NAT_RANGE_PROTO_SPECIFIED
;
120 DEBUGP("orig: %u.%u.%u.%u:%u <-> %u.%u.%u.%u:%u "
121 "newdst: %u.%u.%u.%u:%u\n",
122 NIPQUAD((*pskb
)->nh
.iph
->saddr
), ntohs(udph
->source
),
123 NIPQUAD((*pskb
)->nh
.iph
->daddr
), ntohs(udph
->dest
),
124 NIPQUAD(orig
->src
.ip
), ntohs(orig
->src
.u
.udp
.port
));
127 return ip_nat_setup_info(ct
,&mr
,hooknum
);
130 static struct ip_nat_helper tftp
[MAX_PORTS
];
131 static char tftp_names
[MAX_PORTS
][10];
133 static void fini(void)
137 for (i
= 0 ; i
< ports_c
; i
++) {
138 DEBUGP("unregistering helper for port %d\n", ports
[i
]);
139 ip_nat_helper_unregister(&tftp
[i
]);
143 static int __init
init(void)
149 ports
[0] = TFTP_PORT
;
151 for (i
= 0 ; (i
< MAX_PORTS
) && ports
[i
] ; i
++) {
152 memset(&tftp
[i
], 0, sizeof(struct ip_nat_helper
));
154 tftp
[i
].tuple
.dst
.protonum
= IPPROTO_UDP
;
155 tftp
[i
].tuple
.src
.u
.udp
.port
= htons(ports
[i
]);
156 tftp
[i
].mask
.dst
.protonum
= 0xFFFF;
157 tftp
[i
].mask
.src
.u
.udp
.port
= 0xFFFF;
158 tftp
[i
].help
= tftp_nat_help
;
160 tftp
[i
].me
= THIS_MODULE
;
161 tftp
[i
].expect
= tftp_nat_expected
;
163 tmpname
= &tftp_names
[i
][0];
164 if (ports
[i
] == TFTP_PORT
)
165 sprintf(tmpname
, "tftp");
167 sprintf(tmpname
, "tftp-%d", i
);
168 tftp
[i
].name
= tmpname
;
170 DEBUGP("ip_nat_tftp: registering for port %d: name %s\n",
171 ports
[i
], tftp
[i
].name
);
172 ret
= ip_nat_helper_register(&tftp
[i
]);
175 printk("ip_nat_tftp: unable to register for port %d\n",