Краткий ответ: пакеты отправляются в самый конец программного стека (например, в Linux).
Длинный ответ с копанием кода в ядре tcpdump, libpcap и linux 3.12:
И Wireshark, и tcpdump используют libpcap, например,
http://sources.debian.net/src/tcpdump/4.5.1-2/tcpdump.c#L1472
if (pcap_setfilter(pd, &fcode) < 0)
, которые в свою очередь устанавливают фильтр пакетов через setfilter_op и activ_op. Существует множество реализаций этих операций, и я думаю, что в последних версиях Linux PF_PACKET
будет использоваться с pcap_activate_linux
libpcap-1.5.3-2 / pcap-linux.c # L1287 :
/*
* Current Linux kernels use the protocol family PF_PACKET to
* allow direct access to all packets on the network while
* older kernels had a special socket type SOCK_PACKET to
* implement this feature.
* While this old implementation is kind of obsolete we need
* to be compatible with older kernels for a while so we are
* trying both methods with the newer method preferred.
*/
status = activate_new(handle);
...
activate_new(pcap_t *handle)
...
/*
* Open a socket with protocol family packet. If the
* "any" device was specified, we open a SOCK_DGRAM
* socket for the cooked interface, otherwise we first
* try a SOCK_RAW socket for the raw interface.
*/
sock_fd = is_any_device ?
socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_ALL)) :
socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
PF_PACKET реализован в ядре, в файле net / packet / af_packet.c . Инициализация PF_SOCKET выполняется в packet_do_bind
с функцией register_prot_hook(sk)
(если устройство находится в состоянии UP), , которая вызывает dev_add_pack
из net / core / dev.c в зарегистрировать крючок:
370 /**
371 * dev_add_pack - add packet handler
372 * @pt: packet type declaration
373 *
374 * Add a protocol handler to the networking stack. The passed &packet_type
375 * is linked into kernel lists and may not be freed until it has been
376 * removed from the kernel lists.
377 *
378 * This call does not sleep therefore it can not
379 * guarantee all CPU's that are in middle of receiving packets
380 * will see the new packet type (until the next received packet).
381 */
382
383 void dev_add_pack(struct packet_type *pt)
384 {
385 struct list_head *head = ptype_head(pt);
386
387 spin_lock(&ptype_lock);
388 list_add_rcu(&pt->list, head);
389 spin_unlock(&ptype_lock);
390 }
Я думаю, что обработчик pf_packet - функция tpacket_rcv(...)
- будет зарегистрирован в ptype_all.
Хуки, зарегистрированные в ptype_all
, вызываются для исходящих пакетов из dev_queue_xmit_nit
(«Подпрограмма поддержки. Отправляет исходящие кадры в любые сетевые ответвления, используемые в настоящее время.») С помощью list_for_each_entry_rcu(ptype, &ptype_all, list) { ... deliver_skb ...} .. func
, delivery_skb вызывает функцию, которая равна tpacket_rcv
для libpcap.
dev_queue_xmit_nit вызывается из dev_hard_start_xmit
( строка 2539 в net / core / dev.c ), что является AFAIK последней стадией (для исходящих пакетов) независимой от устройства обработки пакетов в сетевом стеке Linux.
Та же история для входящих пакетов, ptype_all
-регистрационные хуки вызываются из __netif_receive_skb_core
с такими же list_for_each_entry_rcu(ptype, &ptype_all, list) {.. deliver_skb..}
. __netif_receive_skb_core
вызывается с __netif_receive_skb
в самом начале обработки входящих пакетов
Linux Foundation имеет хорошее описание сетевого стека (http://www.linuxfoundation.org/collaborate/workgroups/networking/kernel_flow),, вы можете увидеть dev_hard_start_xmit
на изображении http://www.linuxfoundation.org/images/1/1c/Network_data_flow_through_kernel.png (предупреждение, оно огромно) слева под легендой. И netif_receive_skb
находится внутри самого правого нижнего квадрата ("net / core / dev.c"), который подается из IRQ, затем NAPI poll или netif_rx, и единственный выход отсюда - netif_receive_skb
.
На рисунке даже показан один из двух хуков pf_packet - самый левый квадрат под легендой ("net / packet / af_packet.c") - для исходящих пакетов.
Какой у вас инструмент? Как он подключается к сетевому стеку? Если вы сможете найти инструмент в Network_data_flow picture , вы получите ответ. Например, Netfilter подключается (NF_HOOK
) только в ip_rcv
(входящий) ip_output
(локальный исходящий) и ip_forward
(исходящий из маршрутизации) - сразу после netif_receive_skb
и непосредственно перед dev_queue_xmit
.