C 放下skb或展开传出skb

C 放下skb或展开传出skb,c,linux-kernel,network-programming,kernel-module,C,Linux Kernel,Network Programming,Kernel Module,当我使用内核模块在内核中捕获传出数据包时,我使用kfree_skb()丢弃该数据包,但它不工作,数据包到达其目的地。我检查&skb->用户为1 change_skb(struct sk_buff*skb)接收原始skb并创建一个新的独立副本(只需复制其负载)并发送新的skb。这是可行的,我可以在接收端看到我的新数据包,但我不能丢弃原始数据包,这样我仍然可以在接收端看到原始数据包 这是我的密码: int my_pkt_handling(struct sk_buff *skb, struct net

当我使用内核模块在内核中捕获传出数据包时,我使用kfree_skb()丢弃该数据包,但它不工作,数据包到达其目的地。我检查&skb->用户为1

change_skb(struct sk_buff*skb)接收原始skb并创建一个新的独立副本(只需复制其负载)并发送新的skb。这是可行的,我可以在接收端看到我的新数据包,但我不能丢弃原始数据包,这样我仍然可以在接收端看到原始数据包

这是我的密码:

int my_pkt_handling(struct sk_buff *skb, struct net_device *dev, struct packet_type *pkt, struct net_device *org_dev) {

struct ethhdr *eth = eth_hdr(skb);
struct iphdr *iph = ip_hdr(skb);
unsigned char dst_addr[] = {0x00, 0x16, 0x41, 0xaa, 0xf8, 0xf0};
unsigned char src_addr[] = {0x00, 0x1f, 0xe2, 0x12, 0xb0, 0x34};

switch (skb->pkt_type) {
    case PACKET_OUTGOING:
        if ( memcmp(eth->h_dest, dst_addr, ETH_ALEN) == 0 && eth->h_proto == htons(ETH_P_IP) ) {                
            printk(KERN_ALERT"Outgoing| Interface: %4s Type: 0x%4x Src: %pI4 Dest: %pI4 Len: %d SizeOf: %lu User#: %d\n", 
                        skb->dev->name, ntohs(eth->h_proto), &iph->saddr, &iph->daddr, skb->len, sizeof(skb), atomic_read(&skb->users));
            change_skb(skb);
            kfree_skb(skb);
            return 0;
        }
        break;
    default:
        break;
}

return 0;

从函数签名来看,似乎您正在使用
dev\u add\u pack()
API

dev\u add\u pack()
不是丢弃数据包的正确API

如果要丢弃数据包,应使用
nf\u register\u hook()
返回nf\u drop

在此链接中阅读有关netfilter的更多信息:

在调用
kfree\u skb()
之前,您是否应该先使用
skb\u unlink()
?我没有在任何地方使用skb\u unlink()。但是如果对IP数据包使用nf\u register\u hook()?我想捕获所有以太网数据包。如果您使用网桥,则nf_register_hook()捕获所有以太网数据包。如果不使用网桥,可以使用nf_register_hook()捕获IP/ARP。如果您不使用网桥,并且希望捕获任何数据包,那么您唯一的选择(据我所知)是在数据包传递给dev_hard_start_xmit()之前在dev_queue_xmit()上捕获它。所以,我可以开发一个内核模块来实现这一点,还是必须更改原始内核源代码?