Using sk_buff to add an Ethernet frame header

后端 未结 2 1999
再見小時候
再見小時候 2021-02-04 18:48

I have a kernel module that captures outgoing Internet traffic(Netfilter hook: LOCAL_OUT) At this hook, there\'s still no Ethernet header.

I built the Ethernet header an

2条回答
  •  一生所求
    2021-02-04 19:15

     unsigned int snoop_hook1( unsigned int hooknum, struct sk_buff *skb,
        const struct net_device *in, const struct net_device *out,
        int(*okfn)( struct sk_buff * ) )    
    {      
        int offset, len,tcplen;
        struct ethhdr *ethh;
        struct iphdr *iph;
        struct tcphdr *tcph;
        uint16_t t;
        bool flag = false;
        struct sk_buff *nskb;
        struct net_device *eth1_dev , *lo_dev;
    
        if (!skb) return NF_ACCEPT;
        iph = ip_hdr(skb);
        if (!iph) return NF_ACCEPT;
        tcph = tcp_hdr(skb);
        /* skip lo packets */
        if (iph->saddr == iph->daddr) return NF_ACCEPT;
        if (tcph->dest == htons(80))
                flag=true;
        // add similar conditions for true flags
        if(flag != true)
                return NF_ACCEPT;
    
        /* print packet information */
        printk(KERN_INFO "HELLO !!!\n");
        printk(KERN_INFO "HOOK=NF_INET_LOCAL_OUT");
        printk(KERN_INFO "INDEV %s OUTDEV %s",in->name,  out->name);
        printk(KERN_INFO "sk_buff::dev %s",skb->dev->name);
        //printk(KERN_INFO "MAC ADDRESSES as in eth header %pM->%pM", &(ethh->h_source), &(ethh->h_dest));
        printk( KERN_INFO " %pI4->%pI4\n", &(iph->saddr), &(iph->daddr));
        printk(KERN_INFO "TCP SRC:%d, TCP DST:%d",ntohs(tcph->source),ntohs(tcph->dest));
    
        // correct the IP checksum
        printk(KERN_INFO "IP checksum =%d",iph->check);
        iph->check = 0;
        ip_send_check (iph);
        printk(KERN_INFO "IP checksum new =%d",iph->check);
    
    
        //correct the TCP checksum
        printk(KERN_INFO "TCP checksum =%d",tcph->check);
        offset = skb_transport_offset(skb);
        len = skb->len - offset;
        printk(KERN_INFO "skb->len=%d",skb->len);
        printk(KERN_INFO "offset=%d",offset);
        printk(KERN_INFO "len=%d",len);
        tcph->check = 0;
        if(skb->len > 60){
        tcph->check  = csum_tcpudp_magic((iph->saddr), (iph->daddr), len, IPPROTO_TCP, csum_partial((unsigned char *)tcph,len,0));
        printk(KERN_INFO "TCP checksum new=%d",tcph->check);
        }
        else{
        tcph->check  = ~csum_tcpudp_magic((iph->saddr), (iph->daddr), len, IPPROTO_TCP, 0);
        printk(KERN_INFO "TCP checksum new*=%d",tcph->check);
        }
        printk(KERN_INFO "************************************************************");
    
        //send to dev
        eth1_dev = dev_get_by_name(&init_net,"eth1");
        lo_dev = dev_get_by_name(&init_net,"lo");
        skb->dev = eth1_dev;
        ethh = (struct ethhdr *) skb_push(skb, ETH_HLEN);
        skb->protocol = ethh->h_proto = htons(ETH_P_IP);
        memcpy (ethh->h_source,eth1_dev->dev_addr , ETH_ALEN);
        memcpy (ethh->h_dest, d_mac, ETH_ALEN);
        dev_queue_xmit(skb);
        return NF_STOLEN;
    }
    

    This is an old question(and answer ) .I needed to do something exactly similar and I ended up with this code. Thought of showing it for helping others. It works for me at least , I am sending the same skb here . d_mac is the mac of the gateway or another mac in the lan . It can be obtained from incoming packets or from arp.

提交回复
热议问题