1 /* (C) 2001-2002 Magnus Boden <mb@ozaba.mine.nu>
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 as
5 * published by the Free Software Foundation.
9 * Thu 21 Mar 2002 Harald Welte <laforge@gnumonks.org>
10 * - Port to newnat API
12 * This module currently supports DNAT:
13 * iptables -t nat -A PREROUTING -d x.x.x.x -j DNAT --to-dest x.x.x.y
16 * iptables -t nat -A POSTROUTING { -j MASQUERADE , -j SNAT --to-source x.x.x.x }
18 * It has not been tested with
19 * -j SNAT --to-source x.x.x.x-x.x.x.y since I only have one external ip
20 * If you do test this please let me know if it works or not.
24 #include <linux/module.h>
25 #include <linux/netfilter_ipv4.h>
27 #include <linux/udp.h>
29 #include <linux/netfilter.h>
30 #include <linux/netfilter_ipv4/ip_tables.h>
31 #include <linux/netfilter_ipv4/ip_conntrack_helper.h>
32 #include <linux/netfilter_ipv4/ip_conntrack_tftp.h>
33 #include <linux/netfilter_ipv4/ip_nat_helper.h>
34 #include <linux/netfilter_ipv4/ip_nat_rule.h>
35 #include <linux/moduleparam.h>
37 MODULE_AUTHOR("Magnus Boden <mb@ozaba.mine.nu>");
38 MODULE_DESCRIPTION("tftp NAT helper");
39 MODULE_LICENSE("GPL");
43 static int ports
[MAX_PORTS
];
44 static int ports_c
= 0;
45 module_param_array(ports
, int, ports_c
, 0400);
46 MODULE_PARM_DESC(ports
, "port numbers of tftp servers");
49 #define DEBUGP(format, args...) printk("%s:%s:" format, \
50 __FILE__, __FUNCTION__ , ## args)
52 #define DEBUGP(format, args...)
55 tftp_nat_help(struct ip_conntrack
*ct
,
56 struct ip_conntrack_expect
*exp
,
57 struct ip_nat_info
*info
,
58 enum ip_conntrack_info ctinfo
,
60 struct sk_buff
**pskb
)
62 int dir
= CTINFO2DIR(ctinfo
);
63 struct tftphdr _tftph
, *tfh
;
64 struct ip_conntrack_tuple repl
;
66 if (!((hooknum
== NF_IP_POST_ROUTING
&& dir
== IP_CT_DIR_ORIGINAL
)
67 || (hooknum
== NF_IP_PRE_ROUTING
&& dir
== IP_CT_DIR_REPLY
)))
71 DEBUGP("no conntrack expectation to modify\n");
75 tfh
= skb_header_pointer(*pskb
,
76 (*pskb
)->nh
.iph
->ihl
*4+sizeof(struct udphdr
),
77 sizeof(_tftph
), &_tftph
);
81 switch (ntohs(tfh
->opcode
)) {
82 /* RRQ and WRQ works the same way */
83 case TFTP_OPCODE_READ
:
84 case TFTP_OPCODE_WRITE
:
85 repl
= ct
->tuplehash
[IP_CT_DIR_REPLY
].tuple
;
87 DUMP_TUPLE(&ct
->tuplehash
[IP_CT_DIR_ORIGINAL
].tuple
);
88 DUMP_TUPLE(&ct
->tuplehash
[IP_CT_DIR_REPLY
].tuple
);
89 DEBUGP("expecting: ");
91 DUMP_TUPLE(&exp
->mask
);
92 ip_conntrack_change_expect(exp
, &repl
);
95 DEBUGP("Unknown opcode\n");
102 tftp_nat_expected(struct sk_buff
**pskb
,
103 unsigned int hooknum
,
104 struct ip_conntrack
*ct
,
105 struct ip_nat_info
*info
)
107 const struct ip_conntrack
*master
= ct
->master
->expectant
;
108 const struct ip_conntrack_tuple
*orig
=
109 &master
->tuplehash
[IP_CT_DIR_ORIGINAL
].tuple
;
110 struct ip_nat_multi_range mr
;
112 const struct ip_conntrack_tuple
*repl
=
113 &master
->tuplehash
[IP_CT_DIR_REPLY
].tuple
;
114 struct udphdr _udph
, *uh
;
116 uh
= skb_header_pointer(*pskb
,
117 (*pskb
)->nh
.iph
->ihl
*4,
118 sizeof(_udph
), &_udph
);
124 IP_NF_ASSERT(master
);
125 IP_NF_ASSERT(!(info
->initialized
& (1 << HOOK2MANIP(hooknum
))));
128 mr
.range
[0].flags
= IP_NAT_RANGE_MAP_IPS
;
130 if (HOOK2MANIP(hooknum
) == IP_NAT_MANIP_SRC
) {
131 mr
.range
[0].min_ip
= mr
.range
[0].max_ip
= orig
->dst
.ip
;
132 DEBUGP("orig: %u.%u.%u.%u:%u <-> %u.%u.%u.%u:%u "
133 "newsrc: %u.%u.%u.%u\n",
134 NIPQUAD((*pskb
)->nh
.iph
->saddr
), ntohs(uh
->source
),
135 NIPQUAD((*pskb
)->nh
.iph
->daddr
), ntohs(uh
->dest
),
136 NIPQUAD(orig
->dst
.ip
));
138 mr
.range
[0].min_ip
= mr
.range
[0].max_ip
= orig
->src
.ip
;
139 mr
.range
[0].min
.udp
.port
= mr
.range
[0].max
.udp
.port
=
140 orig
->src
.u
.udp
.port
;
141 mr
.range
[0].flags
|= IP_NAT_RANGE_PROTO_SPECIFIED
;
143 DEBUGP("orig: %u.%u.%u.%u:%u <-> %u.%u.%u.%u:%u "
144 "newdst: %u.%u.%u.%u:%u\n",
145 NIPQUAD((*pskb
)->nh
.iph
->saddr
), ntohs(uh
->source
),
146 NIPQUAD((*pskb
)->nh
.iph
->daddr
), ntohs(uh
->dest
),
147 NIPQUAD(orig
->src
.ip
), ntohs(orig
->src
.u
.udp
.port
));
150 return ip_nat_setup_info(ct
,&mr
,hooknum
);
153 static struct ip_nat_helper tftp
[MAX_PORTS
];
154 static char tftp_names
[MAX_PORTS
][10];
156 static void fini(void)
160 for (i
= 0 ; i
< ports_c
; i
++) {
161 DEBUGP("unregistering helper for port %d\n", ports
[i
]);
162 ip_nat_helper_unregister(&tftp
[i
]);
166 static int __init
init(void)
172 ports
[ports_c
++] = TFTP_PORT
;
174 for (i
= 0; i
< ports_c
; i
++) {
175 memset(&tftp
[i
], 0, sizeof(struct ip_nat_helper
));
177 tftp
[i
].tuple
.dst
.protonum
= IPPROTO_UDP
;
178 tftp
[i
].tuple
.src
.u
.udp
.port
= htons(ports
[i
]);
179 tftp
[i
].mask
.dst
.protonum
= 0xFFFF;
180 tftp
[i
].mask
.src
.u
.udp
.port
= 0xFFFF;
181 tftp
[i
].help
= tftp_nat_help
;
183 tftp
[i
].me
= THIS_MODULE
;
184 tftp
[i
].expect
= tftp_nat_expected
;
186 tmpname
= &tftp_names
[i
][0];
187 if (ports
[i
] == TFTP_PORT
)
188 sprintf(tmpname
, "tftp");
190 sprintf(tmpname
, "tftp-%d", i
);
191 tftp
[i
].name
= tmpname
;
193 DEBUGP("ip_nat_tftp: registering for port %d: name %s\n",
194 ports
[i
], tftp
[i
].name
);
195 ret
= ip_nat_helper_register(&tftp
[i
]);
198 printk("ip_nat_tftp: unable to register for port %d\n",