LINUX.ORG.RU

отправка skb на loopback-интерфейс (dev_queue_xmit) в .ko

 ,


0

1

здравствуйте!

пожаловал сюда, т.к. сам немного запутался и неосилил...

кто работал с сетью на уровне skbuff в ядре: подскажите, пожалуйста, как правильно отправлять пакет в loopback-интерфейсе.

есть код, хорошо работающий на девайсах eth, схематично:

skb = dev_alloc_skb(ip_sz + sizeof(struct tcphdr) + len);
... тут размечаем заголовки пакета, заполняем их поля
... (skb_reserve, skb_push, skb_put, skb_set_network_header
skb->dev = ... назначаем интерфейс
... считаем контрольную сумму (skb->csum, csum_partial,
... csum_tcpudp_magic/csum_ipv6_magic, ip_fast_csum)
skb->pkt_type = PACKET_OUTGOING; // пакет - на выход
res = dev_queue_xmit(skb); // посылаем в xmit

если посылаем в loopback (в ethhdr-заголовке: нулевые mac-адреса), wireshark не видит пакета, пока в h_dest eth-заголовка не поставить broadcast (FF:FF:FF:FF:FF:FF). теперь пакет видно в wireshark, но в сокет к адресату он все равно не попадает.

найденые решения:

  • заполнять dst-entry (skb_dst_set() - заполняли с уже отловленого пакета), что безуспешно (даже иногда валит систему)
  • использовать netif_rx_ni() для прямой доставки в стек:
    skb_reset_mac_header(skb);
    __skb_pull(skb, skb_network_offset(skb));
    skb->pkt_type = PACKET_LOOPBACK;
    skb->ip_summed = CHECKSUM_UNNECESSARY;
    skb_dst_set(skb, dst);
    skb_dst_force(skb);
    netif_rx_ni(skb);
    
    что тоже безрезультатно

хорошо-бы кусочек кода с места отсылки, аналог

skb->pkt_type = PACKET_OUTGOING;
res = dev_queue_xmit(skb);
и/или необходимые дополнения.

С ув., Тарас


Хороший пример создания и передачи пакета есть в net/ipv4/netfilter/ipt_REJECT.c в send_reset();

vel ★★★★★ ()
Ответ на: комментарий от vel

vel, спасибо.

в send_reset() делают ip_local_out(), смотрим ее код:

int __ip_local_out(struct sk_buff *skb)
{
	struct iphdr *iph = ip_hdr(skb);

	iph->tot_len = htons(skb->len);
	ip_send_check(iph);
	return nf_hook(NFPROTO_IPV4, NF_INET_LOCAL_OUT, skb, NULL,
		       skb_dst(skb)->dev, dst_output);
}

int ip_local_out(struct sk_buff *skb)
{
	int err;

	err = __ip_local_out(skb);
	if (likely(err == 1))
		err = dst_output(skb);

	return err;
}

получаеться, если пушим пакет в лупбек, надо тупо послать его в нетфильтр: nf_hook(... NF_INET_LOCAL_OUT ...) вместо dev_queue_xmit.

боюсь только, что в ядре не прокатит фишка с err == 1 (если конечно не будем забивать на dst_entry). так что проверять на лупбек придется другим способом (напр. по ip назначения).

когда реально попробую, отпишусь

gg ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.