diff --git a/include/ieee802-11.h b/include/ieee802-11.h index f607b82..bfed646 100644 --- a/include/ieee802-11.h +++ b/include/ieee802-11.h @@ -502,13 +502,29 @@ namespace Tins { */ void add_tagged_option(TaggedOption opt, uint8_t len, const uint8_t *val); + /** + * \brief Looks up a tagged option in the option list. + * \param opt The option identifier. + * \return The option found, or 0 if no such option has been set. + */ + const IEEE802_11_Option *lookup_option(TaggedOption opt) const; + /** * \brief Getter for the PDU's type. * \sa PDU::pdu_type */ PDUType pdu_type() const { return PDU::IEEE802_11; } + + /** + * \brief Allocates an IEEE802_11 PDU from a buffer. + * \param buffer The buffer from which to take the PDU data. + * \param total_sz The total size of the buffer. + * \return The allocated PDU. + */ + static PDU *from_bytes(const uint8_t *buffer, uint32_t total_sz); protected: virtual uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz) { return 0; } + void parse_tagged_parameters(const uint8_t *buffer, uint32_t total_sz); protected: /** * Struct that represents the 802.11 header @@ -559,7 +575,7 @@ namespace Tins { private: IEEE802_11(const ieee80211_header *header_ptr); - + void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent); @@ -613,9 +629,15 @@ namespace Tins { }; protected: - - ManagementFrame(const uint8_t* dst_hw_addr = 0, const uint8_t* src_hw_addr = 0); - ManagementFrame(const std::string& iface, const uint8_t* dst_hw_addr, const uint8_t* src_hw_addr) throw (std::runtime_error); + /** + * \brief Constructor which creates a ManagementFrame object from a buffer and adds all identifiable + * PDUs found in the buffer as children of this one. + * \param buffer The buffer from which this PDU will be constructed. + * \param total_sz The total size of the buffer. + */ + ManagementFrame(const uint8_t *dst_hw_addr = 0, const uint8_t *src_hw_addr = 0); + ManagementFrame(const std::string &iface, const uint8_t *dst_hw_addr, const uint8_t *src_hw_addr) throw (std::runtime_error); + ManagementFrame(const uint8_t *buffer, uint32_t total_sz); struct CapabilityInformation { unsigned int _ess:1; @@ -773,6 +795,15 @@ namespace Tins { */ IEEE802_11_Beacon(const std::string& iface, const uint8_t* dst_hw_addr = 0, const uint8_t* src_hw_addr = 0) throw (std::runtime_error); + /** + * \brief Constructor which creates a IEEE802_11_Beacon object from a buffer and adds + * all identifiable PDUs found in the buffer as children of this one. + * + * \param buffer The buffer from which this PDU will be constructed. + * \param total_sz The total size of the buffer. + */ + IEEE802_11_Beacon(const uint8_t *buffer, uint32_t total_sz); + /** * \brief Getter for the timestamp field. * @@ -1045,10 +1076,18 @@ namespace Tins { /** * \brief Helper method to set the RSN information option. - * + * \param info The RSNInformation structure to be set. */ void rsn_information(const RSNInformation& info); + /** + * \brief Helper method to search for the ESSID of this beacon. + * + * This method returns the essid of this beacon, or an empty + * string if no essid has been set. + */ + std::string essid() const; + /** * \brief Returns the frame's header length. * @@ -1117,18 +1156,15 @@ namespace Tins { * \sa PDU::header_size() */ uint32_t header_size() const; - private: - struct DisassocBody { uint16_t reason_code; }; - DisassocBody _body; - uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz); + - + DisassocBody _body; }; } diff --git a/src/ieee802-11.cpp b/src/ieee802-11.cpp index c3c2122..ad41e9c 100644 --- a/src/ieee802-11.cpp +++ b/src/ieee802-11.cpp @@ -22,6 +22,7 @@ #include #include #include +#include //borrame #ifndef WIN32 #include #include @@ -68,12 +69,11 @@ Tins::IEEE802_11::IEEE802_11(const ieee80211_header *header_ptr) : PDU(ETHERTYPE Tins::IEEE802_11::IEEE802_11(const uint8_t *buffer, uint32_t total_sz) : PDU(ETHERTYPE_IP), _options_size(0) { if(total_sz < sizeof(_header)) - throw std::runtime_error("Not enough size for an RadioTap header in the buffer."); + throw std::runtime_error("Not enough size for an IEEE 802.11 header in the buffer."); std::memcpy(&_header, buffer, sizeof(_header)); buffer += sizeof(_header); total_sz -= sizeof(_header); - // Tagged arguments missing. // subclass specific parsing missing too. } @@ -84,6 +84,21 @@ Tins::IEEE802_11::~IEEE802_11() { } } +void Tins::IEEE802_11::parse_tagged_parameters(const uint8_t *buffer, uint32_t total_sz) { + uint8_t opcode, length; + while(total_sz >= 2) { + opcode = buffer[0]; + length = buffer[1]; + buffer += 2; + total_sz -= 2; + if(length > total_sz) + return; //malformed + add_tagged_option((TaggedOption)opcode, length, buffer); + buffer += length; + total_sz -= length; + } +} + Tins::IEEE802_11::IEEE802_11_Option::IEEE802_11_Option(uint8_t opt, uint8_t len, const uint8_t *val) : option(opt), length(len) { value = new uint8_t[len]; std::memcpy(value, val, len); @@ -95,6 +110,13 @@ void Tins::IEEE802_11::add_tagged_option(TaggedOption opt, uint8_t len, const ui _options_size += opt_size; } +const Tins::IEEE802_11::IEEE802_11_Option *Tins::IEEE802_11::lookup_option(TaggedOption opt) const { + for(std::list::const_iterator it = _options.begin(); it != _options.end(); ++it) + if(it->option == (uint8_t)opt) + return &(*it); + return 0; +} + void Tins::IEEE802_11::protocol(uint8_t new_proto) { this->_header.control.protocol = new_proto; } @@ -216,18 +238,32 @@ void Tins::IEEE802_11::write_serialization(uint8_t *buffer, uint32_t total_sz, c } } +Tins::PDU *Tins::IEEE802_11::from_bytes(const uint8_t *buffer, uint32_t total_sz) { + if(total_sz < sizeof(ieee80211_header)) + throw std::runtime_error("Not enough size for a IEEE 802.11 header in the buffer."); + const ieee80211_header *hdr = (const ieee80211_header*)buffer; + PDU *ret = 0; + if(hdr->control.type == 0 && hdr->control.subtype == 8) + ret = new IEEE802_11_Beacon(buffer, total_sz); + return ret; +} + /* * ManagementFrame */ -Tins::ManagementFrame::ManagementFrame(const uint8_t* dst_hw_addr, const uint8_t* src_hw_addr) : IEEE802_11(dst_hw_addr, src_hw_addr) { +Tins::ManagementFrame::ManagementFrame(const uint8_t *buffer, uint32_t total_sz) : IEEE802_11(buffer, total_sz) { + +} + +Tins::ManagementFrame::ManagementFrame(const uint8_t *dst_hw_addr, const uint8_t *src_hw_addr) : IEEE802_11(dst_hw_addr, src_hw_addr) { this->type(IEEE802_11::MANAGEMENT); } -Tins::ManagementFrame::ManagementFrame(const std::string& iface, - const uint8_t* dst_hw_addr, - const uint8_t* src_hw_addr) throw (std::runtime_error) : IEEE802_11(iface, dst_hw_addr, src_hw_addr) { +Tins::ManagementFrame::ManagementFrame(const std::string &iface, + const uint8_t *dst_hw_addr, + const uint8_t *src_hw_addr) throw (std::runtime_error) : IEEE802_11(iface, dst_hw_addr, src_hw_addr) { this->type(IEEE802_11::MANAGEMENT); } @@ -248,6 +284,17 @@ Tins::IEEE802_11_Beacon::IEEE802_11_Beacon(const std::string& iface, memset(&_body, 0, sizeof(_body)); } +Tins::IEEE802_11_Beacon::IEEE802_11_Beacon(const uint8_t *buffer, uint32_t total_sz) : ManagementFrame(buffer, total_sz) { + buffer += sizeof(ieee80211_header); + total_sz -= sizeof(ieee80211_header); + if(total_sz < sizeof(_body)) + throw std::runtime_error("Not enough size for a IEEE 802.11 beacon header in the buffer."); + memcpy(&_body, buffer, sizeof(_body)); + buffer += sizeof(_body); + total_sz -= sizeof(_body); + parse_tagged_parameters(buffer, total_sz); +} + void Tins::IEEE802_11_Beacon::timestamp(uint64_t new_timestamp) { this->_body.timestamp = new_timestamp; } @@ -283,6 +330,13 @@ void Tins::IEEE802_11_Beacon::rsn_information(const RSNInformation& info) { delete[] buffer; } +std::string Tins::IEEE802_11_Beacon::essid() const { + const IEEE802_11::IEEE802_11_Option *option = lookup_option(SSID); + if(option) + cout << "Length of option: " << (int)option->length << "\n"; + return (option) ? string((const char*)option->value, option->length) : 0; +} + uint32_t Tins::IEEE802_11_Beacon::header_size() const { return IEEE802_11::header_size() + sizeof(BeaconBody); } diff --git a/src/radiotap.cpp b/src/radiotap.cpp index f65e383..4b9d70d 100644 --- a/src/radiotap.cpp +++ b/src/radiotap.cpp @@ -106,6 +106,8 @@ Tins::RadioTap::RadioTap(const uint8_t *buffer, uint32_t total_sz) : PDU(0xff) { buffer += sizeof(_rx_flags); total_sz -= sizeof(_rx_flags); } + if(total_sz) + inner_pdu(IEEE802_11::from_bytes(buffer, total_sz)); } void Tins::RadioTap::version(uint8_t new_version) {