15#include <net/ethernet.h> 
   16#include <linux/filter.h> 
   17#include <linux/if_ether.h> 
   18#include <linux/if_packet.h> 
   46struct sock_filter dhcp_sock_filter [] = {
 
   53    BPF_STMT(BPF_LD + BPF_H + BPF_ABS, ETHERNET_PACKET_TYPE_OFFSET),
 
   55    BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ETHERTYPE_IP, 0, 11),
 
   61    BPF_STMT(BPF_LD + BPF_B + BPF_ABS,
 
   62             ETHERNET_HEADER_LEN + IP_PROTO_TYPE_OFFSET),
 
   64    BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, IPPROTO_UDP, 0, 9),
 
   72    BPF_STMT(BPF_LD + BPF_H + BPF_ABS, ETHERNET_HEADER_LEN + IP_FLAGS_OFFSET),
 
   74    BPF_JUMP(BPF_JMP + BPF_JSET + BPF_K, 0x1fff, 7, 0),
 
   84    BPF_STMT(BPF_LD + BPF_W + BPF_ABS,
 
   85             ETHERNET_HEADER_LEN + IP_DEST_ADDR_OFFSET),
 
   88    BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0xffffffff, 1, 0),
 
   92    BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x00000000, 0, 4),
 
   98    BPF_STMT(BPF_LDX + BPF_B + BPF_MSH, ETHERNET_HEADER_LEN),
 
  106    BPF_STMT(BPF_LD + BPF_H + BPF_IND, ETHERNET_HEADER_LEN + UDP_DEST_PORT),
 
  113    BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, DHCP4_SERVER_PORT, 0, 1),
 
  117    BPF_STMT(BPF_RET + BPF_K, (u_int)-1),
 
  121    BPF_STMT(BPF_RET + BPF_K, 0),
 
  143                         const uint16_t port, 
const bool,
 
  152    int sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
 
  159    if (fcntl(sock, F_SETFD, FD_CLOEXEC) < 0) {
 
  163                  << 
" on the socket " << sock);
 
  169    struct sock_fprog filter_program;
 
  170    memset(&filter_program, 0, 
sizeof(filter_program));
 
  172    filter_program.filter = dhcp_sock_filter;
 
  173    filter_program.len = 
sizeof(dhcp_sock_filter) / 
sizeof(
struct sock_filter);
 
  178    dhcp_sock_filter[8].k = addr.
toUint32();
 
  181    dhcp_sock_filter[11].k = port;
 
  183    if (setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER, &filter_program,
 
  184                   sizeof(filter_program)) < 0) {
 
  188                  << 
" on the socket " << sock);
 
  193    if (setsockopt(sock, SOL_SOCKET, SO_TIMESTAMP, &enable, 
sizeof(enable))) {
 
  194        const char* errmsg = strerror(errno);
 
  196                  << 
", error: " << errmsg);
 
  200    struct sockaddr_ll sa;
 
  201    memset(&sa, 0, 
sizeof(sockaddr_ll));
 
  202    sa.sll_family = AF_PACKET;
 
  209    if (bind(sock, 
reinterpret_cast<const struct sockaddr*
>(&sa),
 
  214                  << 
"' to interface '" << iface.
getName() << 
"'");
 
  218    if (fcntl(sock, F_SETFL, O_NONBLOCK) != 0) {
 
  221        char* errmsg = strerror(errno);
 
  225                  " LPF socket '" << sock << 
"' to interface '" 
  226                  << iface.
getName() << 
"', reason: " << errmsg);
 
  229    return (
SocketInfo(addr, port, sock, fallback));
 
 
  252        datalen = recv(socket_info.
fallbackfd_, raw_buf, 
sizeof(raw_buf), 0);
 
  253    } 
while (datalen > 0);
 
  258    int data_len = read(socket_info.
sockfd_, raw_buf, 
sizeof(raw_buf));
 
  270    const size_t CONTROL_BUF_LEN = 512;
 
  272    uint8_t control_buf[CONTROL_BUF_LEN];
 
  274    memset(&control_buf[0], 0, CONTROL_BUF_LEN);
 
  278    memset(&m, 0, 
sizeof(m));
 
  281    v.iov_base = 
