2

I'm developing a Linux C app that works like traceroute, sending TCP/UDP packets and listening for incoming TCP/UDP answer packets or ICMP Time Exceeded messages.

I guess it should be easier to use libpcap than dealing with raw sockets, but are there any points to choose raw sockets over libpcap?

Are there differences in terms of

  • performance (how fast my app gets the incoming packet)

  • CPU usage

  • packet loss (packets received by my host but not my app - because of some delay, timeout expired or other reason - especially in cases of high CPU usage, high network traffic and low network performances)?

Are there any other difference I didn't take into account?

Are there other pros and cons if the app is running on Android instead of Linux?

Thank you.

the structure
  • 89
  • 1
  • 10

1 Answers1

1

Yes, there is a very big con: libpcap is not what you're looking for.

lipcap by itself has absolutely zero support for building/analyzing TCP, UDP, ICMP (or even IP) packets. It is simply not what it's made for. It can setup filters that match on some TCP/UDP etc, but passed that point you'll have to do all the parsing yourself.

You should have a look at pcap official tutorial:

http://www.tcpdump.org/pcap.html

Go to the section "The actual sniffing". Look at the prototype of the callback libpcap will call when it will capture a packet matching your filter:

void got_packet(u_char *args,
                const struct pcap_pkthdr *header,
                const u_char *packet);

The packet you'll receive is just a char pointer. You'll have to do all the parsing of it by yourself. As the tutorial goes on:

