Hi there, I've been using BPF to read and write Ethernet packets from the network, however I have encountered issues while writing a test suite for my code. The tests run on the loopback interface, however when calling write(), I received an EAFNOSUPPORT error (looutput: af=0 unexpected). When investigating further my findings were unexpected.
It seems there are three main functions involved with writing packets on the loopback interface using BPF: looutput() from sys/net/if_loop.c; bpfwrite() and bpf_movein() from sys/net/bpf.c. When write()ing, bpf_movein() generates a sockaddr which is later used in looutput(). When using the loopback interface (DLT_NULL), the sa_family field is initialised to AF_UNSPEC, and it specifies a pseudo-header of 4 bytes should exist at the start of the buffer provided to write(). In bpfwrite(), after bpf_movein() has been called, if BIOCSHDRCMPLT has been set, the sa_family field is overwritten with pseudo_AF_HDRCMPLT. After this initial setup, looutput() is called. It handles BPF calls specially, by checking if the sa_family is AF_UNSPEC, and if so treating sa_family as whatever is stored in sa_data. There is then a switch statement, which only handles AF_INET and AF_INET6 packets. This has a number of consequences: * When using BPF on the loopback interface, the first 4 bytes of the buffer being sent are used for a pseudo-header. This pseudo-header remains in-tact when receiving, so the loopback interface must be special-cased for sending/receiving (alternatively a corrupt packet is sent/received, depending on how you look at it). * The need for any kind of pseudo-header is undocumented in the BPF man pages. It is mentioned briefly in the pcap man pages. * When BIOSHDRCMPLT is set, BPF cannot work on the loopback interface (since looutput() checks for AF_UNSPEC, but sa_family is pseudo_AF_HDRCMPLT). So my question is, what is the best way to test data link protocols with BPF offline with FreeBSD? My current ideas: * Special-case the loopback interface to add the pseudo-header and remove the BIOCSHDRCMPLT ioctl() (intresting note here: the ioctl() call does not fail, despite the option being invalid). * Modify the loopback device to support data link protocols properly, without the need for a pseudo-header (of course this would break backwards compatability). * Create an additional type of loopback interface designed to emulate other data link protocols. Your input would be appreciated. Thanks, Robert _______________________________________________ freebsd-net@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/freebsd-net To unsubscribe, send any mail to "freebsd-net-unsubscr...@freebsd.org"