Hi all
To learn how things work I am experimenting with writing kernel code. At
the moment I am trying to send an ICMP packet from a kernel module. I
have pasted my current code below. I suspect some of the lengths are
wrong and a few small things like that, but the first time I insmod the
module it all seems to basically go OK and send the packet. However, if
I remove the module and reinsert it then somewhere in the ip_send
function the sk_buff seems to get corrupted. Subsequent insertions
corrupt the packet in the same way. Here are some messages logged during
correct and corrupted packet sending showing that it is during the
ip_send call:
kernel: Sending now src 1678246666...
kernel: Sent...now src 1678246666...
kernel: Sending now src 1678246666...
kernel: Sent...now src 268435456...
Is there something I'm missing? Something to do with locking or
something perhaps? I have attached a correct and corrupt packet in
tcpdump capture format.
void foo(void) {
struct sk_buff *skb;
struct pckt *p;
struct rtable *rt = NULL;
skb = alloc_skb(sizeof(struct pckt), GFP_KERNEL);
if (!skb) goto end;
p = (struct pckt *) skb_put(skb, sizeof(struct pckt));
memset(p, 0, sizeof(struct pckt));
skb->mac.ethernet = &p->ethernet;
skb->nh.iph = &p->iph;
skb->h.icmph = &p->icmph;
p->iph.saddr = (((((100 << 8) + 8) << 8) + 3) << 8) + 10;
p->iph.daddr = (((((128 << 8) + 8) << 8) + 3) << 8) + 10;
if (ip_route_output(&rt, p->iph.daddr, p->iph.saddr, RT_TOS(0), 0)) {
printk(LOGAT "ip_route_output failed\n");
}
skb->dst = &rt->u.dst;
skb->pkt_type = PACKET_HOST;
skb->protocol = __constant_htons(ETH_P_IP);
p->data[0] = 'A'; p->data[1] = 'B'; p->data[2] = 'C'; p->data[3] = 'D';
p->icmph.type = ICMP_ECHOREPLY;
p->icmph.code = 0;
p->icmph.checksum = 0;
p->iph.ihl = sizeof(struct iphdr) >> 2;
p->iph.ttl = 64;
p->iph.version = 4;
p->iph.frag_off = __constant_htons(IP_DF);
p->iph.protocol = IPPROTO_ICMP;
// p->iph.tot_len = htons(sizeof(struct pckt));
p->iph.tot_len = htons(sizeof(struct iphdr) + sizeof(struct icmphdr) + 4);
ip_send_check(&p->iph);
skb->len = 4;
// skb->len = sizeof(struct pckt);
skb->csum = 0;
skb->data = p->data;
printk(LOGAT "Sending now src %u...\n", p->iph.saddr);
ip_send(skb);
printk(LOGAT "Sent...now src %u...\n", p->iph.saddr);
}
BTW, if there is a source of good documentation that I might have missed
then please point it out to me!
Thanks
Ian
correct.txt
Description: Text document
corrupt.txt
Description: Text document
|