Kea 2.5.8
isc::dhcp::PktFilterBPF Class Reference

Packet handling class using Berkeley Packet Filtering (BPF) More...

#include <pkt_filter_bpf.h>

+ Inheritance diagram for isc::dhcp::PktFilterBPF:

Public Member Functions

virtual bool isDirectResponseSupported () const
 Check if packet can be sent to the host without address directly.
 
virtual bool isSocketReceivedTimeSupported () const
 Check if the socket received time is supported.
 
virtual SocketInfo openSocket (Iface &iface, const isc::asiolink::IOAddress &addr, const uint16_t port, const bool receive_bcast, const bool send_bcast)
 Open primary and fallback socket.
 
virtual Pkt4Ptr receive (Iface &iface, const SocketInfo &socket_info)
 Receive packet over specified socket.
 
virtual int send (const Iface &iface, uint16_t sockfd, const Pkt4Ptr &pkt)
 Send packet over specified socket.
 
- Public Member Functions inherited from isc::dhcp::PktFilter
virtual ~PktFilter ()
 Virtual Destructor.
 
virtual bool isDirectResponseSupported () const =0
 Check if packet can be sent to the host without address directly.
 
virtual bool isSocketReceivedTimeSupported () const =0
 Check if the socket received time is supported.
 
virtual SocketInfo openSocket (Iface &iface, const isc::asiolink::IOAddress &addr, const uint16_t port, const bool receive_bcast, const bool send_bcast)=0
 Open primary and fallback socket.
 
virtual Pkt4Ptr receive (Iface &iface, const SocketInfo &socket_info)=0
 Receive packet over specified socket.
 
virtual int send (const Iface &iface, uint16_t sockfd, const Pkt4Ptr &pkt)=0
 Send packet over specified socket.
 

Additional Inherited Members

- Protected Member Functions inherited from isc::dhcp::PktFilter
virtual int openFallbackSocket (const isc::asiolink::IOAddress &addr, const uint16_t port)
 Default implementation to open a fallback socket.
 

Detailed Description

Packet handling class using Berkeley Packet Filtering (BPF)

The BPF is supported on the BSD-like operating systems. It allows for access to low level layers of the inbound and outbound packets. This is specifically useful when the DHCP server is allocating new address to the client.

The response being sent to the client must include the HW address in the datalink layer. When the regular datagram socket is used the kernel will determine the HW address of the destination using ARP. In the case when the DHCP server is allocating the new address for the client the ARP can't be used because it requires the destination to have the IP address.

The DHCP server utilizes HW address sent by the client in the DHCP message and stores it in the datalink layer of the outbound packet. The BPF provides the means for crafting the whole packet (including datalink and network layers) and injecting the hardware address of the client.

The DHCP server receiving the messages sent from the directly connected clients to the broadcast address must be able to determine the interface on which the message arrives. The Linux kernel provides the SO_BINDTODEVICE socket option which allows for binding the socket to the particular interface. This option is not implemented on the BSD-like operating systems. This implies that there may be only one datagram socket listening to broadcast messages and this socket would receive the traffic on all interfaces. This effectively precludes the server from identifying the interface on which the packet arrived. The BPF resolves this problem. The BPF device (socket) can be attached to the selected interface using the ioctl function.

In nutshell, the BPF device is created by opening the file /dev/bpfd where d is a number. The BPF device is configured by issuing ioctl commands listed here: http://www.freebsd.org/cgi/man.cgi?bpf(4). The specific configuration used by Kea DHCP server is described in documentation of PktFilterBPF::openSocket.

Use of BPF requires Kea to encode and decode the datalink and network layer headers. Currently Kea supports encoding and decoding ethernet frames on physical interfaces and pseudo headers received on local loopback interface.

Definition at line 56 of file pkt_filter_bpf.h.

Member Function Documentation

◆ isDirectResponseSupported()

virtual bool isc::dhcp::PktFilterBPF::isDirectResponseSupported ( ) const
inlinevirtual

Check if packet can be sent to the host without address directly.

This class supports direct responses to the host without address.

Returns
true always.

Implements isc::dhcp::PktFilter.

Definition at line 64 of file pkt_filter_bpf.h.

◆ isSocketReceivedTimeSupported()

virtual bool isc::dhcp::PktFilterBPF::isSocketReceivedTimeSupported ( ) const
inlinevirtual

