Kea: isc::dhcp::PktFilterBPF Class Reference

| Kea 2.2.0

Public Member Functions | List of all members
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:
[legend]

## Public Member Functions
virtual bool | isDirectResponseSupported () const
| Check if packet can be sent to the host without address directly. More...
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. More...
virtual Pkt4Ptr | receive (Iface &iface, const SocketInfo &socket_info)
| Receive packet over specified socket. More...
virtual int | send (const Iface &iface, uint16_t sockfd, const Pkt4Ptr &pkt)
| Send packet over specified socket. More...
Public Member Functions inherited from isc::dhcp::PktFilter
virtual | ~PktFilter ()
| Virtual Destructor. More...
virtual bool | isDirectResponseSupported () const =0
| Check if packet can be sent to the host without address directly. More...
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. More...
virtual Pkt4Ptr | receive (Iface &iface, const SocketInfo &socket_info)=0
| Receive packet over specified socket. More...
virtual int | send (const Iface &iface, uint16_t sockfd, const Pkt4Ptr &pkt)=0
| Send packet over specified socket. More...

## 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. More...

## 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.

## ◆ 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

  iface | Interface descriptor. Note that the function (re)allocates the socket read buffer according to the buffer size returned by the kernel.
  addr | Address on the interface to be used to send packets.
  port | Port number.
  receive_bcast | Configure socket to receive broadcast messages
  send_bcast | Configure socket to send broadcast messages.

Returns
  A structure describing a primary and fallback socket.

Implements isc::dhcp::PktFilter.

Definition at line 225 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

  iface | interface
  socket_info | structure 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 383 of file pkt_filter_bpf.cc.

References 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(), 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

  iface | interface to be used to send packet
  sockfd | socket descriptor
  pkt | packet to be sent

Returns
  result of sending a packet. It is 0 if successful.

Implements isc::dhcp::PktFilter.

Definition at line 544 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::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:

- pkt_filter_bpf.h
- pkt_filter_bpf.cc