From f621cbc7246f944aed3b0739dc5a5d793ab85731 Mon Sep 17 00:00:00 2001 From: Santiago Alessandri Date: Fri, 12 Aug 2011 12:01:58 -0300 Subject: [PATCH] Added options to IP PDU --- include/ip.h | 69 ++++++++++++++++++++++++++++++++++++++++++++++----- src/ip.cpp | 70 ++++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 125 insertions(+), 14 deletions(-) diff --git a/include/ip.h b/include/ip.h index 58c214f..3df9b05 100644 --- a/include/ip.h +++ b/include/ip.h @@ -1,19 +1,19 @@ /* - * libtins is a net packet wrapper library for crafting and + * libtins is a net packet wrapper library for crafting and * interpreting sniffed packets. - * + * * Copyright (C) 2011 Nasel - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -26,12 +26,41 @@ #include #endif #include +#include +#include #include "pdu.h" namespace Tins { class IP : public PDU { public: + enum OptionClass { + CONTROL = 0, + MEASUREMENT = 2 + }; + + enum OptionNumber { + IPOPT_END = 0, + IPOPT_NOOP = 1, + IPOPT_SEC = 2, + IPOPT_LSSR = 3, + IPOPT_TIMESTAMP = 4, + IPOPT_EXTSEC = 5, + IPOPT_RR = 7, + IPOPT_SID = 8, + IPOPT_SSRR = 9, + IPOPT_MTUPROBE = 11, + IPOPT_MTUREPLY = 12, + IPOPT_EIP = 17, + IPOPT_TR = 18, + IPOPT_ADDEXT = 19, + IPOPT_RTRALT = 20, + IPOPT_SDB = 21, + IPOPT_DPS = 23, + IPOPT_UMP = 24, + IPOPT_QS = 25 + }; + IP(const std::string &ip_dst = "", const std::string &ip_src = "", PDU *child = 0); IP(uint32_t ip_dst = 0, uint32_t ip_src = 0, PDU *child = 0); @@ -56,6 +85,12 @@ namespace Tins { void source_address(uint32_t ip); void dest_address(const std::string &ip); void dest_address(uint32_t ip); + void set_option(uint8_t copied, OptionClass op_class, OptionNumber number, uint8_t* data = 0, uint32_t data_size = 0); + + void set_option_eol(); + void set_option_noop(); + void set_option_sec(uint8_t* data, uint32_t data_len); + /* Add more option setters */ /* Virtual methods */ uint32_t header_size() const; @@ -81,7 +116,26 @@ namespace Tins { uint32_t saddr; uint32_t daddr; /*The options start here. */ - } __attribute__((packed)); + } __attribute__((__packed__)); + + struct IpOption { + struct { + #if __BYTE_ORDER == __LITTLE_ENDIAN + unsigned int number:5; + unsigned int op_class:2; + unsigned int copied:1; + #elif __BYTE_ORDER == __BIG_ENDIAN + unsigned int copied:1; + unsigned int op_class:2; + unsigned int number:5; + #endif + } type; + uint8_t* optional_data; + uint32_t optional_data_size; + + uint8_t* write(uint8_t* buffer); + + } __attribute__((__packed__)); static const uint8_t DEFAULT_TTL; @@ -89,6 +143,9 @@ namespace Tins { void write_serialization(uint8_t *buffer, uint32_t total_sz); iphdr _ip; + std::vector _ip_options; + uint32_t _options_size; + uint32_t _padded_options_size; }; }; diff --git a/src/ip.cpp b/src/ip.cpp index a7b2316..9aecd3b 100644 --- a/src/ip.cpp +++ b/src/ip.cpp @@ -1,19 +1,19 @@ /* - * libtins is a net packet wrapper library for crafting and + * libtins is a net packet wrapper library for crafting and * interpreting sniffed packets. - * + * * Copyright (C) 2011 Nasel - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -53,6 +53,7 @@ void Tins::IP::init_ip_fields() { _ip.version = 4; _ip.ihl = sizeof(iphdr) / sizeof(uint32_t); _ip.ttl = DEFAULT_TTL; + _options_size = 0; } /* Setters */ @@ -101,10 +102,59 @@ void Tins::IP::dest_address(uint32_t ip) { _ip.daddr = ip; } +void Tins::IP::set_option_eol() { + this->set_option(0, IP::CONTROL, IP::IPOPT_END); +} + +void Tins::IP::set_option_noop() { + this->set_option(0, IP::CONTROL, IP::IPOPT_NOOP); +} + +void Tins::IP::set_option_sec(uint8_t* data, uint32_t data_len) { + assert(data_len == 10); + this->set_option(1, IP::CONTROL, IP::IPOPT_SEC, data, data_len); +} + +void Tins::IP::set_option(uint8_t copied, + OptionClass op_class, + OptionNumber number, + uint8_t* data, + uint32_t data_size) { + IpOption option; + option.type.copied = copied; + option.type.op_class = op_class; + option.type.number = number; + uint8_t* buffer(0); + if (data_size) { + /* data must be a valid pointer */ + assert(data); + buffer = new uint8_t[data_size]; + memcpy(buffer, data, data_size); + } + option.optional_data = buffer; + option.optional_data_size = data_size; + _ip_options.push_back(option); + _options_size += 1 + ((buffer)? (data_size) : 0); + uint8_t padding = _options_size & 3; + _padded_options_size = padding? (_options_size - padding + 4) : _options_size; +} + +uint8_t* Tins::IP::IpOption::write(uint8_t* buffer) { + + memcpy(buffer, &type, 1); + buffer += 1; + if (optional_data) { + memcpy(buffer, optional_data, optional_data_size); + buffer += optional_data_size; + } + return buffer; +} + /* Virtual method overriding. */ uint32_t Tins::IP::header_size() const { - return sizeof(iphdr); + return sizeof(iphdr) + _padded_options_size; + } bool Tins::IP::send(PacketSender* sender) { @@ -117,11 +167,11 @@ bool Tins::IP::send(PacketSender* sender) { } void Tins::IP::write_serialization(uint8_t *buffer, uint32_t total_sz) { - uint32_t my_sz = header_size() + trailer_size(); + uint32_t my_sz = header_size(); uint32_t new_flag; assert(total_sz >= my_sz); if(inner_pdu()) { - new_flag = inner_pdu()->flag(); + new_flag = inner_pdu()->flag(); if(new_flag == IPPROTO_IP) new_flag = IPPROTO_IPIP; } @@ -130,7 +180,11 @@ void Tins::IP::write_serialization(uint8_t *buffer, uint32_t total_sz) { flag(new_flag); _ip.protocol = new_flag; _ip.tot_len = total_sz; + _ip.ihl = my_sz / sizeof(uint32_t); memcpy(buffer, &_ip, sizeof(iphdr)); /* IP Options here... */ + buffer += sizeof(iphdr); + for (uint32_t i = 0; i < _ip_options.size(); ++i) + buffer = _ip_options[i].write(buffer); }