libb10_dhcp___la_SOURCES += option_data_types.cc option_data_types.h
libb10_dhcp___la_SOURCES += option_definition.cc option_definition.h
libb10_dhcp___la_SOURCES += option_space.cc option_space.h
+libb10_dhcp___la_SOURCES += protocol_util.cc protocol_util.h
libb10_dhcp___la_SOURCES += pkt6.cc pkt6.h
libb10_dhcp___la_SOURCES += pkt4.cc pkt4.h
libb10_dhcp___la_SOURCES += pkt_filter.h
#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,
}
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
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;
--- /dev/null
+// Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <protocol_util.h>
+
+#include <netinet/ip.h>
+#include <netinet/udp.h>
+
+namespace isc {
+namespace dhcp {
+
+void
+writeEthernetHeader(const uint8_t* src_hw_addr, const uint8_t* dest_hw_addr,
+ util::OutputBuffer& out_buf) {
+ // Write destination and source address.
+ out_buf.writeData(dest_hw_addr, HWAddr::ETHERNET_HWADDR_LEN);
+ out_buf.writeData(src_hw_addr, HWAddr::ETHERNET_HWADDR_LEN);
+ // Type IP.
+ out_buf.writeUint16(0x0800);
+}
+
+void
+writeIpUdpHeader(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 =
+ wrapChecksum(calculateChecksum(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
+calculateChecksum(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
+wrapChecksum(uint16_t sum) {
+ return (htons(~sum));
+}
+
+}
+}
--- /dev/null
+// Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#ifndef PROTOCOL_UTIL_H
+#define PROTOCOL_UTIL_H
+
+#include <dhcp/pkt4.h>
+#include <util/buffer.h>
+
+#include <stdint.h>
+
+namespace isc {
+namespace dhcp {
+
+/// @brief Writes ethernet frame header into a buffer.
+///
+/// @param src_hw_addr source HW address.
+/// @param dst_hw_addr destination HW address.
+/// @param [out] out_buf buffer where a header is written.
+void writeEthernetHeader(const uint8_t* src_hw_addr,
+ const uint8_t* dest_hw_addr,
+ util::OutputBuffer& out_buf);
+
+/// @brief Writes both IP and UDP header into output buffer
+///
+/// This utility function assembles IP and UDP packet headers for the
+/// provided DHCPv4 message. The source and destination addreses and
+/// ports stored in the Pkt4 object are copied as source and destination
+/// addresses and ports into IP/UDP headers.
+///
+/// @param pkt DHCPv4 packet to be sent in IP packet
+/// @param [out] out_buf buffer where an IP header is written
+void writeIpUdpHeader(const Pkt4Ptr& pkt, util::OutputBuffer& out_buf);
+
+/// @brief Calculates checksum for provided buffer
+///
+/// @param buf buffer for which the checksum is calculated.
+/// @param buf_size size of the buffer for which checksum is calculated.
+/// @param sum initial checksum value.
+///
+/// @return calculated checksum.
+uint16_t calculateChecksum(const char* buf, const uint32_t buf_size,
+ uint32_t sum = 0);
+
+/// @brief Wraps the calculated checksum and stores it in network byte order.
+///
+/// @param sum calculated checksum
+///
+/// @return wrapped checksum value.
+uint16_t wrapChecksum(uint16_t sum);
+
+}
+}
+#endif // PROTOCOL_UTIL_H