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.