kernel crashed after sending a packet with my own wrapping iphdr

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi!

I'm using Fedoro Core 4 with the default kernel version of 2.6.11-1.

I simply want to wrap certain ip packets with a new iphdr, and then
send it out. So, I decided to plug a hook function at
NF_IP_POST_ROUTING with the priority of NF_IP_PRI_FILTER-1. What I did
in the hook function is :
1. check if it is a ip packet
1. 'copy_and_expand' the skbuff
2. 'skb_set_owner_w' for the new skbuff
3. move the older iphdr and data to the new skbuff, of couse I moved
two copy of the iphdr
4. 'kfree' the older skbuff and set the pointer once pointing to it to
the new skbuff
5. set the members of new iphdr and do 'ip_send_check' for it
6. 'ip_select_ident' for the new skbuff
7. return NF_ACCEPT

Then I'm confused what's wrong?

I've been trapped by these error for over a week and I'll be really
thankful if you could point out some possible reseasons for my stupid
error.

Here is the main code: (The kernel crashed on the time of a ping
command, I can't get those error msg logged even when I killed klogd
and 'cat /proc/kmsg > logfile', so what I can show you of the error
msg is the function stack printed on the screen telling ' delay_pmtmr
... __delay... panic... die... do_page_fault... recalc_task_prio...
__delay... qdisc_restart... do_page_fault... error_code...
force_sog_specific ... ')

/* hook option */
static struct nf_hook_ops kernel_ops[] = {
    {
        .hook = kernel_hook_out,
#ifdef KERNEL26
        .owner = THIS_MODULE,
#endif
        .pf = PF_INET,
        .hooknum = NF_IP_POST_ROUTING,
        .priority = NF_IP_PRI_FILTER-1,
    },
};

static unsigned int
kernel_hook_out(unsigned int hooknum,
	   struct sk_buff **skb,
	   const struct net_device *in,
	   const struct net_device *out, int (*okfn) (struct sk_buff *))
{
	struct iphdr *iph = (*skb)->nh.iph;
	if (iph == NULL) {
		return NF_ACCEPT;
	}

        ip_pkt_encapsulate(*skb);
	return NF_ACCEPT;
}

int ip_pkt_encapsulate(struct sk_buff *skb)
{
	struct iphdr *iph;        /* old iph and new outer iph */
	struct iphdr *iiph;       /* new inner iph */
	struct sk_buff *nskb;  /* new socket buffer */
	
	iph = skb->nh.iph;

	nskb = skb_copy_expand(skb, skb_headroom(skb),
			       skb_tailroom(skb) +
			       (iph->ihl << 2), GFP_ATOMIC);

	if (nskb == NULL) {
		kfree_skb(skb);
		return -1;
	}

	/* Set old owner */
	if (skb->sk != NULL)
		skb_set_owner_w(nskb, skb->sk);
	
	skb_put(nskb, iph->ihl << 2);

	/* Move the IP header, and make a copy at the front of the data part */
	memcpy(nskb->data, skb->data, (iph->ihl << 2));
	memcpy(nskb->data + (iph->ihl << 2), skb->data, (iph->ihl << 2));
	/* Move the data */
	memcpy(nskb->data + 2 * (iph->ihl << 2),
	       skb->data + (iph->ihl << 2), skb->len - (iph->ihl << 2));

	kfree_skb(skb);
	skb = nskb;

	/* Update pointers */
	iph = skb->nh.iph = (struct iphdr *)(skb->data);
	iiph = (struct iphdr *)(skb->data + (iph->ihl << 2));
	ip_send_check(iiph);
	
	iph->tot_len =
	    htons(ntohs(iph->tot_len) + ((iph->ihl) << 2) );
	iph->protocol = 17;
	ip_send_check(iph);

	if (skb->nh.iph->id == 0) {
		ip_select_ident(skb->nh.iph, skb->dst, NULL);
		printk(KERN_EMERG "skb->nh.iph->id == 0\n");
	}
	return 0;
}

Thanks again for read over these code!

Gu, Xinxing



[Index of Archives]     [Linux Netfilter Development]     [Linux Kernel Networking Development]     [Netem]     [Berkeley Packet Filter]     [Linux Kernel Development]     [Advanced Routing & Traffice Control]     [Bugtraq]

  Powered by Linux