我正在实现两个发送自定义以太网数据包的内核模块。当两个模块位于两台不同的机器中时,它可以工作,但是当目标地址与所使用的接口相同时,它不起作用。
这是我的发送功能,我创建了一个这样的包:
|MAC_ADDRESS | PROTO | DATA|
int
eth_send(struct net_device* dev, uint8_t dest_addr[ETH_ALEN], uint16_t proto,
const char* msg, size_t len)
{
int ret;
unsigned char* data;
struct sk_buff* skb = alloc_skb(ETH_FRAME_LEN, GFP_ATOMIC);
skb->dev = dev;
skb->pkt_type = PACKET_OUTGOING;
skb_reserve(skb, ETH_HLEN);
/*changing Mac address */
struct ethhdr* eth = (struct ethhdr*)skb_push(skb, ETH_HLEN);
skb->protocol = eth->h_proto = htons(proto);
memcpy(eth->h_source, dev->dev_addr, ETH_ALEN);
memcpy(eth->h_dest, dest_addr, ETH_ALEN);
/* put the data and send the packet */
if (len > ETH_DATA_LEN)
len = ETH_DATA_LEN;
data = skb_put(skb, len);
if (memcmp(dev->dev_addr, dest_addr, ETH_ALEN * sizeof(uint8_t)) == 0) {
// send to myself
} else {
// sending to other machine
skb->pkt_type = PACKET_OUTGOING;
ret = dev_queue_xmit(skb);
}
return 1;
}
我无法想象如何将它发送给自己。我尝试使用netif_receive_skb
和dev_loopback_xmit
,但它们似乎不起作用。
我注册dev_add_pack
函数以添加包含struct packet_type
的结构,并在内部分配函数以在接收到包含定义的PROTO
的数据包时调用。如上所述,它适用于来自外部的数据包,但不适用于localhost。
我该怎么做?此外,还将提供解释这些功能如何工作的链接。
另外,为什么dev_loopback_xmit(struct net *net, struct sock *sk, struct sk_buff *skb)
还需要袜子和网*,而内部只使用skb?
提前致谢。
更新:这是我用来发送的内容
int
eth_send(struct net_device* dev, uint8_t dest_addr[ETH_ALEN], uint16_t proto,
const char* msg, size_t len)
{
int ret = 0;
unsigned char* data;
struct sk_buff* skb = alloc_skb(ETH_FRAME_LEN, GFP_ATOMIC);
skb->dev = dev;
skb->pkt_type = PACKET_OUTGOING;
skb_reserve(skb, ETH_HLEN);
/*changing Mac address */
struct ethhdr* eth = (struct ethhdr*)skb_push(skb, ETH_HLEN);
skb->protocol = eth->h_proto = htons(proto);
memcpy(eth->h_source, dev->dev_addr, ETH_ALEN);
memcpy(eth->h_dest, dest_addr, ETH_ALEN);
/* put the data and send the packet */
if (len > ETH_DATA_LEN)
len = ETH_DATA_LEN;
data = skb_put(skb, len);
memcpy(data, msg, len);
if (memcmp(dev->dev_addr, dest_addr, ETH_ALEN) == 0) {
skb->pkt_type = PACKET_LOOPBACK;
netif_rx_ni(skb); // undefined behaviour?
} else {
ret = dev_queue_xmit(skb);
}
return !ret;
}
这是我得到的恐慌,我的模块叫做kclient,
[ +0.000087] skbuff: skb_under_panic: text:ffffffff81833552
len:-65485 put:-65535 head:ffff88030dabf800 data:ffff88020dacf7ff tail:0x32 end:0x6c0 dev:enp0s3
[ +0.241948] ------------[ cut here ]------------
[ +0.105630] kernel BUG at /build/linux-jUC7gW/linux-4.4.0/net/core/skbuff.c:104!
[ +0.183770] invalid opcode: 0000 [#1] SMP
[ +0.080865] Modules linked in: kclient(OE) vboxsf binfmt_misc input_leds video vboxguest serio_raw isofs ib_iser rdma_cm iw_cm ib_cm ib_sa ib_mad ib_core ib_addr iscsi_tcp libiscsi_tcp libiscsi scsi_transport_iscsi autofs4 btrfs raid10 raid456 async_raid6_recov async_memcpy async_pq async_xor async_tx xor raid6_pq libcrc32c raid1 raid0 multipath linear crct10dif_pclmul crc32_pclmul ghash_clmulni_intel aesni_intel mptspi aes_x86_64 lrw scsi_transport_spi gf128mul mptscsih glue_helper ablk_helper cryptd psmouse mptbase e1000
[ +0.967271] CPU: 2 PID: 2233 Comm: insmod Tainted: G OE 4.4.0-121-generic #145-Ubuntu
[ +0.192036] Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS VirtualBox 12/01/2006
[ +0.091681] task: ffff88030dd50000 ti: ffff88030f1ac000 task.ti: ffff88030f1ac000
[ +0.119018] RIP: 0010:[<ffffffff8172c1c4>] [<ffffffff8172c1c4>] skb_panic+0x64/0x70
[ +0.025014] RSP: 0000:ffff88031f103d20 EFLAGS: 00010282
[ +0.001016] RAX: 000000000000008f RBX: ffff8800dadb2d00 RCX: 0000000000000000
[ +0.073327] RDX: 0000000000000000 RSI: ffff88031f110558 RDI: ffff88031f110558
[ +0.151802] RBP: ffff88031f103d40 R08: 0000000000000000 R09: 0000000000000219
[ +0.156554] R10: 0000000000012400 R11: 0000000000000219 R12: ffff88030f32a800
[ +0.163420] R13: ffff88030dabf800 R14: 0000000000000032 R15: ffff88030dc36000
[ +0.175838] FS: 00007fd90ae3d700(0000) GS:ffff88031f100000(0000) knlGS:0000000000000000
[ +0.132958] CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b
[ +0.130855] CR2: 00005638cb656a18 CR3: 000000030fb62000 CR4: 0000000000040670
[ +0.161277] Stack:
[ +0.044096] ffff88020dacf7ff 0000000000000032 00000000000006c0 ffff88030dc36000
[ +0.162723] ffff88031f103d50 ffffffff8172cb8f ffff88031f103da0 ffffffff81833552
[ +0.188238] ffff88031f110440 0000000000000002 ffff88030dc36000 ffff8800dadb2d00
[ +0.193325] Call Trace:
[ +0.060884] <IRQ>
[ +0.043792] [<ffffffff8172cb8f>] skb_push+0x3f/0x40
[ +0.099121] [<ffffffff81833552>] packet_rcv+0xa2/0x450
[ +0.133466] [<ffffffff81741c1c>] __netif_receive_skb_core+0x74c/0xab0
[ +0.117920] [<ffffffff810b7bb9>] ? update_curr+0x79/0x170
[ +0.110059] [<ffffffff81741f98>] __netif_receive_skb+0x18/0x60
[ +0.100118] [<ffffffff81742d98>] process_backlog+0xa8/0x150
[ +0.117832] [<ffffffff817424e3>] net_rx_action+0x223/0x360
[ +0.137399] [<ffffffff81087d66>] __do_softirq+0x106/0x2a0
[ +0.134271] [<ffffffff81088073>] irq_exit+0xa3/0xb0
[ +0.064162] [<ffffffff810af683>] scheduler_ipi+0x93/0x150
[ +0.127852] [<ffffffff81051b3f>] smp_reschedule_interrupt +0x2f/0x40
[ +0.127852] [<ffffffff8185143f>] reschedule_interrupt +0xbf/0xdo
<EOI>
我正在使用虚拟机进行测试,正如您所见。