From owner-freebsd-net@FreeBSD.ORG Thu Jul 31 17:39:16 2014 Return-Path: Delivered-To: freebsd-net@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id BF48F3BE for ; Thu, 31 Jul 2014 17:39:16 +0000 (UTC) Received: from mail-we0-f169.google.com (mail-we0-f169.google.com [74.125.82.169]) (using TLSv1 with cipher ECDHE-RSA-RC4-SHA (128/128 bits)) (Client CN "smtp.gmail.com", Issuer "Google Internet Authority G2" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4D76E2FA5 for ; Thu, 31 Jul 2014 17:39:15 +0000 (UTC) Received: by mail-we0-f169.google.com with SMTP id u56so3127462wes.0 for ; Thu, 31 Jul 2014 10:39:14 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:from:date:message-id:subject:to :content-type; bh=qwrLhlByfV3FK3lEsoitKHndQBYB4IuOBetvrF0V4GY=; b=dxJrzcJi+LL7ARLMzgC3ME5Xp9hDQao7bm7tO6FMul3OFx8VSXbUkXdzx99N6Ro7rK vKG+ZADVxvKPCxKHByraSYoFgr6yKYqYhVOhltwakVY7slVEzADeDxXZXiZCLPm4ojWv 4zsJbYr/0wEGEJTV5yP9sNOKWi/QuSI3TXJZJhmBa1D4gUbpNciZZ8kCVEBvqQbQcu0C sZwIz5HxLaq72L+a0k/u0ZMwsBRS+nCp/V6ihNs9Gj+B8G5JAP/NT5AgbdytXeh9sMyz 5Wh9diUHv3i4PIDohYQRj/DsCJYwSO/yrUIzrVaT1KOf8WZ3NZDhztmU5Ve7YbcUOjqF vkCg== X-Gm-Message-State: ALoCoQkZRJQ+0YKN03vvg7PYFKHNpJ6Hu3nT/3jN1aldE1AtsHtHrkeL2al3CVzXT+DS1NuoCzxv X-Received: by 10.194.243.99 with SMTP id wx3mr18869765wjc.58.1406825199633; Thu, 31 Jul 2014 09:46:39 -0700 (PDT) MIME-Version: 1.0 Received: by 10.217.148.3 with HTTP; Thu, 31 Jul 2014 09:46:19 -0700 (PDT) From: Robert Clipsham Date: Thu, 31 Jul 2014 17:46:19 +0100 Message-ID: Subject: Using the loopback interface with BPF To: freebsd-net@freebsd.org Content-Type: text/plain; charset=UTF-8 X-Content-Filtered-By: Mailman/MimeDel 2.1.18 X-BeenThere: freebsd-net@freebsd.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Networking and TCP/IP with FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 31 Jul 2014 17:39:16 -0000 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