Check if the socket received time is supported.

Returns
true always.

Implements isc::dhcp::PktFilter.

Definition at line 71 of file pkt_filter_bpf.h.

◆ openSocket()

SocketInfo isc::dhcp::PktFilterBPF::openSocket ( Iface iface,
const isc::asiolink::IOAddress addr,
const uint16_t  port,
const bool  receive_bcast,
const bool  send_bcast 
)
virtual

Open primary and fallback socket.

This method opens the BPF device and applies the following configuration to it:

  • attach the device to the specified interface
  • set filter program to receive DHCP messages encapsulated in UDP packets
  • set immediate mode which causes the read function to return immediately and do not wait for the whole read buffer to be filled by the kernel (to avoid hangs)

It also obtains the following configuration from the kernel:

  • major and minor version of the BPF (and checks if it is valid)
  • length of the buffer to be used to receive the data from the socket
Parameters
ifaceInterface descriptor. Note that the function (re)allocates the socket read buffer according to the buffer size returned by the kernel.
addrAddress on the interface to be used to send packets.
portPort number.
receive_bcastConfigure socket to receive broadcast messages
send_bcastConfigure socket to send broadcast messages.
Returns
A structure describing a primary and fallback socket.

Implements isc::dhcp::PktFilter.

Definition at line 226 of file pkt_filter_bpf.cc.

References isc::dhcp::Iface::flag_loopback_, isc::dhcp::Iface::getName(), isc_throw, isc::dhcp::PktFilter::openFallbackSocket(), isc::dhcp::Iface::resizeReadBuffer(), and isc::asiolink::IOAddress::toUint32().

+ Here is the call graph for this function:

◆ receive()

Pkt4Ptr isc::dhcp::PktFilterBPF::receive ( Iface iface,
const SocketInfo socket_info 
)
virtual

Receive packet over specified socket.

Parameters
ifaceinterface
socket_infostructure holding socket information
Returns
Received packet
Todo:
BPF may occasionally append more than one packet in a single read. Our current libdhcp++ API is oriented towards receiving one packet at the time so we just pick first usable packet here and drop other packets. In the future the additional packets should be queued and processed. For now, we just iterate over the packets in the buffer and pick the first usable one.

Implements isc::dhcp::PktFilter.

Definition at line 384 of file pkt_filter_bpf.cc.

References isc::dhcp::PktEvent::BUFFER_READ, isc::dhcp::decodeEthernetHeader(), isc::dhcp::decodeIpUdpHeader(), isc::dhcp::DHCPDISCOVER, isc::dhcp::SocketInfo::fallbackfd_, isc::dhcp::Iface::flag_loopback_, isc::dhcp::Iface::getIndex(), isc::util::InputBuffer::getLength(), isc::dhcp::Iface::getName(), isc::util::InputBuffer::getPosition(), isc::dhcp::Iface::getReadBuffer(), isc::dhcp::Iface::getReadBufferSize(), isc_throw, isc::util::InputBuffer::readVector(), isc::util::InputBuffer::setPosition(), isc::dhcp::PktEvent::SOCKET_RECEIVED, and isc::dhcp::SocketInfo::sockfd_.

+ Here is the call graph for this function:

◆ send()

int isc::dhcp::PktFilterBPF::send ( const Iface iface,
uint16_t  sockfd,
const Pkt4Ptr pkt 
)
virtual

Send packet over specified socket.

Parameters
ifaceinterface to be used to send packet
sockfdsocket descriptor
pktpacket to be sent
Returns
result of sending a packet. It is 0 if successful.

Implements isc::dhcp::PktFilter.

Definition at line 561 of file pkt_filter_bpf.cc.

References isc::dhcp::Iface::flag_loopback_, isc::util::OutputBuffer::getData(), isc::dhcp::Iface::getHWType(), isc::util::OutputBuffer::getLength(), isc::dhcp::Iface::getMac(), isc::dhcp::Iface::getMacLen(), isc_throw, isc::dhcp::PktEvent::RESPONSE_SENT, isc::util::OutputBuffer::writeData(), isc::dhcp::writeEthernetHeader(), and isc::dhcp::writeIpUdpHeader().

+ Here is the call graph for this function:

The documentation for this class was generated from the following files: