/* * Copyright (c) 2017, Matias Fontanini * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "dot11/dot11_base.h" #ifdef TINS_HAVE_DOT11 #include #include #include #include #include "macros.h" #include "exceptions.h" #ifndef _WIN32 #if defined(__FreeBSD_kernel__) || defined(BSD) || defined(__APPLE__) #include #include #else #include #endif #include #include #endif #include "dot11.h" #include "rawpdu.h" #include "rsn_information.h" #include "packet_sender.h" #include "snap.h" #include "memory_helpers.h" using Tins::Memory::InputMemoryStream; using Tins::Memory::OutputMemoryStream; namespace Tins { const Dot11::address_type Dot11::BROADCAST = "ff:ff:ff:ff:ff:ff"; Dot11::Dot11(const address_type& dst_hw_addr) : header_(), options_size_(0) { addr1(dst_hw_addr); } Dot11::Dot11(const dot11_header* /*header_ptr*/) : header_(), options_size_(0) { } Dot11::Dot11(const uint8_t* buffer, uint32_t total_sz) : options_size_(0) { InputMemoryStream stream(buffer, total_sz); stream.read(header_); } void Dot11::write_ext_header(Memory::OutputMemoryStream& /*stream*/) { } void Dot11::write_fixed_parameters(Memory::OutputMemoryStream& /*stream*/) { } void Dot11::parse_tagged_parameters(InputMemoryStream& stream) { if (stream) { while (stream.size() >= 2) { OptionTypes opcode = static_cast(stream.read()); uint8_t length = stream.read(); if (!stream.can_read(length)) { throw malformed_packet(); } add_tagged_option(opcode, length, stream.pointer()); stream.skip(length); } } } void Dot11::add_tagged_option(OptionTypes opt, uint8_t len, const uint8_t* val) { uint32_t opt_size = len + sizeof(uint8_t) * 2; options_.push_back(option((uint8_t)opt, val, val + len)); options_size_ += opt_size; } void Dot11::internal_add_option(const option& opt) { options_size_ += static_cast(opt.data_size() + sizeof(uint8_t) * 2); } bool Dot11::remove_option(OptionTypes type) { options_type::iterator iter = search_option_iterator(type); if (iter == options_.end()) { return false; } options_size_ -= static_cast(iter->data_size() + sizeof(uint8_t) * 2); options_.erase(iter); return true; } void Dot11::add_option(const option& opt) { internal_add_option(opt); options_.push_back(opt); } const Dot11::option* Dot11::search_option(OptionTypes type) const { // Search for the iterator. If we found something, return it, otherwise return nullptr. options_type::const_iterator iter = search_option_iterator(type); return (iter != options_.end()) ? &*iter : 0; } Dot11::options_type::const_iterator Dot11::search_option_iterator(OptionTypes type) const { Internals::option_type_equality_comparator