LinuxQuestions.org
Download your favorite Linux distribution at LQ ISO.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 04-19-2005, 03:31 PM   #1
kannerke
LQ Newbie
 
Registered: Apr 2005
Posts: 9

Rep: Reputation: 0
some help needed with my kernel module


Hello,

I'm programming a kernel module to intercept certain UDP-packets and add some new headers to them. The new headers

must come before the original IP-header. So, after the operation, I want to send a packet like this:

new IP header|new UPD header|overlay header|original IP header|original UDP header|original payload

When I try my code, I get a kernel panic. I can't find what I'm doing wrong here.


Here's a fragment of my code:


....

if ((sk->nh.iph->protocol == IPPROTO_UDP) && (enter_network)) {

print_string("UDP datagram entering overlay network");

/* allocate space for temporary headers */
tmp_iph = kmalloc(sizeof(struct iphdr),GFP_NFS);
tmp_udph = kmalloc(sizeof(struct udphdr),GFP_NFS);

/* copy original IP header */
__memcpy(tmp_iph,sk->nh.iph,sizeof(struct iphdr));


/* copy original UDP header */
__memcpy(tmp_udph,(struct udphdr *)(sk->data +(sk->nh.iph->ihl * 4)),sizeof(struct udphdr));


overlayh = (struct overlayhdr *)skb_push(sk,sizeof(struct overlayhdr));
//complete overlay-header
overlayh->qos0 = qos0;
overlayh->qos1 = qos1;
overlayh->dst = tmp_iph->daddr;
overlayh->dstport = tmp_udph->dest;
overlayh->lsthp = *(unsigned int*)lasthop_ip;

/*expand for new udp header */
udph = (struct udphdr *)skb_push(sk,sizeof(struct udphdr));

//complete udp-header
udph->source = tmp_udph->source;
udph->dest = htons(overlay_port);
udph->len = htons(htons(tmp_iph->tot_len) + sizeof(struct udphdr) + sizeof(struct overlayhdr));
udph->check = 0;
print_string("SFSG 7\n");

/* calculate checksum */
udph->check = csum ((unsigned short *)udph, htons(udph->len) >> 1);


/* expand for new ip header */
iph = (struct iphdr *)skb_push(sk,sizeof(struct iphdr));

//complete new ip-header
iph->ihl = 5;
iph->version = 4;
iph->tos = 0;
iph->tot_len = htons(htons(tmp_iph->tot_len) + sizeof(struct iphdr) + sizeof(struct udphdr) +

sizeof(struct overlayhdr));
iph->id = tmp_iph->id;
iph->frag_off = tmp_iph->frag_off;
iph->ttl = tmp_iph->ttl;
iph->protocol = 17; /* UDP */
iph->check = 0; /* set it to 0 before computing the actual checksum later */
iph->saddr = tmp_iph->saddr;
iph->daddr = *(unsigned int*)overlay_ip;

/* calculate checksum */
iph->check = csum ((unsigned short *)iph, sizeof(struct iphdr) >> 1);


//free used memory
kfree(tmp_iph);
kfree(tmp_udph);

return NF_ACCEPT;

}


/* Initialisation routine */
static int hooks_init() {
/* Fill in our hook structure */
nfho.hook = hook_func; /* Handler function */
nfho.hooknum = NF_IP_PRE_ROUTING; /* First hook for IPv4 */
nfho.pf = PF_INET;
nfho.priority = NF_IP_PRI_FIRST; /* Make our function first */

nf_register_hook(&nfho);

return 0;

};



/* Cleanup routine */
static void hooks_exit() {
nf_unregister_hook(&nfho);
};



module_init(hooks_init);
module_exit(hooks_exit);



enter_network = 1 when the packet needs to be expanded.
sk is a (struct sk_buff *)

I guess I'm doing some things wrong because of the kernel panic I get, but I don't know what I did wrong. I think

it has something to do with the skb_push operation. All help is welcome or when someone has a good example for

doing this kind of operations, please let me know


regards,
Peter
 
Old 04-21-2005, 01:19 AM   #2
mehuljv
Member
 
Registered: Nov 2004
Posts: 72

Rep: Reputation: 15
hi
can u do in this manner ?? because say if you are using ethernet then size of the maximum ip packet will be 1500, now you are adding your own header , then new UDP header and New IP Header. which could be more than 1500 ?? isnt it . plz let me know if i am wrong.
Hey and i want some information regarding hook (nf_register_hook) . if you have any good links then please send me.

Regards
Mehul
 
Old 04-21-2005, 10:39 AM   #3
kannerke
LQ Newbie
 
Registered: Apr 2005
Posts: 9

Original Poster
Rep: Reputation: 0
Hi,

1500 Bytes is indeed the max size of an IP packet.. In that case, my module wont work ( I check the length before I enlarge my packet)

The purpose is to intercept smaller packet, typical used for VoIP of video streaming. Adding those headers makes it possible to make use of my overlay-network. This consists of server, programmed in Java. These servers do measurements ont the netwerk ( suck as RTT and packet loss), and o base of the measurement, I route the intercepted packets on a more intelligent way that just on base of hop count.

on http://www.netfilter.org/documentation/ you can find usefull information about using the hooks.
http://uqconnect.net/~zzoklan/documents/netfilter.html is a paper with was very usefull to learn the basics


For now, I solved the problem by using the pull-opertation on the sk_buff structure and then move the packet through a copy. A finally I overwrite the first bytes with my own headers.

It seems to work, but my packets don4t arrive, probably there's an error in my checksums.


If some know some usefull tricks with sk_buff structures, please, share them :-)

