|
@@ -16,94 +16,17 @@
|
|
|
#include <dhcp/iface_mgr.h>
|
|
|
#include <dhcp/pkt4.h>
|
|
|
#include <dhcp/pkt_filter_lpf.h>
|
|
|
+#include <dhcp/protocol_util.h>
|
|
|
#include <exceptions/exceptions.h>
|
|
|
|
|
|
#include <linux/if_ether.h>
|
|
|
#include <linux/if_packet.h>
|
|
|
-#include <netinet/ip.h>
|
|
|
-#include <netinet/udp.h>
|
|
|
|
|
|
using namespace isc::util;
|
|
|
|
|
|
namespace isc {
|
|
|
namespace dhcp {
|
|
|
|
|
|
-void
|
|
|
-PktFilterLPF::assembleEthernetHeader(const Iface& iface,
|
|
|
- const Pkt4Ptr& pkt,
|
|
|
- util::OutputBuffer& out_buf) {
|
|
|
-
|
|
|
- std::vector<uint8_t> dest_addr = pkt->getHWAddr()->hwaddr_;
|
|
|
- if (dest_addr.empty()) {
|
|
|
- dest_addr.resize(HWAddr::ETHERNET_HWADDR_LEN);
|
|
|
- }
|
|
|
- out_buf.writeData(&dest_addr[0], dest_addr.size());
|
|
|
- out_buf.writeData(iface.getMac(), iface.getMacLen());
|
|
|
-
|
|
|
- out_buf.writeUint16(0x0800);
|
|
|
-}
|
|
|
-
|
|
|
-void
|
|
|
-PktFilterLPF::assembleIpUdpHeader(const Pkt4Ptr& pkt,
|
|
|
- util::OutputBuffer& out_buf) {
|
|
|
-
|
|
|
- struct ip ip_hdr;
|
|
|
- memset(&ip_hdr, 0, sizeof(ip_hdr));
|
|
|
- ip_hdr.ip_hl = (ip_hdr.ip_hl | 5) & 0xF;
|
|
|
- ip_hdr.ip_v = (ip_hdr.ip_v | 4) & 0xF;
|
|
|
- ip_hdr.ip_tos = IPTOS_LOWDELAY;
|
|
|
- ip_hdr.ip_len = htons(sizeof(ip) + sizeof(udphdr) +
|
|
|
- pkt->getBuffer().getLength());
|
|
|
- ip_hdr.ip_id = 0;
|
|
|
- ip_hdr.ip_off = 0;
|
|
|
- ip_hdr.ip_ttl = 128;
|
|
|
- ip_hdr.ip_p = IPPROTO_UDP;
|
|
|
- ip_hdr.ip_src.s_addr = htonl(pkt->getLocalAddr());
|
|
|
- ip_hdr.ip_dst.s_addr = htonl(pkt->getRemoteAddr());
|
|
|
- ip_hdr.ip_sum = checksumFinish(checksum(reinterpret_cast<const char*>(&ip_hdr),
|
|
|
- sizeof(ip_hdr)));
|
|
|
-
|
|
|
- out_buf.writeData(static_cast<void*>(&ip_hdr), sizeof(ip_hdr));
|
|
|
-
|
|
|
- struct udphdr udp_hdr;
|
|
|
- memset(&udp_hdr, 0, sizeof(udp_hdr));
|
|
|
- udp_hdr.source = htons(pkt->getLocalPort());
|
|
|
- udp_hdr.dest = htons(pkt->getRemotePort());
|
|
|
- udp_hdr.len = htons(sizeof(udp_hdr) + pkt->getBuffer().getLength());
|
|
|
- udp_hdr.check = 0;
|
|
|
-
|
|
|
- out_buf.writeData(static_cast<void*>(&udp_hdr), sizeof(udp_hdr));
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-uint16_t
|
|
|
-PktFilterLPF::checksum(const char* buf, const uint32_t buf_size,
|
|
|
- uint32_t sum) {
|
|
|
-
|
|
|
- uint32_t i;
|
|
|
- for (i = 0; i < (buf_size & ~1U); i += 2) {
|
|
|
- uint16_t chunk = buf[i] << 8 | buf[i+1];
|
|
|
- sum += chunk;
|
|
|
- if (sum > 0xFFFF) {
|
|
|
- sum -= 0xFFFF;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (i < buf_size) {
|
|
|
- sum += buf[i] << 8;
|
|
|
- if (sum > 0xFFFF) {
|
|
|
- sum -= 0xFFFF;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return (sum);
|
|
|
-}
|
|
|
-
|
|
|
-uint16_t
|
|
|
-PktFilterLPF::checksumFinish(uint16_t sum) {
|
|
|
- return (htons(~sum));
|
|
|
-}
|
|
|
-
|
|
|
int
|
|
|
PktFilterLPF::openSocket(const Iface& iface, const isc::asiolink::IOAddress&,
|
|
|
const uint16_t, const bool,
|
|
@@ -131,9 +54,19 @@ PktFilterLPF::openSocket(const Iface& iface, const isc::asiolink::IOAddress&,
|
|
|
}
|
|
|
|
|
|
Pkt4Ptr
|
|
|
-PktFilterLPF::receive(const Iface&, const SocketInfo&) {
|
|
|
- isc_throw(isc::NotImplemented,
|
|
|
- "Linux Packet Filtering is not implemented yet");
|
|
|
+PktFilterLPF::receive(const Iface&, const SocketInfo& socket_info) {
|
|
|
+ // @todo: implement this function
|
|
|
+ unsigned char buf[1536];
|
|
|
+ int data_len = read(socket_info.sockfd_, buf, sizeof(buf));
|
|
|
+ if (data_len <= 0) {
|
|
|
+ return Pkt4Ptr();
|
|
|
+ }
|
|
|
+
|
|
|
+ // Length of the Ethernet, IP and UDP.
|
|
|
+ int data_offset = 42;
|
|
|
+ Pkt4Ptr pkt = Pkt4Ptr(new Pkt4(buf + data_offset,
|
|
|
+ data_len - data_offset));
|
|
|
+ return (pkt);
|
|
|
}
|
|
|
|
|
|
int
|
|
@@ -141,9 +74,17 @@ PktFilterLPF::send(const Iface& iface, uint16_t sockfd, const Pkt4Ptr& pkt) {
|
|
|
|
|
|
OutputBuffer buf(14);
|
|
|
|
|
|
- assembleEthernetHeader(iface, pkt, buf);
|
|
|
- assembleIpUdpHeader(pkt, buf);
|
|
|
+ // Ethernet frame header
|
|
|
+ std::vector<uint8_t> dest_addr = pkt->getHWAddr()->hwaddr_;
|
|
|
+ if (dest_addr.empty()) {
|
|
|
+ dest_addr.resize(HWAddr::ETHERNET_HWADDR_LEN);
|
|
|
+ }
|
|
|
+ writeEthernetHeader(iface.getMac(), &dest_addr[0], buf);
|
|
|
+
|
|
|
+ // IP and UDP header
|
|
|
+ writeIpUdpHeader(pkt, buf);
|
|
|
|
|
|
+ // DHCPv4 message
|
|
|
buf.writeData(pkt->getBuffer().getData(), pkt->getBuffer().getLength());
|
|
|
|
|
|
sockaddr_ll sa;
|