From: "Chen Ding" <ding@packetlink.com>
To: netfilter@lists.netfilter.org
Subject: Failing to manipulate IP headers
Date: Fri, 20 Sep 2002 15:29:45 -0500 [thread overview]
Message-ID: <003801c260e4$75e77bf0$6501a8c0@JCC> (raw)
[-- Attachment #1.1: Type: text/plain, Size: 1207 bytes --]
All,
I am trying to develop a customized NAT app based on netfilter framework. I have:
a. Created a module
b. Initialized and registered with netfilter
c. Got sk_buff from the core
Currently, the program is very simple: just changes the receiver IP address (pre-routing)
and sender IP address (post-routing), and then forward the packets.
Everything worked fine except that after the packets forwarded to the destination, the
reading program on the destination machine reported reading error (-1), and errno 11
(don't know the reason).
After changed the IP address, I did recalculated the checksum, as follows (copied
from ip_nat_core.c):
saddr = <the address to be changed to>;
iph->check = ip_nat_cheat_check(~iph->saddr, saddr, iph->check);
iph->saddr = saddr;
I did rechecked the checksum and it appeared to be good.
Having searched answers from the Internet and digged the code without results, I hope
someone here can help me out. I guess I must have messed up the packets.
For your information, I have attached the tiny source code at the end of this email.
Your help is most appreciated!!!
Chen Ding
[-- Attachment #1.2: Type: text/html, Size: 3120 bytes --]
[-- Attachment #2: hello.c --]
[-- Type: application/octet-stream, Size: 5860 bytes --]
/* hello.c
* Copyright (C) 1998 by Ori Pomerantz
*
* "Hello, world" - the kernel module version.
*/
/* The necessary header files */
/* Standard in kernel modules */
#include <linux/config.h>
#include <linux/skbuff.h>
#include <linux/kmod.h>
#include <linux/vmalloc.h>
#include <linux/netdevice.h>
#include <linux/module.h>
#include <linux/tcp.h>
#include <linux/udp.h>
#include <linux/icmp.h>
#include <net/ip.h>
#include <asm/uaccess.h>
#include <asm/semaphore.h>
#include <asm/checksum.h>
#include <linux/proc_fs.h>
#include <linux/kernel.h> /* We're doing kernel work */
#include <linux/module.h> /* Specifically, a module */
#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_nat_lock)
#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ip_nat_lock)
#include <linux/netfilter_ipv4/ip_nat.h>
#include <linux/netfilter_ipv4/ip_nat_rule.h>
#include <linux/netfilter_ipv4/ip_nat_protocol.h>
#include <linux/netfilter_ipv4/ip_nat_core.h>
#include <linux/netfilter_ipv4/ip_nat_helper.h>
#include <linux/netfilter_ipv4/ip_tables.h>
#include <linux/netfilter_ipv4/ip_conntrack_core.h>
#include <linux/netfilter_ipv4/listhelp.h>
#include <linux/netfilter.h>
/* Deal with CONFIG_MODVERSIONS */
#if CONFIG_MODVERSIONS==1
#define MODVERSIONS
#include <linux/modversions.h>
#endif
u_int16_t
ip_nat_cheat_check(u_int32_t oldvalinv, u_int32_t newval, u_int16_t oldcheck)
{
u_int32_t diffs[] = { oldvalinv, newval };
return csum_fold(csum_partial((char *)diffs, sizeof(diffs),
oldcheck^0xFFFF));
}
static unsigned int addr192_168_1_17 = 0x1101a8c0;
static unsigned int addr192_168_1_81 = 0x5101a8c0;
static unsigned int addr10_10_10_1 = 0x010a0a0a;
static unsigned int addr10_10_10_3 = 0x030a0a0a;
static unsigned int
ip_nat_fn(unsigned int hooknum,
struct sk_buff **pskb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
/*
* The pre-routing function
*/
unsigned int saddr;
unsigned int daddr;
struct iphdr *iph;
struct udphdr *udphdr;
iph = (*pskb)->nh.iph;
udphdr = (struct udphdr*)((u_int32_t *)iph + iph->ihl);
if (iph->protocol == 17)
{
/*
* It is UDP
*/
saddr = iph->saddr;
daddr = iph->daddr;
if (saddr == addr192_168_1_17 &&
daddr == addr192_168_1_81)
{
/* Found the match. Change daddr to 10.10.10.3 */
daddr = addr10_10_10_3; /* 10.10.10.3 */
iph->check = ip_nat_cheat_check(~iph->daddr, daddr, iph->check);
iph->daddr = daddr;
(*pskb)->nfcache |= NFC_UNKNOWN; /* not sure whether should do this */
(*pskb)->nfcache |= NFC_ALTERED;
(*pskb)->nfcache |= NFC_IP_DST;
}
}
return NF_ACCEPT;
}
static unsigned int
ip_nat_out(unsigned int hooknum,
struct sk_buff **pskb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
/*
* The post-routing function
*/
unsigned int saddr;
unsigned int daddr;
struct iphdr *iph;
struct udphdr *udphdr;
iph = (*pskb)->nh.iph;
udphdr = (struct udphdr*)((u_int32_t *)iph + iph->ihl);
if (iph->protocol == 17)
{
/*
* It is UDP
*/
saddr = iph->saddr;
daddr = iph->daddr;
if (saddr == addr192_168_1_17 && daddr == addr10_10_10_3)
{
/* Change the source address to 10.10.10.1 */
saddr = addr10_10_10_1;
iph->check = ip_nat_cheat_check(~iph->saddr, saddr, iph->check);
iph->saddr = saddr;
(*pskb)->nfcache |= NFC_UNKNOWN; /* again, not sure whether should do it */
(*pskb)->nfcache |= NFC_ALTERED;
(*pskb)->nfcache |= NFC_IP_SRC;
}
}
return NF_ACCEPT;
}
static unsigned int
ip_nat_local_fn(unsigned int hooknum,
struct sk_buff **pskb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
return NF_ACCEPT;
}
// = { { NULL, NULL }, ip_nat_fn, PF_INET, NF_IP_PRE_ROUTING, NF_IP_PRI_NAT_DST };
/* Before packet filtering, change destination */
static struct nf_hook_ops ip_nat_in_ops
= { { NULL, NULL }, ip_nat_fn, PF_INET, NF_IP_PRE_ROUTING, NF_IP_PRI_NAT_DST-1};
/* After packet filtering, change source */
static struct nf_hook_ops ip_nat_out_ops
= { { NULL, NULL }, ip_nat_out, PF_INET, NF_IP_POST_ROUTING, NF_IP_PRI_NAT_SRC-1};
/* Before packet filtering, change destination */
static struct nf_hook_ops ip_nat_local_out_ops
= { { NULL, NULL }, ip_nat_local_fn, PF_INET, NF_IP_LOCAL_OUT, NF_IP_PRI_NAT_DST-1 };
/* Initialize the module */
int init_module()
{
/* If we return a non zero value, it means that
* init_module failed and the kernel module
* can't be loaded */
int ret = 0;
printk("Hello, world - this is the little netfilter module\n");
ret = nf_register_hook(&ip_nat_in_ops);
if (ret < 0)
{
printk("ip_nat_init: can't register in hook.\n");
// MUST_BE_READ_WRITE_UNLOCKED(&ip_nat_lock);
return ret;
}
ret = nf_register_hook(&ip_nat_out_ops);
if (ret < 0)
{
printk("ip_nat_init: can't register out hook.\n");
return ret;
}
ret = nf_register_hook(&ip_nat_local_out_ops);
if (ret < 0)
{
printk("ip_nat_init: can't register local out hook.\n");
return ret;
}
return ret;
return 0;
}
/* Cleanup - undid whatever init_module did */
void cleanup_module()
{
printk("Short is the life of a kernel module\n");
nf_unregister_hook(&ip_nat_in_ops);
nf_unregister_hook(&ip_nat_out_ops);
nf_unregister_hook(&ip_nat_local_out_ops);
}
[-- Attachment #3: Makefile --]
[-- Type: application/octet-stream, Size: 373 bytes --]
# Makefile for a basic kernel module
CC=gcc
MODCFLAGS := -I/usr/src/linux/include -Wall -DMODULE -D__KERNEL__ -DLINUX
hello.o: hello.c /usr/include/linux/version.h
$(CC) $(MODCFLAGS) -c hello.c
# echo insmod hello.o to turn it on
# echo rmmod hello to turn if off
# echo
# echo X and kernel programming do not mix.
# echo Do the insmod and rmmod from outside X.
reply other threads:[~2002-09-20 20:29 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
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='003801c260e4$75e77bf0$6501a8c0@JCC' \
--to=ding@packetlink.com \
--cc=netfilter@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox