在内核模块

时间:2018-04-15 19:32:05

标签: c linux-kernel kernel-module ethernet raw-sockets

我正在实现两个发送自定义以太网数据包的内核模块。当两个模块位于两台不同的机器中时,它可以工作,但是当目标地址与所使用的接口相同时,它不起作用。 这是我的发送功能,我创建了一个这样的包:
|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_skbdev_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>

我正在使用虚拟机进行测试,正如您所见。

0 个答案:

没有答案