Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sending SKB's for transmission from kernel space

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).

like image 370
MacStation Avatar asked Oct 30 '22 03:10

MacStation


1 Answers

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?

like image 132
user2699113 Avatar answered Nov 15 '22 05:11

user2699113