5

I am currently writing a kernel module that modifies packet payloads as a learning experience. I have the packet modifications done, but now I want to send out this new modified packet after the original (I don't want to drop the original). I can't seem to find a kernel function that sends SKB's for transmission. I've tried dev_queue_xmit(nskb) but that causes a kernel panic, I also tried skb->next = nskb but that does nothing. Do I have to implement the SKB list handling? I am unsure of how to do that since this article seems to be outdated .

EDIT:

So I was able to fix the kernel panic when calling dev_queue_xmit(nskb), I was accidentally doing dev_queue_xmit(skb) which would delete skb and cause a panic from net filter. The problem is now that everything works, but I'm not seeing duplicate packets being sent out, there is no trace of the second packet ever being sent. TCPDump on the machine doesn't see anything and TPCDump on the target doesn't see anything either, the following is my code.

unsigned int in_hook(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) {
    struct sk_buff *nskb = skb_copy(skb, GFP_KERNEL);
    /* Various other variables not relevant to the problem */
    __u32 saddr, daddr;
    saddr = ntohl(iph->saddr);
    if (saddr == ipToInt(10,0,2,12) || saddr == ipToInt(10,0,2,13)) {
        /*For loop that saves the payload contents into a variable */

        /* Here is where the problem is, 
        I have this if statement to prevent a feedback loop
        then if the ip matches, I call dev_queue_xmit(nskb) 
        which is supposed to send out sk_buff's, but TCPDump doesn't
        show anything on any computer */
        if (saddr == ipToInt(10,0,2,13)) {
            dev_queue_xmit(nskb);
        }

        /* Rest of the code that isn't relevant to sending packets */
   }
   return NF_ACCEPT;
}

My network setup is as follows, it's 3 Ubuntu Server VM's, all of them are being SSH'd into from the host computer (macOS if it matters, I don't know at this point). The computer running the above kernel module spoofs bidirectionally the other two VM's. The other two VM's then talk to each other via a netcat session. I'm hoping that when I send one message from the VM with ip 10.0.2.13, that 10.0.2.12 sees two of the same message. I know the acknowledgement number mishap will break the connection, but I'm not getting that. TCPDump on any of the 3 computers doesn't show anything besides the packets that are supposed to be sent.

I have so far tried dev_queue_xmit(nskb) as well as nskb->dev->netdev_ops->ndo_start_xmit(nskb, skb->dev).

MacStation
  • 411
  • 4
  • 20

2 Answers2

1

As far as I remember dev_queue_xmit() is the right procedure for sending. The question is how do you prepared the skb you want to send? Also give us the calltrace from dmesg when the kernel panic occured. Do you set skb->dev?

user2699113
  • 4,262
  • 3
  • 25
  • 43
  • Dmesg is empty when I check, and skb->dev is set I think, when I do `if(skb->dev)`, it returns true. Also, for now I'm just trying to send a second packet, so the skb given to me by the net filter function, I do `dev_queue_xmit(skb)` on it hoping to see two duplicate packets. – MacStation Aug 25 '17 at 21:46
  • The most important thing: we need exact what is in dmesg (on the screen) when the kernel panic occurs. I know that when the kernel occurs it may not be logged into system files - so you can use second system with serial console connected and do the dump of this console. – user2699113 Aug 26 '17 at 03:14
  • Second thing - how do you copy the skb? – user2699113 Aug 26 '17 at 12:55
  • I fixed the panic, I was sending the original skb and `dev_queue_xmit` destroys the original, now there's no panic, but nothing happens. I copy skb into nskb with `nskb = skb_copy(skb, GFP_KERNEL);`, and send it with `dev_queue_xmit(nskb)`. – MacStation Aug 26 '17 at 16:08
  • AFAIK dev_queue_xmit() should return some status... Anyway try such a thing: nskb->dev->netdev_ops->ndo_start_xmit(nskb, skb->dev), but I didn't test it. – user2699113 Aug 26 '17 at 17:34
  • You were right, upon further examination, it returns 0 which I think is NET_XMIT_SUCCESS, but in the receiving machine, tcpdump doesn't show two packets being received, just the original one. – MacStation Aug 27 '17 at 22:25
  • I'd suggest to go through dev_queue_xmit() and find out where this skb disappeared. – user2699113 Aug 31 '17 at 15:24
  • Is there anything I should be doing to nskb before calling `dev_queue_xmit(nskb)`? I know it's already initialized as it's a copy of the original skb. – MacStation Sep 01 '17 at 01:36
1

I figured it out, skb_copy doesn't copy the ethernet header of an skb, so the sent packet never reaches its destination.

MacStation
  • 411
  • 4
  • 20