* Failing to manipulate IP headers
@ 2002-09-20 20:29 Chen Ding
0 siblings, 0 replies; only message in thread
From: Chen Ding @ 2002-09-20 20:29 UTC (permalink / raw)
To: netfilter
[-- 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.
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2002-09-20 20:29 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2002-09-20 20:29 Failing to manipulate IP headers Chen Ding
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox