]> git.pld-linux.org Git - packages/kernel.git/blame - linux-netfilter-newnat-conntrack-nat-udp.patch
- replaced by linux-2.4-sfq.patch
[packages/kernel.git] / linux-netfilter-newnat-conntrack-nat-udp.patch
CommitLineData
dcc219c8
JR
1Please find below a patch to modify some existing and add some new
2convenience functions to the newnat core conntrack and nat functions.
3
4In summary:
5
6 - make ip_nat_resize_packet more generic (TCP and UDP)
7 - optimize away the memmove in ip_nat_mangle_tcp_packet when the
8 replacement string is the same size as the match string
9 - add ip_nat_mangle_udp_packet
10
11The latter change/function is an implementation of
12ip_nat_mangle_udp_packet which takes an array of modifications to be
13made to a packet. A similar TCP version could/should be made.
14
15These changes are a prerequisite for the patch I will be submitting
16subsequently which is a NAT/conntrack helper pair for the Amanda
17backup protocol. I will attempt to do that one patch-o-matic compliant.
18
19If there is anything unacceptable in either patch submissions, I will
20be most willing to make corrections.
21
22Thanx,
23b.
24
25
26diff -uNr linux-2.4.18-6mdk-pom-clean/include/linux/netfilter_ipv4/ip_nat_helper.h linux-2.4.18-6mdkuml-48um-pom/include/linux/netfilter_ipv4/ip_nat_helper.h
27--- linux-2.4.18-6mdk-pom-clean/include/linux/netfilter_ipv4/ip_nat_helper.h 2002-08-01 14:21:44.000000000 -0400
28+++ linux-2.4.18-6mdkuml-48um-pom/include/linux/netfilter_ipv4/ip_nat_helper.h 2002-08-15 12:47:38.000000000 -0400
29@@ -39,6 +39,13 @@
30 struct ip_nat_info *info);
31 };
32
33+struct ip_nat_mangle_rep {
34+ unsigned int match_offset;
35+ unsigned int match_len;
36+ char *rep_buffer;
37+ unsigned int rep_len;
38+};
39+
40 extern struct list_head helpers;
41
42 extern int ip_nat_helper_register(struct ip_nat_helper *me);
43@@ -50,6 +57,13 @@
44 unsigned int match_len,
45 char *rep_buffer,
46 unsigned int rep_len);
47+extern int ip_nat_mangle_udp_packet(struct sk_buff **skb,
48+ struct ip_conntrack *ct,
49+ enum ip_conntrack_info ctinfo,
50+ unsigned int match_offset,
51+ unsigned int match_len,
52+ char *rep_buffer,
53+ unsigned int rep_len);
54 extern int ip_nat_seq_adjust(struct sk_buff *skb,
55 struct ip_conntrack *ct,
56 enum ip_conntrack_info ctinfo);
57diff -uNr linux-2.4.18-6mdk-pom-clean/net/ipv4/netfilter/ip_nat_helper.c linux-2.4.18-6mdkuml-48um-pom/net/ipv4/netfilter/ip_nat_helper.c
58--- linux-2.4.18-6mdk-pom-clean/net/ipv4/netfilter/ip_nat_helper.c 2002-07-25 08:56:27.000000000 -0400
59+++ linux-2.4.18-6mdkuml-48um-pom/net/ipv4/netfilter/ip_nat_helper.c 2002-08-16 03:11:33.000000000 -0400
60@@ -8,6 +8,9 @@
61 * - add support for SACK adjustment
62 * 14 Mar 2002 Harald Welte <laforge@gnumonks.org>:
63 * - merge SACK support into newnat API
64+ * 16 Aug 2002 Brian J. Murrell <netfilter@interlinx.bc.ca>:
65+ * - make ip_nat_resize_packet more generic (TCP and UDP)
66+ * - add ip_nat_mangle_udp_packet
67 */
68 #include <linux/version.h>
69 #include <linux/config.h>
70@@ -22,6 +26,7 @@
71 #include <net/icmp.h>
72 #include <net/ip.h>
73 #include <net/tcp.h>
74+#include <net/udp.h>
75
76 #define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_nat_lock)
77 #define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ip_nat_lock)
78@@ -51,18 +56,12 @@
79 int new_size)
80 {
81 struct iphdr *iph;
82- struct tcphdr *tcph;
83- void *data;
84 int dir;
85 struct ip_nat_seq *this_way, *other_way;
86
87 DEBUGP("ip_nat_resize_packet: old_size = %u, new_size = %u\n",
88 (*skb)->len, new_size);
89
90- iph = (*skb)->nh.iph;
91- tcph = (void *)iph + iph->ihl*4;
92- data = (void *)tcph + tcph->doff*4;
93-
94 dir = CTINFO2DIR(ctinfo);
95
96 this_way = &ct->nat.info.seq[dir];
97@@ -84,37 +83,41 @@
98 }
99
100 iph = (*skb)->nh.iph;
101- tcph = (void *)iph + iph->ihl*4;
102- data = (void *)tcph + tcph->doff*4;
103-
104- DEBUGP("ip_nat_resize_packet: Seq_offset before: ");
105- DUMP_OFFSET(this_way);
106+ if (iph->protocol == IPPROTO_TCP) {
107+ struct tcphdr *tcph = (void *)iph + iph->ihl*4;
108+ void *data = (void *)tcph + tcph->doff*4;
109+
110+ DEBUGP("ip_nat_resize_packet: Seq_offset before: ");
111+ DUMP_OFFSET(this_way);
112+
113+ LOCK_BH(&ip_nat_seqofs_lock);
114+
115+ /* SYN adjust. If it's uninitialized, of this is after last
116+ * correction, record it: we don't handle more than one
117+ * adjustment in the window, but do deal with common case of a
118+ * retransmit */
119+ if (this_way->offset_before == this_way->offset_after
120+ || before(this_way->correction_pos, ntohl(tcph->seq))) {
121+ this_way->correction_pos = ntohl(tcph->seq);
122+ this_way->offset_before = this_way->offset_after;
123+ this_way->offset_after = (int32_t)
124+ this_way->offset_before + new_size -
125+ (*skb)->len;
126+ }
127
128- LOCK_BH(&ip_nat_seqofs_lock);
129+ UNLOCK_BH(&ip_nat_seqofs_lock);
130
131- /* SYN adjust. If it's uninitialized, of this is after last
132- * correction, record it: we don't handle more than one
133- * adjustment in the window, but do deal with common case of a
134- * retransmit */
135- if (this_way->offset_before == this_way->offset_after
136- || before(this_way->correction_pos, ntohl(tcph->seq))) {
137- this_way->correction_pos = ntohl(tcph->seq);
138- this_way->offset_before = this_way->offset_after;
139- this_way->offset_after = (int32_t)
140- this_way->offset_before + new_size - (*skb)->len;
141+ DEBUGP("ip_nat_resize_packet: Seq_offset after: ");
142+ DUMP_OFFSET(this_way);
143 }
144-
145- UNLOCK_BH(&ip_nat_seqofs_lock);
146-
147- DEBUGP("ip_nat_resize_packet: Seq_offset after: ");
148- DUMP_OFFSET(this_way);
149
150 return 1;
151 }
152
153
154 /* Generic function for mangling variable-length address changes inside
155- * NATed connections (like the PORT XXX,XXX,XXX,XXX,XXX,XXX command in FTP).
156+ * NATed TCP connections (like the PORT XXX,XXX,XXX,XXX,XXX,XXX
157+ * command in FTP).
158 *
159 * Takes care about all the nasty sequence number changes, checksumming,
160 * skb enlargement, ...
161@@ -174,10 +177,11 @@
162 tcph = (void *)iph + iph->ihl*4;
163 data = (void *)tcph + tcph->doff*4;
164
165- /* move post-replacement */
166- memmove(data + match_offset + rep_len,
167- data + match_offset + match_len,
168- (*skb)->tail - (data + match_offset + match_len));
169+ if (rep_len != match_len)
170+ /* move post-replacement */
171+ memmove(data + match_offset + rep_len,
172+ data + match_offset + match_len,
173+ (*skb)->tail - (data + match_offset + match_len));
174
175 /* insert data from buffer */
176 memcpy(data + match_offset, rep_buffer, rep_len);
177@@ -207,6 +211,109 @@
178
179 return 1;
180 }
181+
182+/* Generic function for mangling variable-length address changes inside
183+ * NATed UDP connections (like the CONNECT DATA XXXXX MESG XXXXX INDEX XXXXX
184+ * command in the Amanda protocol)
185+ *
186+ * Takes care about all the nasty sequence number changes, checksumming,
187+ * skb enlargement, ...
188+ *
189+ * XXX - This function could be merged with ip_nat_mangle_tcp_packet which
190+ * should be fairly easy to do.
191+ */
192+int
193+ip_nat_mangle_udp_packet(struct sk_buff **skb,
194+ struct ip_conntrack *ct,
195+ enum ip_conntrack_info ctinfo,
196+ unsigned int match_offset,
197+ unsigned int match_len,
198+ char *rep_buffer,
199+ unsigned int rep_len)
200+{
201+ struct iphdr *iph = (*skb)->nh.iph;
202+ struct udphdr *udph = (void *)iph + iph->ihl * 4;
203+ unsigned char *data;
204+ u_int32_t udplen, newlen, newudplen;
205+
206+ udplen = (*skb)->len - iph->ihl*4;
207+ newudplen = udplen - match_len + rep_len;
208+ newlen = iph->ihl*4 + newudplen;
209+
210+ if (newlen > 65535) {
211+ if (net_ratelimit())
212+ printk("ip_nat_mangle_udp_packet: nat'ed packet "
213+ "exceeds maximum packet size\n");
214+ return 0;
215+ }
216+
217+ if ((*skb)->len != newlen) {
218+ if (!ip_nat_resize_packet(skb, ct, ctinfo, newlen)) {
219+ printk("resize_packet failed!!\n");
220+ return 0;
221+ }
222+ }
223+
224+ /* Alexey says: if a hook changes _data_ ... it can break
225+ original packet sitting in tcp queue and this is fatal */
226+ if (skb_cloned(*skb)) {
227+ struct sk_buff *nskb = skb_copy(*skb, GFP_ATOMIC);
228+ if (!nskb) {
229+ if (net_ratelimit())
230+ printk("Out of memory cloning TCP packet\n");
231+ return 0;
232+ }
233+ /* Rest of kernel will get very unhappy if we pass it
234+ a suddenly-orphaned skbuff */
235+ if ((*skb)->sk)
236+ skb_set_owner_w(nskb, (*skb)->sk);
237+ kfree_skb(*skb);
238+ *skb = nskb;
239+ }
240+
241+ /* skb may be copied !! */
242+ iph = (*skb)->nh.iph;
243+ udph = (void *)iph + iph->ihl*4;
244+ data = (void *)udph + sizeof(struct udphdr);
245+
246+ if (rep_len != match_len)
247+ /* move post-replacement */
248+ memmove(data + match_offset + rep_len,
249+ data + match_offset + match_len,
250+ (*skb)->tail - (data + match_offset + match_len));
251+
252+ /* insert data from buffer */
253+ memcpy(data + match_offset, rep_buffer, rep_len);
254+
255+ /* update skb info */
256+ if (newlen > (*skb)->len) {
257+ DEBUGP("ip_nat_mangle_udp_packet: Extending packet by "
258+ "%u to %u bytes\n", newlen - (*skb)->len, newlen);
259+ skb_put(*skb, newlen - (*skb)->len);
260+ } else {
261+ DEBUGP("ip_nat_mangle_udp_packet: Shrinking packet from "
262+ "%u to %u bytes\n", (*skb)->len, newlen);
263+ skb_trim(*skb, newlen);
264+ }
265+
266+ /* update the length of the UDP and IP packets to the new values*/
267+ udph->len = htons((*skb)->len - iph->ihl*4);
268+ iph->tot_len = htons(newlen);
269+
270+ /* fix checksum information */
271+ (*skb)->csum = csum_partial((char *)udph + sizeof(struct udphdr),
272+ newudplen - sizeof(struct udphdr), 0);
273+
274+ udph->check = 0;
275+ udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr, newudplen,
276+ IPPROTO_UDP,
277+ csum_partial((char *)udph,
278+ sizeof(struct udphdr),
279+ (*skb)->csum));
280+ ip_send_check(iph);
281+
282+ return 1;
283+}
284
285 /* Adjust one found SACK option including checksum correction */
286 static void
287diff -uNr linux-2.4.18-6mdk-pom-clean/net/ipv4/netfilter/ip_nat_standalone.c linux-2.4.18-6mdkuml-48um-pom/net/ipv4/netfilter/ip_nat_standalone.c
288--- linux-2.4.18-6mdk-pom-clean/net/ipv4/netfilter/ip_nat_standalone.c 2002-08-16 03:56:03.000000000 -0400
289+++ linux-2.4.18-6mdkuml-48um-pom/net/ipv4/netfilter/ip_nat_standalone.c 2002-08-16 03:55:29.000000000 -0400
290@@ -358,5 +358,6 @@
291 EXPORT_SYMBOL(ip_nat_helper_unregister);
292 EXPORT_SYMBOL(ip_nat_cheat_check);
293 EXPORT_SYMBOL(ip_nat_mangle_tcp_packet);
294+EXPORT_SYMBOL(ip_nat_mangle_udp_packet);
295 EXPORT_SYMBOL(ip_nat_used_tuple);
296 MODULE_LICENSE("GPL");
297
298--
299Brian J. Murrell
This page took 2.613119 seconds and 4 git commands to generate.