static_cast<void*
>(msg_buf);
 
  292    m.msg_control = &control_buf[0];
 
  293    m.msg_controllen = CONTROL_BUF_LEN;
 
  295    int result = recvmsg(socket_info.
sockfd_, &m, 0);
 
  327    std::vector<uint8_t> dhcp_buf;
 
  336    pkt->setIface(iface.
getName());
 
  337    pkt->setLocalAddr(dummy_pkt->getLocalAddr());
 
  338    pkt->setRemoteAddr(dummy_pkt->getRemoteAddr());
 
  339    pkt->setLocalPort(dummy_pkt->getLocalPort());
 
  340    pkt->setRemotePort(dummy_pkt->getRemotePort());
 
  341    pkt->setLocalHWAddr(dummy_pkt->getLocalHWAddr());
 
  342    pkt->setRemoteHWAddr(dummy_pkt->getRemoteHWAddr());
 
  345    struct cmsghdr* cmsg = CMSG_FIRSTHDR(&m);
 
  346    while (cmsg != NULL) {
 
  347        if ((cmsg->cmsg_level == SOL_SOCKET) &&
 
  348            (cmsg->cmsg_type  == SCM_TIMESTAMP)) {
 
  350            struct timeval cmsg_time;
 
  351            memcpy(&cmsg_time, CMSG_DATA(cmsg), 
sizeof(cmsg_time));
 
  356        cmsg = CMSG_NXTHDR(&m, cmsg);
 
 
  379        pkt->setLocalHWAddr(hwaddr);
 
  392    buf.
writeData(pkt->getBuffer().getData(), pkt->getBuffer().getLength());
 
  395    memset(&sa, 0x0, 
sizeof(sa));
 
  396    sa.sll_family = AF_PACKET;
 
  398    sa.sll_protocol = htons(ETH_P_IP);
 
  403                        reinterpret_cast<const struct sockaddr*
>(&sa),
 
  404                        sizeof(sockaddr_ll));
 
  407                  << errno << 
" (check errno.h)");
 
 
The IOAddress class represents an IP addresses (version agnostic)
std::string toText() const
Convert the address to a string.
uint32_t toUint32() const
Converts IPv4 address to uint32_t.
static const uint32_t RCVBUFSIZE
Packet reception buffer size.
Represents a single network interface.
size_t getMacLen() const
Returns MAC length.
std::string getName() const
Returns interface name.
uint16_t getHWType() const
Returns hardware type of the interface.
unsigned int getIndex() const
Returns interface index.
const uint8_t * getMac() const
Returns pointer to MAC address.
Represents DHCPv4 packet.
static const std::string BUFFER_READ
Event that marks when a packet is read from the socket buffer by application.
static const std::string SOCKET_RECEIVED
Event that marks when a packet is placed in the socket buffer by the kernel.
static const std::string RESPONSE_SENT
Event that marks when a packet is been written to the socket by application.
virtual bool isSocketReceivedTimeSupported() const
Check if the socket received time is supported.
virtual int send(const Iface &iface, uint16_t sockfd, const Pkt4Ptr &pkt)
Send packet over specified socket.
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 openFallbackSocket(const isc::asiolink::IOAddress &addr, const uint16_t port)
Default implementation to open a fallback socket.
IfaceMgr exception thrown thrown when socket opening or configuration failed.
IfaceMgr exception thrown thrown when error occurred during reading data from socket.
IfaceMgr exception thrown thrown when error occurred during sending data through socket.
The OutputBuffer class is a buffer abstraction for manipulating mutable data.
void writeData(const void *data, size_t len)
Copy an arbitrary length of data into the buffer.
const uint8_t * getData() const
Return a pointer to the head of the data stored in the buffer.
size_t getLength() const
Return the length of data written in the buffer.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
boost::shared_ptr< Pkt4 > Pkt4Ptr
A pointer to Pkt4 object.
void decodeEthernetHeader(InputBuffer &buf, Pkt4Ptr &pkt)
Decode the Ethernet header.
void writeEthernetHeader(const Pkt4Ptr &pkt, OutputBuffer &out_buf)
Writes ethernet frame header into a buffer.
void decodeIpUdpHeader(InputBuffer &buf, Pkt4Ptr &pkt)
Decode IP and UDP header.
boost::shared_ptr< HWAddr > HWAddrPtr
Shared pointer to a hardware address structure.
void writeIpUdpHeader(const Pkt4Ptr &pkt, util::OutputBuffer &out_buf)
Writes both IP and UDP header into output buffer.
Defines the logger used by the top-level component of kea-lfc.
Hardware type that represents information from DHCPv4 packet.
Holds information about socket.
int fallbackfd_
Fallback socket descriptor.