Libpcap or Pf_Packet

libpcap or PF_PACKET?

As far as I know, libpcap put a timestamp on each packet.

No, libpcap gets a timestamp for the packet from the OS packet capture mechanism that it uses - which, on Linux is...

...PF_PACKET sockets.

The Linux kernel time stamps incoming packets. PF_PACKET sockets have multiple ways of reading from them:

  • regular socket receives, for which you can either get a time stamp with an explicit ioctl (so you can avoid fetching it to userland, but you can't avoid the kernel time stamping the packet in the first place; libpcap, when using regular socket receives, always asks for the time stamp);
  • memory-mapped access, which always supplies the time stamp.

Libpcap uses memory-mapped access whenever it's available; if you care about capture performance, you probably want to do so as well. It's not easy to use, however.

Is libpcap implemented by socket API?

Is it true that libpcap is implemented by socket API?

If you're on Linux or IRIX, it is true. If you're on another flavor of UN*X, it is not true.

If not, which OS-level API is used to implement it?

On *BSD, OS X, AIX, and Solaris 11 and later: BPF.

On earlier versions of Solaris, and on HP-UX: STREAMS+DLPI.

it seems impossible to intercept all network traffic (from all ports) by just using the socket API in Unix-like system

On Linux, if you open a PF_PACKET socket, and don't bind it to a particular interface, packets from all interfaces are delivered to the socket.

socket API seems unable to get the information in link layer

You have to use the right type of socket, namely a PF_PACKET socket on Linux or a PF_RAW socket with a protocol of RAWPROTO_SNOOP on IRIX. Other UN*Xes don't have socket types for packet capture, and use other mechanisms.

Does libpcap use the traffic control layer of linux?

does pcap_inject call the traffic control layer of linux to send packets? Or does it directly send to the device driver?

It does a send() call on a PF_PACKET socket. By default, packets sent on those sockets go through the traffic control layer; to quote the PF_PACKET socket man page:

   PACKET_QDISC_BYPASS (since Linux 3.14)
By default, packets sent through packet sockets pass through
the kernel's qdisc (traffic control) layer, which is fine for
the vast majority of use cases. For traffic generator appli‐
ances using packet sockets that intend to brute-force flood
the network—for example, to test devices under load in a simi‐
lar fashion to pktgen—this layer can be bypassed by setting
this integer option to 1. A side effect is that packet
buffering in the qdisc layer is avoided, which will lead to
increased drops when network device transmit queues are busy;
therefore, use at your own risk.

libpcap does not turn that option on.

libpcap performance and behavior differences between Ubuntu 14.40 and CentOS 6.5

This has been answered. According to Guy Harris from tcpdump/libpcap, the difference is due to CentOS6.5 running 2.6.X kernel. Below is his response:

"
3.2 introduced the TPACKET_V3 version of the "T(urbo)PACKET" memory-mapped packet capture mechanism for PF_PACKET sockets; newer versions of libpcap (1.5 and later) support TPACKET_V3 and will use it if the kernel supports it. TPACKET_V3 makes much more efficient use of the capture buffer; in at least one test, it dropped fewer packets. It also might impose less overhead, so that asking for a 2GB buffer takes less kernel memory."

Does libpcap always make a copy of the packet?

There appear to be two questions here:

  • the one in the title, which sounds as if it's asking whether libpcap copies the packet;
  • the one in the body, asking whether it always copies the entire packet.

For the first question:

There's probably at least one copy done by any code using the mechanisms atop which libpcap runs in various OSes - a copy from the mbufs/skbuff/STREAMS buffers/whatever to the mechanism's buffer. For Linux, when the tpacket mechanism is not being used, the skbuff might just be queued on the receive queue for the PF_PACKET socket libpcap is using.

There may be another copy - a copy from that buffer to userland; if libpcap is using a "zero-copy" mechanism, such as the Linux tpacket mechanism (which libpcap 1.0 and later use by default), the second copy doesn't happen. It will happen if a zero-copy mechanism isn't being used.

However, if you're using pcap_next() or pcap_next_ex() on a Linux system and the tpacket mechanism is being used, a separate copy, from the memory-mapped buffer to a private buffer; that doesn't happen if you use pcap_dispatch() or pcap_loop().

For the second question:

That's what the "snaplen" argument to pcap_open_live() and pcap_set_snaplen() is for - it lets you specify that no more than "snaplen" bytes of packet data should be captured, and that means that no more than that many bytes are copied.

Note that this length includes the link-layer headers, and that those can include "metadata" headers such as radiotap headers that you might get on 802.11 adapters. This header might be variable-length (for example, on 802.11, the 802.11 header is variable-length, and, if you're getting radiotap headers, those are variable-length as well).

In addition, both IPv4 and TCP headers can have options, and IPv6 packets can have extension headers, so the length of IP and TCP headers can also be variable.

This means that you might have to determine a "worst case" snapshot length to use; there's no way to explicitly say "don't give me anything past the TCP/UDP header", you can only say "give me no more than N bytes".

Does libpcap use raw sockets underneath them?

"libpcap" and "raw sockets" are different topics.

Libpcap is a packet capture library for linux which is used to capture the traffic/packets that pass through a network interface like eth0.

On windows the Winpcap library does the same thing.

Raw sockets are a feature of the socket api provided by the OS that can be used to send packets with headers defined by the application and not the OS. So using raw sockets we can specify the IP , TCP headers and send the packets.

Raw sockets are available on Linux since all time. On Windows raw sockets were available only in Windows XP and Windows XP(SP1).

On windows the winpcap library has a feature to send packets with arbitrary content , which means raw socket functionality can be achieved with winpcap on Windows.

Why does a PF_PACKET RAW socket stop missing packets after Wireshark was launched?

By default, Wireshark is setting the network interface in promiscuous mode, using libpcap:
https://github.com/the-tcpdump-group/libpcap/blob/735f1f9d3318693f0096be4198d34e9ac0985777/pcap-linux.c#L3528

Try adding this setsockopt call in your code, to see if it helps.



Related Topics



Leave a reply



Submit