(it is e.g. possible to give the kernel a pointer to a new sk_buff structure. So it uses the new one and forgit about the original. One possiblility is to change the pointers in the sk_buff structure (head, data, tail and end). Don't forget to free the original allocated memory ;-)

other suggestions?
 
Old 04-22-2005, 05:34 AM   #4
mehuljv
Member
 
Registered: Nov 2004
Posts: 72

Rep: Reputation: 15
hi ,
thanks for sending me links, i have some doubts in your code.. plz just go through this...

/* allocate space for temporary headers */
tmp_iph = kmalloc(sizeof(struct iphdr),GFP_NFS);
tmp_udph = kmalloc(sizeof(struct udphdr),GFP_NFS);



whatever size you are allocating for ip header does it includes all the optional fields ?? because optional field size is not included in "struct iphdr " ( see /include/linux/ip.h)


/* copy original IP header */
__memcpy(tmp_iph,sk->nh.iph,sizeof(struct iphdr));

/* copy original UDP header */
__memcpy(tmp_udph,(struct udphdr *)(sk->data +(sk->nh.iph->ihl * 4)),sizeof(struct udphdr));

why are you using nh.iph->ihl * 4 to get the address of udp header ?? i dont know exactly but there could be some allignment problem.. say ip layer might keep some space before udp header. better to use "sk->h" which contains pointer to the udp header.


iph->tot_len = htons(htons(tmp_iph->tot_len) + sizeof(struct iphdr) + sizeof(struct udphdr) + sizeof(struct overlayhdr));

why are you using htons(tmp_iph->tot_len) ?? shouldnt you use in this manner??

iph->tot_len = htons(ntohs(tmp_iph->tot_len) + sizeof(struct iphdr) + sizeof(struct udphdr) + sizeof(struct overlayhdr));

because tmp_iph->tot_len is already in the network format isnt it??

Regards
Mehul
 
Old 04-22-2005, 05:39 AM   #5
mehuljv
Member
 
Registered: Nov 2004
Posts: 72

Rep: Reputation: 15
hi,
go through this for skb stuff....

http://gnumonks.org/ftp/pub/doc/skb-doc.html

Regards
Mehul
 
Old 04-24-2005, 04:09 PM   #6
kannerke
LQ Newbie
 
Registered: Apr 2005
Posts: 9

Original Poster
Rep: Reputation: 0
hi,

the size of struct iphdr is 20 bytes, so I guess that's ok. When there are optional fields, I don't need them.

about htons: I didn't know how I had to use the field and I have checked if the operation is ok and it was: a == htons(htons(a)), but maybe it's better to use ntons? so a == ntons(htons(a))? I'll give it a try.

I allready could solve the problem, but no, I'm having another problem. I solved it this way: I allocated some memory, as big as the packet, I copied it into the memory, I used the skb_put-operation instead of the skb_push. Then I copied the packet into te sk_buff, but higher, so I can overwrite the first bytes of the packet, without loosing the original packet. (the size of the head of the sk_buff was to small to add the 3 new headers + in the head, there are some field used by th sk_buff struct)


The problem I have no, is that the modiefied packet doens't arrive. There are 2 possibilities I guess: 1 ) the checksum is wrong, 2) there's a problem with the way I copy the original headers, so that not al the fields have a good value.


I also have another strange something:

struct overlayhdr {
unsigned char qos0; /* QoS[0] */
unsigned char qos1; /* QoS[1] */
unsigned int dst; /* IP address destination */
unsigned short int dstport; /* port destination */
unsigned int lsthp; /* IP address last hop within overlay network */
}; /* total overlay header length: 12 bytes (=96 bits) */


when I ask the sizeof(struct overlayhdr), I get 16 bytes instead of 12. I checked the length of all components and I normally should get 12 bytes. The only way I can think of for an additionally 4 bytes is a pointer to the struct.


regards,
Peter
 
Old 04-29-2005, 11:20 AM   #7
mehuljv
Member
 
Registered: Nov 2004
Posts: 72

Rep: Reputation: 15
hi peter,

size of the foll. structure must be 16 only... that is due to structure padding ...

struct overlayhdr {
unsigned char qos0; /* QoS[0] */
unsigned char qos1; /* QoS[1] */
unsigned int dst; /* IP address destination */
unsigned short int dstport; /* port destination */
unsigned int lsthp; /* IP address last hop within overlay network */
}; /* total overlay header length: 12 bytes (=96 bits) */

consider when u allocate the structre object it gets store at 1000 th memory location then address of each element will be foll.

&qos0 = 1000
&qos1 = 1001
&dst = 1004
&dstport = 1008
&lshtp = 1012... and hence it ends with 1016 so size will be 16 bytes... this is because address of any element must be at the multiple of its size.

if u want 12 byte address then allocate structure in foll. manner

struct overlayhdr {
unsigned char qos0; /* QoS[0] */
unsigned char qos1; /* QoS[1] */
unsigned short int dstport; /* port destination */
unsigned int dst; /* IP address destination */
unsigned int lsthp; /* IP address last hop within overlay network */
}; /* total overlay header length: 12 bytes (=96 bits) */

thn it should give you 12 bytes.

Regards
Mehul
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Can a kernel module call the function of another kernel module sceadu Programming 3 05-02-2011 02:22 AM
[Error] Kernel Module : No kernel module build environment saman007uk Debian 7 09-09-2006 06:34 PM
kernel module ignorant newbie looking for any one with kernel module knowledge cpoet Slackware 4 11-24-2003 09:37 PM
Xfree prob radeon.o kernel module version is 1.1.1 but version 1.5.0 or newer needed. jimdaworm Slackware 0 10-01-2003 06:27 PM
i810 module needed I_NEED_HELP Linux - Software 3 02-11-2002 04:36 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 09:14 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration