15 #include <net/ethernet.h>
16 #include <linux/filter.h>
17 #include <linux/if_ether.h>
18 #include <linux/if_packet.h>
46 struct 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),
132 PktFilterLPF::openSocket(
Iface& iface,
134 const uint16_t port,
const bool,
141 int fallback = openFallbackSocket(addr, port);
144 int sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
151 if (fcntl(sock, F_SETFD, FD_CLOEXEC) < 0) {
155 <<
" on the socket " << sock);
161 struct sock_fprog filter_program;
162 memset(&filter_program, 0,
sizeof(filter_program));
164 filter_program.filter = dhcp_sock_filter;
165 filter_program.len =
sizeof(dhcp_sock_filter) /
sizeof(
struct sock_filter);
170 dhcp_sock_filter[8].k = addr.
toUint32();
173 dhcp_sock_filter[11].k = port;
175 if (setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER, &filter_program,
176 sizeof(filter_program)) < 0) {
180 <<
" on the socket " << sock);
183 struct sockaddr_ll sa;
184 memset(&sa, 0,
sizeof(sockaddr_ll));
185 sa.sll_family = AF_PACKET;
192 if (bind(sock, reinterpret_cast<const struct sockaddr*>(&sa),
197 <<
"' to interface '" << iface.
getName() <<
"'");
201 if (fcntl(sock, F_SETFL, O_NONBLOCK) != 0) {
204 char* errmsg = strerror(errno);
208 " LPF socket '" << sock <<
"' to interface '"
209 << iface.
getName() <<
"'" <<
", reason: " << errmsg);
212 return (
SocketInfo(addr, port, sock, fallback));
218 uint8_t raw_buf[IfaceMgr::RCVBUFSIZE];
235 datalen = recv(socket_info.
fallbackfd_, raw_buf,
sizeof(raw_buf), 0);
236 }
while (datalen > 0);
240 int data_len = read(socket_info.
sockfd_, raw_buf,
sizeof(raw_buf));
271 std::vector<uint8_t> dhcp_buf;
280 pkt->setIface(iface.
getName());
281 pkt->setLocalAddr(dummy_pkt->getLocalAddr());
282 pkt->setRemoteAddr(dummy_pkt->getRemoteAddr());
283 pkt->setLocalPort(dummy_pkt->getLocalPort());
284 pkt->setRemotePort(dummy_pkt->getRemotePort());
285 pkt->setLocalHWAddr(dummy_pkt->getLocalHWAddr());
286 pkt->setRemoteHWAddr(dummy_pkt->getRemoteHWAddr());
292 PktFilterLPF::send(
const Iface& iface, uint16_t sockfd,
const Pkt4Ptr& pkt) {
304 pkt->setLocalHWAddr(hwaddr);
317 buf.
writeData(pkt->getBuffer().getData(), pkt->getBuffer().getLength());
320 memset(&sa, 0x0,
sizeof(sa));
321 sa.sll_family = AF_PACKET;
323 sa.sll_protocol = htons(ETH_P_IP);
327 reinterpret_cast<const struct sockaddr*
>(&sa),
328 sizeof(sockaddr_ll));
331 << errno <<
" (check errno.h)");
uint32_t toUint32() const
Converts IPv4 address to uint32_t.
void writeEthernetHeader(const Pkt4Ptr &pkt, OutputBuffer &out_buf)
Writes ethernet frame header into a buffer.
IfaceMgr exception thrown thrown when socket opening or configuration failed.
const void * getData() const
Return a pointer to the head of the data stored in the buffer.
int fallbackfd_
Fallback socket descriptor.
boost::shared_ptr< HWAddr > HWAddrPtr
Shared pointer to a hardware address structure.
uint32_t getIndex() const
Returns interface index.
size_t getMacLen() const
Returns MAC length.
Represents a single network interface.
uint16_t getHWType() const
Returns hardware type of the interface.
void decodeEthernetHeader(InputBuffer &buf, Pkt4Ptr &pkt)
Decode the Ethernet header.
void writeData(const void *data, size_t len)
Copy an arbitrary length of data into the buffer.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
void writeIpUdpHeader(const Pkt4Ptr &pkt, util::OutputBuffer &out_buf)
Writes both IP and UDP header into output buffer.
boost::shared_ptr< Pkt4 > Pkt4Ptr
A pointer to Pkt4 object.
const uint8_t * getMac() const
Returns pointer to MAC address.
The OutputBuffer class is a buffer abstraction for manipulating mutable data.
std::string getName() const
Returns interface name.
Defines the logger used by the top-level component of kea-dhcp-ddns.
Represents DHCPv4 packet.
Hardware type that represents information from DHCPv4 packet.
The IOAddress class represents an IP addresses (version agnostic)
size_t getLength() const
Return the length of data written in the buffer.
IfaceMgr exception thrown thrown when error occurred during sending data through socket.
Holds information about socket.
void decodeIpUdpHeader(InputBuffer &buf, Pkt4Ptr &pkt)
Decode IP and UDP header.