]> git.pld-linux.org Git - packages/kernel.git/blob - linux-netfilter-newnat-conntrack-nat-udp.patch
- obsolete
[packages/kernel.git] / linux-netfilter-newnat-conntrack-nat-udp.patch
1 Please find below a patch to modify some existing and add some new
2 convenience functions to the newnat core conntrack and nat functions.
3
4 In 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
11 The latter change/function is an implementation of
12 ip_nat_mangle_udp_packet which takes an array of modifications to be
13 made to a packet.  A similar TCP version could/should be made.
14
15 These changes are a prerequisite for the patch I will be submitting
16 subsequently which is a NAT/conntrack helper pair for the Amanda
17 backup protocol.  I will attempt to do that one patch-o-matic compliant.
18
19 If there is anything unacceptable in either patch submissions, I will
20 be most willing to make corrections.
21
22 Thanx,
23 b.
24
25
26 diff -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);
57 diff -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
287 diff -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 -- 
299 Brian J. Murrell
This page took 0.05995 seconds and 3 git commands to generate.