But how do you make use of this variable (named "packet" in our prototype)? A packet contains many attributes, so as you can imagine, it is not really a string, but actually a collection of structures (for instance, a TCP/IP packet would have an Ethernet header, an IP header, a TCP header, and lastly, the packet's payload). This u_char pointer points to the serialized version of these structures. To make any use of it, we must do some interesting typecasting.

And then you have some code that do just that (with some simplifications so that it's not 10 kilometers long, like "ethernet headers are always exactly 14 bytes" - try that on VLAN!). From then on, for this packet parsing, none of the code is provided by pcap.

Look at pcap API. Do you see anything related to IP/TCP/UDP/ICMP? No.

pcap_activate (3pcap) - activate a capture handle
pcap_breakloop (3pcap) - force a pcap_dispatch() or pcap_loop() call to return
pcap_can_set_rfmon (3pcap) - check whether monitor mode can be set for a not-yet-activated capture handle
pcap_close (3pcap)   - close a capture device or savefile
pcap_compile (3pcap) - compile a filter expression
pcap_create (3pcap)  - create a live capture handle
pcap_datalink (3pcap) - get the link-layer header type
pcap_datalink_name_to_val (3pcap) - get the link-layer header type value corresponding to a header type name
pcap_datalink_val_to_description (3pcap) - get a name or description for a link-layer header type value
pcap_datalink_val_to_name (3pcap) - get a name or description for a link-layer header type value
pcap_dispatch (3pcap) - process packets from a live capture or savefile
pcap_dump (3pcap)    - write a packet to a capture file
pcap_dump_close (3pcap) - close a savefile being written to
pcap_dump_file (3pcap) - get the standard I/O stream for a savefile being written
pcap_dump_flush (3pcap) - flush to a savefile packets dumped
pcap_dump_fopen (3pcap) - open a file to which to write packets
pcap_dump_ftell (3pcap) - get the current file offset for a savefile being written
pcap_dump_open (3pcap) - open a file to which to write packets
pcap_file (3pcap)    - get the standard I/O stream for a savefile being read
pcap_fileno (3pcap)  - get the file descriptor for a live capture
pcap_findalldevs (3pcap) - get a list of capture devices, and free that list
pcap_fopen_offline (3pcap) - open a saved capture file for reading
pcap_fopen_offline_with_tstamp_precision (3pcap) - open a saved capture file for reading
pcap_free_datalinks (3pcap) - get a list of link-layer header types supported by a capture device, and free that list
pcap_free_tstamp_types (3pcap) - get a list of time stamp types supported by a capture device, and free that list
pcap_freealldevs (3pcap) - get a list of capture devices, and free that list
pcap_freecode (3pcap) - free a BPF program
pcap_get_selectable_fd (3pcap) - get a file descriptor on which a select() can be done for a live capture
pcap_get_tstamp_precision (3pcap) - get the time stamp precision returned in captures
pcap_geterr (3pcap)  - get or print libpcap error message text
pcap_getnonblock (3pcap) - set or get the state of non-blocking mode on a capture device
pcap_inject (3pcap)  - transmit a packet
pcap_is_swapped (3pcap) - find out whether a savefile has the native byte order
pcap_lib_version (3pcap) - get the version information for libpcap
pcap_list_datalinks (3pcap) - get a list of link-layer header types supported by a capture device, and free that list
pcap_list_tstamp_types (3pcap) - get a list of time stamp types supported by a capture device, and free that list
pcap_lookupdev (3pcap) - find the default device on which to capture
pcap_lookupnet (3pcap) - find the IPv4 network number and netmask for a device
pcap_loop (3pcap)    - process packets from a live capture or savefile
pcap_major_version (3pcap) - get the version number of a savefile
pcap_minor_version (3pcap) - get the version number of a savefile
pcap_next (3pcap)    - read the next packet from a pcap_t
pcap_next_ex (3pcap) - read the next packet from a pcap_t
pcap_offline_filter (3pcap) - check whether a filter matches a packet
pcap_open_dead (3pcap) - open a fake pcap_t for compiling filters or opening a capture for output
pcap_open_dead_with_tstamp_precision (3pcap) - open a fake pcap_t for compiling filters or opening a capture for output
pcap_open_live (3pcap) - open a device for capturing
pcap_open_offline (3pcap) - open a saved capture file for reading
pcap_open_offline_with_tstamp_precision (3pcap) - open a saved capture file for reading
pcap_perror (3pcap)  - get or print libpcap error message text
pcap_sendpacket (3pcap) - transmit a packet
pcap_set_buffer_size (3pcap) - set the buffer size for a not-yet-activated capture handle
pcap_set_datalink (3pcap) - set the link-layer header type to be used by a capture device
pcap_set_immediate_mode (3pcap) - set immediate mode for a not-yet-activated capture handle
pcap_set_promisc (3pcap) - set promiscuous mode for a not-yet-activated capture handle
pcap_set_rfmon (3pcap) - set monitor mode for a not-yet-activated capture handle
pcap_set_snaplen (3pcap) - set the snapshot length for a not-yet-activated capture handle
pcap_set_timeout (3pcap) - set the read timeout for a not-yet-activated capture handle
pcap_set_tstamp_precision (3pcap) - set the time stamp precision returned in captures
pcap_set_tstamp_type (3pcap) - set the time stamp type to be used by a capture device
pcap_setdirection (3pcap) - set the direction for which packets will be captured
pcap_setfilter (3pcap) - set the filter
pcap_setnonblock (3pcap) - set or get the state of non-blocking mode on a capture device
pcap_snapshot (3pcap) - get the snapshot length
pcap_stats (3pcap)   - get capture statistics
pcap_statustostr (3pcap) - convert a PCAP_ERROR_ or PCAP_WARNING_ value to a string
pcap_strerror (3pcap) - convert an errno value to a string
pcap_tstamp_type_name_to_val (3pcap) - get the time stamp type value corresponding to a time stamp type name
pcap_tstamp_type_val_to_description (3pcap) - get a name or description for a time stamp type value
pcap_tstamp_type_val_to_name (3pcap) - get a name or description for a time stamp type value

(And BTW there is nothing either to build packets, just to send some)

Now, regarding the idea of raw sockets:

If you want to send and receive TCP and UDP, why not go for TCP and UDP sockets directly?

Finally, look here and google around for networking libraries that will best suits your needs:

Best C/C++ Network Library

Community
  • 1
  • 1
jbm
  • 3,063
  • 1
  • 16
  • 25
  • Thank you jbm, are there any differences in performace, too? I have an old version of the same application I'm working on that uses libpcap, while mine uses raw sockets. I've exeperiecing that mine is somehow faster and shows more packets than the the older (especially when there's a lot of traffic) but I'm not sure if it's a matter of the library or of other implementation choices. – the structure Oct 11 '15 at 11:49
  • The "performance" question is out of topic. You say "I want to grow tomatoes", and ask "I envision to use salad or potato seeds for that, will there be a performance difference?" – jbm Oct 11 '15 at 11:58