From: Marcin Siodelski Date: Tue, 16 Apr 2013 22:24:01 +0000 (-0700) Subject: [2902] Moved protocol utility functions to a separate file. X-Git-Tag: bind10-1.2.0beta1-release~440^2~34 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=edd0b0623481ea70b4af23a0cbd2bb4ef797d10f;p=thirdparty%2Fkea.git [2902] Moved protocol utility functions to a separate file. --- diff --git a/src/lib/dhcp/Makefile.am b/src/lib/dhcp/Makefile.am index 1e292bdb57..ab702d8fc1 100644 --- a/src/lib/dhcp/Makefile.am +++ b/src/lib/dhcp/Makefile.am @@ -33,6 +33,7 @@ libb10_dhcp___la_SOURCES += option_custom.cc option_custom.h 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 diff --git a/src/lib/dhcp/pkt_filter_lpf.cc b/src/lib/dhcp/pkt_filter_lpf.cc index e0a4616552..4070c9b5cc 100644 --- a/src/lib/dhcp/pkt_filter_lpf.cc +++ b/src/lib/dhcp/pkt_filter_lpf.cc @@ -16,94 +16,17 @@ #include #include #include +#include #include #include #include -#include -#include using namespace isc::util; namespace isc { namespace dhcp { -void -PktFilterLPF::assembleEthernetHeader(const Iface& iface, - const Pkt4Ptr& pkt, - util::OutputBuffer& out_buf) { - - std::vector 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(&ip_hdr), - sizeof(ip_hdr))); - - out_buf.writeData(static_cast(&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(&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 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; diff --git a/src/lib/dhcp/protocol_util.cc b/src/lib/dhcp/protocol_util.cc new file mode 100644 index 0000000000..eb8209a625 --- /dev/null +++ b/src/lib/dhcp/protocol_util.cc @@ -0,0 +1,94 @@ +// 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 + +#include +#include + +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(&ip_hdr), + sizeof(ip_hdr))); + + out_buf.writeData(static_cast(&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(&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)); +} + +} +} diff --git a/src/lib/dhcp/protocol_util.h b/src/lib/dhcp/protocol_util.h new file mode 100644 index 0000000000..0c8ae132a4 --- /dev/null +++ b/src/lib/dhcp/protocol_util.h @@ -0,0 +1,65 @@ +// 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 +#include + +#include + +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