Данные, появляющиеся как Ethernet-трейлер в самодельном SKB

Я пытаюсь сделать пользовательский skb в модуле ядра Linux, а затем отправить его по сети. Мне удается создать SKB, но когда я отправляю его по сети, он не достигает пункта назначения.

Если я запускаю wireshark на локальной машине, которая отправляет мой SBK по сети, он показывает мой пакет. Однако, если я проверяю содержимое моего пакета, это показывает, что данные помещаются как "Ethernet Trailer".

Кроме того, если я удаляю все данные из моего SKB и отправляю только SKB только для заголовка, он все равно не достигает места назначения

Вот код:

u_int32_t local_ip;
u_int32_t remote_ip;
struct udphdr *udph;
struct iphdr *iph;
struct ethhdr *eth;
unsigned short udp_len;
char remote_mac[6];
char local_mac[6];

Выделите skb:

int header_len = sizeof(*iph) + sizeof(*udph) + sizeof(*eth);
skb = sock_wmalloc(sock->sk, /*payload len*/ len + header_len + LL_RESERVED_SPACE(pfr->ring_netdev->dev), 0, GFP_KERNEL);

Так как я использую skb_push, я перемещаюсь вниз по данным и опускаюсь до конца:

skb_reserve(skb,
            len + header_len + LL_RESERVED_SPACE(pfr->ring_netdev->dev));

Push UDP заголовок:

skb_push(skb, sizeof(*udph));    

Сбросьте transport_pointer соответственно:

skb_reset_transport_header(skb);

Установите и заполните заголовок udp:

udph = udp_hdr(skb);

udph->source = htons(5123);
udph->dest = htons(5123);
udp_len = 14;
udph->len = htons(udp_len);
udph->check = 0;
local_ip = htonl(0xCB873F2A);  /*203.135.63.42*/
remote_ip = htonl(0xCB873F29); /*203.135.61.41*/
udph->check = csum_tcpudp_magic(local_ip,
                                remote_ip,
                                udp_len, IPPROTO_UDP,
                                csum_partial(udph, udp_len, 0));

if (udph->check == 0) {
    printk("mangled checksum\n");
    udph->check = CSUM_MANGLED_0;
}

Теперь нажмите IP-заголовок:

skb_push(skb, sizeof(*iph));

Сброс указателя сети:

skb_reset_network_header(skb);

Установите и заполните сетевой заголовок:

iph = ip_hdr(skb);

put_unaligned(0x45, (unsigned char *)iph);
iph->tos      = 0;
ip_len        = 40;
put_unaligned(htons(ip_len), &(iph->tot_len));
//iph->id     = htons(atomic_inc_return(&ip_ident));                                                                                                                                                  
iph->frag_off = 0;
iph->ttl      = 64;
iph->protocol = IPPROTO_UDP;
iph->check    = 0;
put_unaligned(local_ip   /*"\xC0\xA8\x00\x01"*/, &(iph->saddr));
put_unaligned(remote_ip  /*"\xC0\xA8\x00\x01"*/, &(iph->daddr));
iph->check    = ip_fast_csum((unsigned char *)iph, iph->ihl);

Нажмите заголовок Ethernet:

eth = (struct ethhdr *) skb_push(skb, ETH_HLEN);

Сбросьте mac_pointer соответственно:

skb_reset_mac_header(skb);

установить и заполнить mac_header:

skb->protocol = eth->h_proto = htons(ETH_P_IP);

remote_mac[0] = 0x4C;
remote_mac[1] = 0x72;
remote_mac[2] = 0xB9;
remote_mac[3] = 0x24;
remote_mac[4] = 0x14;
remote_mac[5] = 0x1E;

local_mac[0] = 0x00;
local_mac[1] = 0x1E;
local_mac[2] = 0xE3;
local_mac[3] = 0xED;
local_mac[4] = 0xD4;
local_mac[5] = 0xA9;

memcpy(eth->h_source, remote_mac, ETH_ALEN);
memcpy(eth->h_dest, remote_mac, ETH_ALEN);

Установить устройство и протокол:

skb->protocol = htons(ETH_P_IP);
skb->dev = pfr->ring_netdev->dev;
skb->priority = sock->sk->sk_priority;

 if(!err)
    goto out_free;

Сейчас отправь

if (dev_queue_xmit(skb) != NETDEV_TX_OK) {
    err = -ENETDOWN; /* Probably we need a better error here */
    goto out;
}

0 ответов

Другие вопросы по тегам