clinuxlinux-kernel

Send a ping packet using dev_queue_xmit


I have written a driver which sends a ping packet, but it's not working (I checked using tcpdump -i wlan0 icmp).

Basically, I have used ioctl call from a user program to start the transmission (it's working), but there is a problem in the module code.

Transmission code:

case WLAN_TRANSMIT:
    icmp.type = ICMP_ECHO;
    icmp.code = 0;
    icmp.un.echo.sequence = i++;
    icmp.un.echo.id = current -> pid & 0xFFFF;
    printk(KERN_ALERT "ID::%X\n", icmp.un.echo.id);
    ip4.protocol = 0x01; //for icmp protocol
    ip4.tos = 0x00;
    ip4.frag_off = 0;
    ip4.daddr = in_aton(procfs_buffer);
    ip4.saddr = in_aton(ifr -> ifr_addr.sa_data);
    len = sizeof(data);
    skb = dev_alloc_skb(1500);
    skb -> dev = __dev_get_by_name( & init_net, "wlan0");
    skb_reserve(skb, NET_IP_ALIGN); //header of 2 bytes; increments tail and data pointer
    skb -> data = skb_put(skb, sizeof(len)); // increments all pointer or adds data
    memcpy(data, skb -> data, len);
    wdev = skb -> dev;
    skb -> transport_header = skb_push(skb, sizeof(icmp));
    memset(skb -> transport_header, 0, sizeof(struct icmphdr));
    memcpy(skb -> transport_header, & icmp, sizeof(struct icmphdr));
    
    skb -> network_header = skb_push(skb, sizeof(ip4));
    memset(skb -> network_header, 0, sizeof(struct iphdr));
    memcpy(skb -> network_header, & ip4, sizeof(struct iphdr));
    // printk("i::%d\n",i);
    // skb->mac_header = skb_push(skb,6*sizeof(0xFF)); 
    //skb->mac_header = ()
    skb -> mac_header = skb -> dev -> dev_addr;
    if (dev_queue_xmit(skb) == NET_XMIT_SUCCESS)
      printk(KERN_ALERT "success");

I am using dev_queue_xmit.


Solution

  • skb->mac_header = skb->dev->dev_addr looks wrong.
    The MAC header must be copied into the packet, before the IP header, and skb->data must point to it. Setting skb->mac_header in this context is quite meaningless.

    I also don't see that you calculate the IP and ICMP checksums (the ICMP checksum is, I think, optional, but the IP checksum is mandatory).

    I really can't tell if it's all.
    You should see what's the return value from dev_queue_xmit, and also print the packet contents, from skb->data to skb->tail and see they're a valid ICMP packet.