From: netfilter@interlinx.bc.ca
To: netfilter-devel@lists.netfilter.org
Subject: [PATCH] ip_nat_mangle_udp_packet() updated
Date: Thu, 17 Oct 2002 12:39:09 -0400 [thread overview]
Message-ID: <20021017163909.GO344@pc.ilinx> (raw)
[-- Attachment #1.1: Type: text/plain, Size: 389 bytes --]
Hello Harald and all.
Find attached an updated patch for my ip_nat_mangle_udp_packet().
This function no longer gratuitously checkums the mangled UDP packet.
It only calculated a UDP checksum when the pre-mangling checksum is
non-zero. It still pushes the packet up for IP checksum however. I
believe this to be the correct way to do this.
Thanx,
b.
--
Brian J. Murrell
[-- Attachment #1.2: udp_conntrack-2.patch --]
[-- Type: text/plain, Size: 9199 bytes --]
diff -Nur --exclude '*~' --exclude '*.orig' linux-2.4.19-16mdk/include/linux/netfilter_ipv4/ip_nat_helper.h linux-2.4.19-16mdk.tmp/include/linux/netfilter_ipv4/ip_nat_helper.h
--- linux-2.4.19-16mdk/include/linux/netfilter_ipv4/ip_nat_helper.h 2002-10-09 04:52:29.000000000 -0400
+++ linux-2.4.19-16mdk.tmp/include/linux/netfilter_ipv4/ip_nat_helper.h 2002-10-17 11:07:43.000000000 -0400
@@ -50,6 +50,13 @@
unsigned int match_len,
char *rep_buffer,
unsigned int rep_len);
+extern int ip_nat_mangle_udp_packet(struct sk_buff **skb,
+ struct ip_conntrack *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned int match_offset,
+ unsigned int match_len,
+ char *rep_buffer,
+ unsigned int rep_len);
extern int ip_nat_seq_adjust(struct sk_buff *skb,
struct ip_conntrack *ct,
enum ip_conntrack_info ctinfo);
diff -Nur --exclude '*~' --exclude '*.orig' linux-2.4.19-16mdk/net/ipv4/netfilter/ip_nat_helper.c linux-2.4.19-16mdk.tmp/net/ipv4/netfilter/ip_nat_helper.c
--- linux-2.4.19-16mdk/net/ipv4/netfilter/ip_nat_helper.c 2002-09-20 09:44:35.000000000 -0400
+++ linux-2.4.19-16mdk.tmp/net/ipv4/netfilter/ip_nat_helper.c 2002-10-17 11:15:35.000000000 -0400
@@ -8,6 +8,9 @@
* - add support for SACK adjustment
* 14 Mar 2002 Harald Welte <laforge@gnumonks.org>:
* - merge SACK support into newnat API
+ * 16 Aug 2002 Brian J. Murrell <netfilter@interlinx.bc.ca>:
+ * - make ip_nat_resize_packet more generic (TCP and UDP)
+ * - add ip_nat_mangle_udp_packet
*/
#include <linux/version.h>
#include <linux/config.h>
@@ -22,6 +25,7 @@
#include <net/icmp.h>
#include <net/ip.h>
#include <net/tcp.h>
+#include <net/udp.h>
#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_nat_lock)
#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ip_nat_lock)
@@ -51,18 +55,12 @@
int new_size)
{
struct iphdr *iph;
- struct tcphdr *tcph;
- void *data;
int dir;
struct ip_nat_seq *this_way, *other_way;
DEBUGP("ip_nat_resize_packet: old_size = %u, new_size = %u\n",
(*skb)->len, new_size);
- iph = (*skb)->nh.iph;
- tcph = (void *)iph + iph->ihl*4;
- data = (void *)tcph + tcph->doff*4;
-
dir = CTINFO2DIR(ctinfo);
this_way = &ct->nat.info.seq[dir];
@@ -84,37 +82,41 @@
}
iph = (*skb)->nh.iph;
- tcph = (void *)iph + iph->ihl*4;
- data = (void *)tcph + tcph->doff*4;
-
- DEBUGP("ip_nat_resize_packet: Seq_offset before: ");
- DUMP_OFFSET(this_way);
+ if (iph->protocol == IPPROTO_TCP) {
+ struct tcphdr *tcph = (void *)iph + iph->ihl*4;
+ void *data = (void *)tcph + tcph->doff*4;
+
+ DEBUGP("ip_nat_resize_packet: Seq_offset before: ");
+ DUMP_OFFSET(this_way);
+
+ LOCK_BH(&ip_nat_seqofs_lock);
+
+ /* SYN adjust. If it's uninitialized, of this is after last
+ * correction, record it: we don't handle more than one
+ * adjustment in the window, but do deal with common case of a
+ * retransmit */
+ if (this_way->offset_before == this_way->offset_after
+ || before(this_way->correction_pos, ntohl(tcph->seq))) {
+ this_way->correction_pos = ntohl(tcph->seq);
+ this_way->offset_before = this_way->offset_after;
+ this_way->offset_after = (int32_t)
+ this_way->offset_before + new_size -
+ (*skb)->len;
+ }
- LOCK_BH(&ip_nat_seqofs_lock);
+ UNLOCK_BH(&ip_nat_seqofs_lock);
- /* SYN adjust. If it's uninitialized, of this is after last
- * correction, record it: we don't handle more than one
- * adjustment in the window, but do deal with common case of a
- * retransmit */
- if (this_way->offset_before == this_way->offset_after
- || before(this_way->correction_pos, ntohl(tcph->seq))) {
- this_way->correction_pos = ntohl(tcph->seq);
- this_way->offset_before = this_way->offset_after;
- this_way->offset_after = (int32_t)
- this_way->offset_before + new_size - (*skb)->len;
+ DEBUGP("ip_nat_resize_packet: Seq_offset after: ");
+ DUMP_OFFSET(this_way);
}
-
- UNLOCK_BH(&ip_nat_seqofs_lock);
-
- DEBUGP("ip_nat_resize_packet: Seq_offset after: ");
- DUMP_OFFSET(this_way);
return 1;
}
/* Generic function for mangling variable-length address changes inside
- * NATed connections (like the PORT XXX,XXX,XXX,XXX,XXX,XXX command in FTP).
+ * NATed TCP connections (like the PORT XXX,XXX,XXX,XXX,XXX,XXX
+ * command in FTP).
*
* Takes care about all the nasty sequence number changes, checksumming,
* skb enlargement, ...
@@ -174,10 +176,11 @@
tcph = (void *)iph + iph->ihl*4;
data = (void *)tcph + tcph->doff*4;
- /* move post-replacement */
- memmove(data + match_offset + rep_len,
- data + match_offset + match_len,
- (*skb)->tail - (data + match_offset + match_len));
+ if (rep_len != match_len)
+ /* move post-replacement */
+ memmove(data + match_offset + rep_len,
+ data + match_offset + match_len,
+ (*skb)->tail - (data + match_offset + match_len));
/* insert data from buffer */
memcpy(data + match_offset, rep_buffer, rep_len);
@@ -207,6 +210,114 @@
return 1;
}
+
+/* Generic function for mangling variable-length address changes inside
+ * NATed UDP connections (like the CONNECT DATA XXXXX MESG XXXXX INDEX XXXXX
+ * command in the Amanda protocol)
+ *
+ * Takes care about all the nasty sequence number changes, checksumming,
+ * skb enlargement, ...
+ *
+ * XXX - This function could be merged with ip_nat_mangle_tcp_packet which
+ * should be fairly easy to do.
+ */
+int
+ip_nat_mangle_udp_packet(struct sk_buff **skb,
+ struct ip_conntrack *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned int match_offset,
+ unsigned int match_len,
+ char *rep_buffer,
+ unsigned int rep_len)
+{
+ struct iphdr *iph = (*skb)->nh.iph;
+ struct udphdr *udph = (void *)iph + iph->ihl * 4;
+ unsigned char *data;
+ u_int32_t udplen, newlen, newudplen;
+
+ udplen = (*skb)->len - iph->ihl*4;
+ newudplen = udplen - match_len + rep_len;
+ newlen = iph->ihl*4 + newudplen;
+
+ if (newlen > 65535) {
+ if (net_ratelimit())
+ printk("ip_nat_mangle_udp_packet: nat'ed packet "
+ "exceeds maximum packet size\n");
+ return 0;
+ }
+
+ if ((*skb)->len != newlen) {
+ if (!ip_nat_resize_packet(skb, ct, ctinfo, newlen)) {
+ printk("resize_packet failed!!\n");
+ return 0;
+ }
+ }
+
+ /* Alexey says: if a hook changes _data_ ... it can break
+ original packet sitting in tcp queue and this is fatal */
+ if (skb_cloned(*skb)) {
+ struct sk_buff *nskb = skb_copy(*skb, GFP_ATOMIC);
+ if (!nskb) {
+ if (net_ratelimit())
+ printk("Out of memory cloning TCP packet\n");
+ return 0;
+ }
+ /* Rest of kernel will get very unhappy if we pass it
+ a suddenly-orphaned skbuff */
+ if ((*skb)->sk)
+ skb_set_owner_w(nskb, (*skb)->sk);
+ kfree_skb(*skb);
+ *skb = nskb;
+ }
+
+ /* skb may be copied !! */
+ iph = (*skb)->nh.iph;
+ udph = (void *)iph + iph->ihl*4;
+ data = (void *)udph + sizeof(struct udphdr);
+
+ if (rep_len != match_len)
+ /* move post-replacement */
+ memmove(data + match_offset + rep_len,
+ data + match_offset + match_len,
+ (*skb)->tail - (data + match_offset + match_len));
+
+ /* insert data from buffer */
+ memcpy(data + match_offset, rep_buffer, rep_len);
+
+ /* update skb info */
+ if (newlen > (*skb)->len) {
+ DEBUGP("ip_nat_mangle_udp_packet: Extending packet by "
+ "%u to %u bytes\n", newlen - (*skb)->len, newlen);
+ skb_put(*skb, newlen - (*skb)->len);
+ } else {
+ DEBUGP("ip_nat_mangle_udp_packet: Shrinking packet from "
+ "%u to %u bytes\n", (*skb)->len, newlen);
+ skb_trim(*skb, newlen);
+ }
+
+ /* update the length of the UDP and IP packets to the new values*/
+ udph->len = htons((*skb)->len - iph->ihl*4);
+ iph->tot_len = htons(newlen);
+
+ /* fix udp checksum if udp checksum was previously calculated */
+ if ((*skb)->csum != 0) {
+ (*skb)->csum = csum_partial((char *)udph +
+ sizeof(struct udphdr),
+ newudplen - sizeof(struct udphdr),
+ 0);
+
+ udph->check = 0;
+ udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr,
+ newudplen, IPPROTO_UDP,
+ csum_partial((char *)udph,
+ sizeof(struct udphdr),
+ (*skb)->csum));
+ }
+
+ ip_send_check(iph);
+
+ return 1;
+}
/* Adjust one found SACK option including checksum correction */
static void
diff -Nur --exclude '*~' --exclude '*.orig' linux-2.4.19-16mdk/net/ipv4/netfilter/ip_nat_standalone.c linux-2.4.19-16mdk.tmp/net/ipv4/netfilter/ip_nat_standalone.c
--- linux-2.4.19-16mdk/net/ipv4/netfilter/ip_nat_standalone.c 2002-09-20 09:44:36.000000000 -0400
+++ linux-2.4.19-16mdk.tmp/net/ipv4/netfilter/ip_nat_standalone.c 2002-10-17 11:16:00.000000000 -0400
@@ -358,5 +358,6 @@
EXPORT_SYMBOL(ip_nat_helper_unregister);
EXPORT_SYMBOL(ip_nat_cheat_check);
EXPORT_SYMBOL(ip_nat_mangle_tcp_packet);
+EXPORT_SYMBOL(ip_nat_mangle_udp_packet);
EXPORT_SYMBOL(ip_nat_used_tuple);
MODULE_LICENSE("GPL");
Binary files linux-2.4.19-16mdk/net/ipv4/netfilter/.ip_nat_standalone.c.swp and linux-2.4.19-16mdk.tmp/net/ipv4/netfilter/.ip_nat_standalone.c.swp differ
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
next reply other threads:[~2002-10-17 16:39 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2002-10-17 16:39 netfilter [this message]
2002-10-18 11:09 ` [PATCH] tcp window tracking patch with SACK support Jozsef Kadlecsik
2002-10-18 14:48 ` Harald Welte
2002-11-06 11:33 ` Roberto Nibali
2002-11-18 9:48 ` Roberto Nibali
2002-11-18 14:08 ` netfilter
2002-10-18 14:52 ` [PATCH] ip_nat_mangle_udp_packet() updated Harald Welte
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20021017163909.GO344@pc.ilinx \
--to=netfilter@interlinx.bc.ca \
--cc=netfilter-devel@lists.netfilter.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.